Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
2
2022fall-Compiler_CMinus
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
6
Merge Requests
6
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李晓奇
2022fall-Compiler_CMinus
Commits
0454682c
You need to sign in or sign up before continuing.
Commit
0454682c
authored
Feb 05, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
write reg-alloca for int values
parent
3d814ba8
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
373 additions
and
188 deletions
+373
-188
Reports/5-bonus/report.md
Reports/5-bonus/report.md
+47
-23
include/codegen/codegen.hpp
include/codegen/codegen.hpp
+102
-50
include/codegen/liverange.hpp
include/codegen/liverange.hpp
+14
-7
include/codegen/regalloc.hpp
include/codegen/regalloc.hpp
+18
-4
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+170
-94
src/codegen/liverange.cpp
src/codegen/liverange.cpp
+8
-8
src/codegen/regalloc.cpp
src/codegen/regalloc.cpp
+14
-2
No files found.
Reports/5-bonus/report.md
View file @
0454682c
...
...
@@ -59,38 +59,38 @@ label7: ; preds = %label0
```
llvm
1
.
op1
=
0
in-set:
[
]
out-set:
[
op1
]
in-set:
[
]
out-set:
[
op1
]
2
.
br
label
%label0
in-set:
[
op1
]
out-set:
[
op1
]
in-set:
[
op1
]
out-set:
[
op1
]
3
.
%op2
=
icmp
slt
i32
%op1
,
10
in-set:
[
op1
]
out-set:
[
op2
op1
]
in-set:
[
op1
]
out-set:
[
op2
op1
]
4
.
%op3
=
zext
i1
%op2
to
i32
in-set:
[
op2
op1
]
out-set:
[
op3
op1
]
in-set:
[
op2
op1
]
out-set:
[
op3
op1
]
5
.
%op4
=
icmp
ne
i32
%op3
,
0
in-set:
[
op3
op1
]
out-set:
[
op4
op1
]
in-set:
[
op3
op1
]
out-set:
[
op4
op1
]
6
.
br
i1
%op4
,
label
%label5
,
label
%label7
in-set:
[
op4
op1
]
out-set:
[
op1
]
in-set:
[
op4
op1
]
out-set:
[
op1
]
7
.
call
void
@output
(
i32
%op1
)
in-set:
[
op1
]
out-set:
[
op1
]
in-set:
[
op1
]
out-set:
[
op1
]
8
.
%op6
=
add
i32
%op1
,
1
in-set:
[
op1
]
out-set:
[
op6
]
in-set:
[
op1
]
out-set:
[
op6
]
9
.
op1
=
op6
in-set:
[
op6
]
out-set:
[
op1
]
in-set:
[
op6
]
out-set:
[
op1
]
10
.
br
label
%label0
in-set:
[
op1
]
out-set:
[
op1
]
in-set:
[
op1
]
out-set:
[
op1
]
11
.
ret
i32
0
in-set:
[
]
out-set:
[
]
in-set:
[
]
out-set:
[
]
```
获得活跃区间:编号为i的指令,涉及两个端点:i-1和i,分别对应IN和OUT。由此得到各个变量的活跃区间是:
...
...
@@ -111,4 +111,28 @@ op6: <8, 8>
-
[
Documentations/5-bonus/寄存器分配.md · master · compiler_staff / 2022fall-Compiler_CMinus · GitLab
](
https://cscourse.ustc.edu.cn/vdir/Gitlab/compiler_staff/2022fall-compiler_cminus/-/blob/master/Documentations/5-bonus/%E5%AF%84%E5%AD%98%E5%99%A8%E5%88%86%E9%85%8D.md#poletto
)
i
程序有
`$a`
系列寄存器8个,
`$t`
系列9个,拿出
`$t0`
、
`$t1`
做IR生成汇编过程中的临时寄存器(这个方案仅在cminus下成立),所以可以自由分配的寄存器一共15个。
首先完成对于局部变量的寄存器分配,即全局变量、传参依旧通过栈进行。
程序分配寄存器时会对部分指令做特殊处理,具体如下:
-
`phi`
指令:还原为
`copy-stmt`
,所以寄存器照样分配,如果没分到使用栈内存
-
`alloca`
指令:这里忽略对于
`alloca`
指令的寄存器分配,
`alloca`
仍然使用栈存储,原因如下:
-
对于int|float的
`alloca`
,使用寄存器可以正常进行,只需将相关指令
`load`
和
`store`
分别成赋值即可。
-
但是对于数组的
`alloca`
,使用寄存器就很难模拟了。
即寄存器不能完成
`alloca`
的内存逻辑,同时经过
`mem2reg`
优化过后,不再有局部变量的声明,所以忽略对于
`alloca`
指令的寄存器分配。
-
`cmp`
、
`fcmp`
和
`zext`
指令:不做寄存器分配,也不做栈分配。
这实际是指令选择部分的内容:
因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。
-
`call`
指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖
`call`
指令的程序点。
include/codegen/codegen.hpp
View file @
0454682c
...
...
@@ -9,15 +9,17 @@
#include "Module.h"
#include "Value.h"
#include "liverange.hpp"
#include "
logging
.hpp"
#include "
regalloc
.hpp"
#define __RO_PART__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2
#include <map>
#include <ostream>
#include <vector>
#define ALIGN(x, align) (((
x / align) + (x % align
? 1 : 0)) * align)
#define ALIGN(x, align) (((
(x) / align) + (((x) % align)
? 1 : 0)) * align)
// #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
#define STACK_ALIGN(x) ALIGN(x, 16)
...
...
@@ -27,7 +29,7 @@ using std::vector;
class
CodeGen
{
public:
CodeGen
(
Module
*
m_
)
:
m
(
m_
),
LRA
(
m_
,
phi_map
)
{}
CodeGen
(
Module
*
m_
)
:
m
(
m_
),
LRA
(
m_
,
phi_map
)
,
RA
(
R_USABLE
)
{}
string
print
()
{
string
result
;
...
...
@@ -42,35 +44,41 @@ class CodeGen {
void
run
();
private:
void
IR2assem
(
Instruction
&
,
BasicBlock
&
);
void
IR2assem
(
LoadInst
*
);
void
IR2assem
(
StoreInst
*
);
void
IR2assem
(
ReturnInst
*
);
void
IR2assem
(
GetElementPtrInst
*
);
void
IR2assem
(
CallInst
*
);
void
IR2assem
(
BranchInst
*
);
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
//
// data member
//
std
::
map
<
Value
*
,
unsigned
int
>
off
;
// stack offset to $fp
std
::
map
<
Function
*
,
std
::
map
<
int
,
int
>>
func_arg_off
;
// to $sp
// total space for args, NOTE: not aligned
std
::
map
<
Function
*
,
int
>
func_arg_N
;
std
::
map
<
BasicBlock
*
,
std
::
vector
<
std
::
pair
<
Value
*
,
Value
*>>>
phi_map
;
std
::
map
<
Constant
*
,
std
::
string
>
ROdata
;
unsigned
int
stackN
;
// function local vars and so on
Function
*
cur_func
;
Module
*
m
;
vector
<
string
>
output
;
// register allocation
LRA
::
LiveRangeAnalyzer
LRA
;
RA
::
RegAllocator
RA
;
// some instruction has lvalue, but is stack-allocated,
// we need this variable to track the reg name which has rvalue.
// this variable is maintain by gencopy() and LoadInst.
string
last_reg
;
//
// function member
//
void
stackMemAlloc
();
void
stackMemDealloc
();
// load value `opk` to the specified register
// - for constant number, just load into reg
// - for global variables and pointers from alloca and GEP, read through
// address
// only use register a_id and t_
void
value2reg
(
Value
*
,
int
id
=
0
);
// In the case of register allocation, this function will return the
// allocated register for that value, if the value possesses no register,
// choose from from $t0 or $t1 based on id
__attribute__
((
warn_unused_result
))
string
value2reg
(
Value
*
,
int
i
=
0
);
// load the content in ptr to specified register.
// only use register a_id and t_
void
ptrContent2reg
(
Value
*
,
int
id
=
0
);
void
ptrContent2reg
(
Value
*
,
string
);
void
compute_arg_info
(
Function
*
);
string
bool2branch
(
Instruction
*
);
void
getPhiMap
();
...
...
@@ -80,15 +88,35 @@ class CodeGen {
output
.
push_back
(
"# "
+
print_as_op
(
copy
.
first
,
false
)
+
" = "
+
print_as_op
(
copy
.
second
,
false
));
auto
lvalue
=
static_cast
<
Instruction
*>
(
copy
.
first
);
value2reg
(
copy
.
second
);
back2stack
(
lvalue
);
auto
src_reg
=
value2reg
(
copy
.
second
);
if
(
gencopy
(
lvalue
,
src_reg
)
==
false
)
back2stack
(
lvalue
);
}
}
// if reg-allocation, store to the specific register
// or is stack-allocation, set last_reg for back2stack()
bool
gencopy
(
Value
*
lhs
,
string
rhs_reg
)
{
auto
[
lhs_reg
,
find
]
=
getRegName
(
lhs
);
if
(
not
find
)
{
// wait for back2stack() to store back
last_reg
=
rhs_reg
;
return
false
;
}
auto
is_float
=
lhs
->
get_type
()
->
is_float_type
();
if
(
rhs_reg
!=
lhs_reg
)
{
if
(
is_float
)
output
.
push_back
(
"fmov.s "
+
lhs_reg
+
", "
+
rhs_reg
);
else
output
.
push_back
(
"or "
+
lhs_reg
+
", $zero, "
+
rhs_reg
);
}
return
true
;
}
string
label_in_assem
(
BasicBlock
*
bb
)
{
string
label_in_assem
(
BasicBlock
*
bb
)
const
{
return
cur_func
->
get_name
()
+
bb
->
get_name
().
substr
(
5
);
}
int
typeLen
(
Type
*
type
)
{
int
typeLen
(
Type
*
type
)
const
{
if
(
type
->
is_float_type
())
return
4
;
else
if
(
type
->
is_integer_type
())
{
...
...
@@ -107,19 +135,19 @@ class CodeGen {
}
}
// assert the value needed to store back is in
$a0 or $f0
, according to the
// assert the value needed to store back is in
`last_reg`
, according to the
// value type
void
back2stack
(
Instruction
*
instr
)
{
// std::cerr << instr->print() << std::endl;
auto
type
=
instr
->
get_type
();
string
instr_ir
=
type
->
is_float_type
()
?
"fst"
:
"st"
;
string
suff
=
suffix
(
type
);
string
reg
=
type
->
is_float_type
()
?
"$fa0"
:
"$a0"
;
string
addr
=
"$fp, -"
+
std
::
to_string
(
off
[
instr
]
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", "
+
addr
);
//
string reg = type->is_float_type() ? "$fa0" : "$a0";
string
addr
=
"$fp, -"
+
std
::
to_string
(
off
.
at
(
instr
)
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
last_
reg
+
", "
+
addr
);
}
string
suffix
(
Type
*
type
)
{
string
suffix
(
Type
*
type
)
const
{
int
len
=
typeLen
(
type
);
switch
(
len
)
{
case
1
:
...
...
@@ -134,29 +162,53 @@ class CodeGen {
assert
(
false
&&
"no such suffix"
);
}
bool
no_stack_alloca
(
Instruction
*
instr
)
{
bool
no_stack_alloca
(
Instruction
*
instr
)
const
{
if
(
instr
->
is_void
())
return
true
;
if
(
instr
->
is_fcmp
()
or
instr
->
is_cmp
()
or
instr
->
is_zext
())
return
true
;
if
(
RA
.
get
().
find
(
instr
)
!=
RA
.
get
().
end
())
return
true
;
return
false
;
}
string
tmpregname
(
int
i
,
bool
is_float
)
const
{
assert
(
i
==
0
or
i
==
1
);
return
(
is_float
?
"$ft"
:
"$t"
)
+
to_string
(
i
);
}
std
::
map
<
Value
*
,
unsigned
int
>
off
;
// stack offset to $fp
std
::
map
<
Function
*
,
std
::
map
<
int
,
int
>>
func_arg_off
;
// to $sp
std
::
map
<
Function
*
,
int
>
func_arg_N
;
// total space for args
std
::
map
<
BasicBlock
*
,
std
::
vector
<
std
::
pair
<
Value
*
,
Value
*>>>
phi_map
;
std
::
map
<
Constant
*
,
std
::
string
>
ROdata
;
unsigned
int
stackN
;
// function local vars and so on
Function
*
cur_func
;
static
string
regname
(
int
i
,
bool
is_float
=
false
)
{
string
name
;
if
(
is_float
)
{
assert
(
false
&&
"not implemented!"
);
}
else
{
if
(
1
<=
i
and
i
<=
8
)
name
=
"$a"
+
to_string
(
i
-
1
);
else
if
(
9
<=
i
and
i
<=
R_USABLE
)
name
=
"$t"
+
to_string
(
i
-
9
+
2
);
}
return
name
;
}
Module
*
m
;
vector
<
string
>
output
;
pair
<
string
,
bool
>
getRegName
(
Value
*
,
int
=
0
)
const
;
// register allocation
LRA
::
LiveRangeAnalyzer
LRA
;
void
IR2assem
(
Instruction
&
,
BasicBlock
&
);
void
IR2assem
(
LoadInst
*
);
void
IR2assem
(
StoreInst
*
);
void
IR2assem
(
ReturnInst
*
);
void
IR2assem
(
GetElementPtrInst
*
);
void
IR2assem
(
CallInst
*
);
void
IR2assem
(
BranchInst
*
);
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
};
#endif
include/codegen/liverange.hpp
View file @
0454682c
...
...
@@ -2,6 +2,7 @@
#define LIVERANGE_HPP
#include "Module.h"
#include "Value.h"
#include <iostream>
#include <map>
...
...
@@ -27,7 +28,6 @@ struct Interval {
using
LiveSet
=
set
<
Value
*>
;
using
PhiMap
=
map
<
BasicBlock
*
,
vector
<
pair
<
Value
*
,
Value
*>>>
;
using
LiveInterval
=
pair
<
Interval
,
Value
*>
;
struct
LiveIntervalCMP
{
bool
operator
()(
LiveInterval
const
&
lhs
,
LiveInterval
const
&
rhs
)
const
{
if
(
lhs
.
first
.
i
!=
rhs
.
first
.
i
)
...
...
@@ -36,29 +36,31 @@ struct LiveIntervalCMP {
return
lhs
.
second
<
rhs
.
second
;
}
};
using
LVITS
=
set
<
LiveInterval
,
LiveIntervalCMP
>
;
class
LiveRangeAnalyzer
{
public:
friend
class
CodeGen
;
public:
LiveRangeAnalyzer
(
Module
*
m_
,
PhiMap
&
phi_map_
)
:
m
(
m_
),
phi_map
(
phi_map_
)
{}
LiveRangeAnalyzer
()
=
delete
;
void
run
();
//
void run();
void
run
(
Function
*
);
void
clear
();
void
print
(
Function
*
func
,
bool
printSet
=
true
);
string
print_liveSet
(
const
LiveSet
&
ls
)
{
void
print
(
Function
*
func
,
bool
printSet
=
true
)
const
;
string
print_liveSet
(
const
LiveSet
&
ls
)
const
{
string
s
=
"[ "
;
for
(
auto
k
:
ls
)
s
+=
k
->
get_name
()
+
" "
;
s
+=
"]"
;
return
s
;
}
string
print_interval
(
Interval
&
i
)
{
string
print_interval
(
Interval
&
i
)
const
{
return
"<"
+
to_string
(
i
.
i
)
+
", "
+
to_string
(
i
.
j
)
+
">"
;
}
const
LVITS
&
get
()
{
return
liveIntervals
;
}
private:
Module
*
m
;
...
...
@@ -68,7 +70,8 @@ class LiveRangeAnalyzer {
map
<
Value
*
,
int
>
instr_id
;
map
<
pair
<
Value
*
,
Value
*>
,
int
>
cpstmt_id
;
const
PhiMap
&
phi_map
;
set
<
LiveInterval
,
LiveIntervalCMP
>
liveIntervals
;
LVITS
liveIntervals
;
map
<
Value
*
,
Interval
>
intervalmap
;
void
make_id
(
Function
*
);
void
make_interval
(
Function
*
);
...
...
@@ -86,6 +89,10 @@ class LiveRangeAnalyzer {
// Require: out-set is already set
// Return: the in-set(will not set IN-map)
LiveSet
transferFunction
(
Instruction
*
);
public:
const
decltype
(
instr_id
)
&
get_instr_id
()
{
return
instr_id
;
}
const
decltype
(
intervalmap
)
&
get_interval_map
()
{
return
intervalmap
;
}
};
}
// namespace LRA
#endif
include/codegen/regalloc.hpp
View file @
0454682c
#include "Value.h"
#include "liverange.hpp"
// using std::transform;
#include <iostream>
#include <string>
using
std
::
cout
;
using
std
::
endl
;
using
std
::
to_string
;
using
namespace
LRA
;
namespace
RA
{
#define MAXR 32
bool
no_reg_alloca
(
Value
*
v
);
struct
ActiveCMP
{
bool
operator
()(
LiveInterval
const
&
lhs
,
LiveInterval
const
&
rhs
)
const
{
if
(
lhs
.
first
.
j
!=
rhs
.
first
.
j
)
...
...
@@ -18,15 +27,20 @@ struct ActiveCMP {
class
RegAllocator
{
public:
RegAllocator
(
const
uint
R_
)
:
R
(
R_
),
used
{
false
}
{}
RegAllocator
(
const
uint
R_
)
:
R
(
R_
),
used
{
false
}
{
assert
(
R
<=
MAXR
);
}
RegAllocator
()
=
delete
;
// input set is sorted by increasing start point
void
LinearScan
(
set
<
LiveInterval
>
&
liveints
);
void
LinearScan
(
const
LVITS
&
liveints
);
void
reset
();
const
map
<
Value
*
,
int
>
&
get
()
const
{
return
regmap
;
}
void
print
(
string
(
*
regname
)(
int
))
{
for
(
auto
[
op
,
reg
]
:
regmap
)
cout
<<
op
->
get_name
()
<<
" ~ "
<<
regname
(
reg
)
<<
endl
;
}
private:
const
uint
R
;
bool
used
[
MAXR
];
bool
used
[
MAXR
+
1
];
// index range: 1 ~ R
map
<
Value
*
,
int
>
regmap
;
// sorted by increasing end point
set
<
LiveInterval
,
ActiveCMP
>
active
;
...
...
src/codegen/codegen.cpp
View file @
0454682c
// 局部变量究竟保存在哪里?
// alloca会返回一个指针,这个指针指向一块可用的内存区域
// 这个该如何体现在assemb上?
// NOTE: 参数类型需要额外考虑!
#include "codegen.hpp"
#include "BasicBlock.h"
...
...
@@ -21,6 +15,7 @@
#include <sstream>
#include <string>
#include <sys/types.h>
#include <tuple>
#include <utility>
#include <vector>
...
...
@@ -37,30 +32,23 @@
using
std
::
to_string
;
class
Reg
{
public:
Reg
(
int
index
)
:
id
(
index
)
{}
int
id
;
string
print
()
{
if
(
id
==
0
)
return
"$zero"
;
if
(
id
==
1
)
return
"$ra"
;
if
(
id
==
2
)
return
"$tp"
;
if
(
id
==
3
)
return
"$sp"
;
if
(
4
<=
id
and
id
<=
11
)
return
"$a"
+
to_string
(
id
-
4
);
if
(
12
<=
id
and
id
<=
20
)
return
"$t"
+
to_string
(
id
-
12
);
if
(
id
==
22
)
return
"$fp"
;
assert
(
false
);
pair
<
string
,
bool
>
CodeGen
::
getRegName
(
Value
*
v
,
int
i
)
const
{
assert
(
i
==
0
or
i
==
1
);
bool
find
;
string
name
;
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
auto
regmap
=
RA
.
get
();
if
(
regmap
.
find
(
v
)
==
regmap
.
end
())
{
name
=
tmpregname
(
i
,
is_float
);
find
=
false
;
}
else
{
auto
regid
=
regmap
.
find
(
v
)
->
second
;
name
=
regname
(
regid
,
is_float
);
find
=
true
;
}
};
return
{
name
,
find
};
}
void
CodeGen
::
getPhiMap
()
{
...
...
@@ -95,12 +83,25 @@ CodeGen::run() {
}
// arguments: stack transfer
for
(
auto
&
func
:
m
->
get_functions
())
if
(
not
func
.
is_declaration
())
compute_arg_info
(
&
func
);
//
if (not func.is_declaration())
compute_arg_info
(
&
func
);
// funtions
for
(
auto
&
func
:
m
->
get_functions
())
{
if
(
not
func
.
is_declaration
())
{
LRA
.
run
(
&
func
);
RA
.
LinearScan
(
LRA
.
get
());
std
::
cout
<<
"register map for function: "
<<
func
.
get_name
()
<<
std
::
endl
;
RA
.
print
([](
int
i
)
{
return
regname
(
i
);
});
auto
regmap
=
RA
.
get
();
for
(
auto
[
_
,
op
]
:
LRA
.
get
())
{
if
(
regmap
.
find
(
op
)
==
regmap
.
end
())
std
::
cout
<<
"no reg belongs to "
<<
op
->
get_name
()
<<
std
::
endl
;
}
cur_func
=
&
func
;
output
.
push_back
(
""
);
output
.
push_back
(
".globl "
+
func
.
get_name
());
...
...
@@ -140,37 +141,49 @@ CodeGen::run() {
}
void
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
int
id
)
{
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
string
reg_name
)
{
auto
ele_tp
=
ptr
->
get_type
()
->
get_pointer_element_type
();
assert
(
ele_tp
);
bool
is_float
=
ele_tp
->
is_float_type
();
string
instr_ir
=
(
is_float
?
"fld"
:
"ld"
);
string
reg_name
=
(
is_float
?
"$fa"
:
"$a"
)
+
to_string
(
id
);
string
suff
=
suffix
(
ele_tp
);
auto
[
addr_reg
,
find
]
=
getRegName
(
ptr
,
1
);
if
(
not
find
)
addr_reg
=
"$t1"
;
if
(
dynamic_cast
<
GlobalVariable
*>
(
ptr
))
{
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
ptr
->
get_name
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
output
.
push_back
(
"la.local "
+
addr_reg
+
", "
+
ptr
->
get_name
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
addr_reg
+
", 0"
);
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
ptr
))
{
/* auto alloc_instr = static_cast<AllocaInst *>(ptr);
* string suff = suffix(alloc_instr->get_alloca_type()); */
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
ptr
]
));
to_string
(
off
.
at
(
ptr
)
));
}
else
if
(
dynamic_cast
<
GetElementPtrInst
*>
(
ptr
))
{
// auto GEP_instr = static_cast<GetElementPtrInst *>(ptr);
output
.
push_back
(
"ld.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
ptr
]));
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
if
(
not
find
)
{
output
.
push_back
(
"ld.d "
+
addr_reg
+
", $fp, -"
+
to_string
(
off
.
at
(
ptr
)));
}
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
addr_reg
+
", 0"
);
}
else
assert
(
false
&&
"unknown type"
);
}
void
CodeGen
::
value2reg
(
Value
*
v
,
int
i
d
)
{
string
CodeGen
::
value2reg
(
Value
*
v
,
int
i
)
{
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
auto
reg_name
=
(
is_float
?
"$fa"
:
"$a"
)
+
to_string
(
id
);
string
tmp_ireg
=
"$t0"
;
string
tmp_ireg
=
"$t"
+
to_string
(
i
);
auto
[
reg_name
,
find
]
=
getRegName
(
v
,
i
);
if
(
find
)
return
reg_name
;
// now is the stack allocation case
if
(
dynamic_cast
<
Constant
*>
(
v
))
{
if
(
v
==
ConstantInt
::
get
(
0
,
m
))
return
"$zero"
;
auto
constant
=
static_cast
<
Constant
*>
(
v
);
#ifdef __RO_PART__
if
(
ROdata
.
find
(
constant
)
==
ROdata
.
end
())
...
...
@@ -182,6 +195,7 @@ CodeGen::value2reg(Value *v, int id) {
instr_ir
=
"fld.s"
;
else
assert
(
false
&&
"wait for completion"
);
// bug here: maybe
output
.
push_back
(
"la.local "
+
tmp_ireg
+
", "
+
addr
);
output
.
push_back
(
instr_ir
+
" "
+
reg_name
+
", "
+
tmp_ireg
+
", 0"
);
#else
...
...
@@ -217,7 +231,8 @@ CodeGen::value2reg(Value *v, int id) {
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
v
))
{
// auto alloc_instr = dynamic_cast<AllocaInst *>(v);
// give the stack address
output
.
push_back
(
"addi.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]));
output
.
push_back
(
"addi.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
.
at
(
v
)));
}
else
if
(
dynamic_cast
<
Argument
*>
(
v
))
{
auto
args
=
cur_func
->
get_args
();
int
id
=
1
;
...
...
@@ -226,12 +241,14 @@ CodeGen::value2reg(Value *v, int id) {
break
;
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $fp, "
+
to_string
(
func_arg_off
[
cur_func
][
id
]));
", $fp, "
+
to_string
(
func_arg_off
.
at
(
cur_func
).
at
(
id
)));
}
else
{
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]
));
", $fp, -"
+
to_string
(
off
.
at
(
v
)
));
}
return
reg_name
;
}
void
...
...
@@ -250,20 +267,7 @@ CodeGen::compute_arg_info(Function *func) {
}
for
(
arg_id
=
1
;
arg_id
<=
func
->
get_num_of_args
();
++
arg_id
)
arg_off
[
arg_id
]
=
argN
-
arg_off
[
arg_id
];
func_arg_N
[
func
]
=
STACK_ALIGN
(
argN
);
}
void
CodeGen
::
stackMemDealloc
()
{
// 7: return value should be determined already!
output
.
push_back
(
cur_func
->
get_name
()
+
"_end:"
);
output
.
push_back
(
"# epilog"
);
output
.
push_back
(
"ld.d $ra, $sp, "
+
to_string
(
stackN
-
8
));
output
.
push_back
(
"ld.d $fp, $sp, "
+
to_string
(
stackN
-
16
));
/* output.push_back("ld.d $ra, $fp, -8");
* output.push_back("ld.d $fp, $fp, -16"); */
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
stackN
));
output
.
push_back
(
"jr $ra"
);
func_arg_N
[
func
]
=
argN
;
}
// the addr for opk is: fp - off[opk]
...
...
@@ -294,20 +298,39 @@ CodeGen::stackMemAlloc() {
output
.
push_back
(
"st.d $fp, $sp, "
+
to_string
(
stackN
-
16
));
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
}
void
CodeGen
::
stackMemDealloc
()
{
// 7: return value should be determined already!
output
.
push_back
(
cur_func
->
get_name
()
+
"_end:"
);
output
.
push_back
(
"# epilog"
);
output
.
push_back
(
"ld.d $ra, $sp, "
+
to_string
(
stackN
-
8
));
output
.
push_back
(
"ld.d $fp, $sp, "
+
to_string
(
stackN
-
16
));
/* output.push_back("ld.d $ra, $fp, -8");
* output.push_back("ld.d $fp, $fp, -16"); */
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
stackN
));
output
.
push_back
(
"jr $ra"
);
}
void
CodeGen
::
IR2assem
(
FpToSiInst
*
instr
)
{
assert
(
instr
->
get_operand
(
0
)
->
get_type
()
==
m
->
get_float_type
());
assert
(
instr
->
get_dest_type
()
==
m
->
get_int32_type
());
value2reg
(
instr
->
get_operand
(
0
));
output
.
push_back
(
"ftintrz.w.s $fa0, $fa0"
);
output
.
push_back
(
"movfr2gr.s $a0, $fa0"
);
string
f_reg
=
value2reg
(
instr
->
get_operand
(
0
));
auto
[
i_reg
,
_
]
=
getRegName
(
instr
);
output
.
push_back
(
"ftintrz.w.s "
+
f_reg
+
", "
+
f_reg
);
output
.
push_back
(
"movfr2gr.s "
+
i_reg
+
", "
+
f_reg
);
gencopy
(
instr
,
i_reg
);
}
void
CodeGen
::
IR2assem
(
SiToFpInst
*
instr
)
{
assert
(
instr
->
get_operand
(
0
)
->
get_type
()
==
m
->
get_int32_type
());
assert
(
instr
->
get_dest_type
()
==
m
->
get_float_type
());
output
.
push_back
(
"movgr2fr.w $fa0, $a0"
);
output
.
push_back
(
"ffint.s.w $fa0, $fa0"
);
string
i_reg
=
value2reg
(
instr
->
get_operand
(
0
));
auto
[
f_reg
,
_
]
=
getRegName
(
instr
);
output
.
push_back
(
"movgr2fr.w "
+
f_reg
+
", "
+
i_reg
);
output
.
push_back
(
"ffint.s.w "
+
f_reg
+
", "
+
f_reg
);
gencopy
(
instr
,
f_reg
);
}
string
...
...
@@ -355,10 +378,12 @@ CodeGen::bool2branch(Instruction *instr) {
reverse
=
true
;
break
;
}
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
return
instr_ir
+
(
reverse
?
" $a1, $a0,"
:
" $a0, $a1,"
);
auto
reg1
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
instr
->
get_operand
(
1
),
1
);
return
instr_ir
+
" "
+
(
reverse
?
(
reg2
+
", "
+
reg1
)
:
(
reg1
+
", "
+
reg2
))
+
","
;
}
else
{
assert
(
false
&&
"not implemented"
);
switch
(
fcmp_instr
->
get_cmp_op
())
{
case
FCmpInst
::
EQ
:
instr_ir
=
"fcmp.ceq.s $fcc0"
;
...
...
@@ -381,9 +406,9 @@ CodeGen::bool2branch(Instruction *instr) {
instr_ir
=
"fcmp.cle.s $fcc0"
;
break
;
}
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
output
.
push_back
(
instr_ir
+
", "
+
"$fa0, $fa1"
);
auto
reg1
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
instr
->
get_operand
(
1
),
1
);
output
.
push_back
(
instr_ir
+
", "
+
reg1
+
", "
+
reg2
);
return
(
reverse
?
"bceqz $fcc0,"
:
"bcnez $fcc0,"
);
}
}
...
...
@@ -407,42 +432,79 @@ CodeGen::IR2assem(BranchInst *instr) {
void
CodeGen
::
IR2assem
(
CallInst
*
instr
)
{
auto
func
=
static_cast
<
Function
*>
(
instr
->
get_operand
(
0
));
auto
func_argN
=
func_arg_N
.
at
(
func
);
// analyze the registers that need to be stored
int
cur_i
=
LRA
.
get_instr_id
().
at
(
instr
);
auto
regmap
=
RA
.
get
();
//
int
storeN
=
0
;
vector
<
std
::
tuple
<
Value
*
,
string
,
int
>>
store_record
;
for
(
auto
[
op
,
interval
]
:
LRA
.
get_interval_map
())
{
if
(
RA
::
no_reg_alloca
(
op
))
continue
;
if
(
interval
.
i
<=
cur_i
and
cur_i
<=
interval
.
j
)
{
int
tplen
=
typeLen
(
op
->
get_type
());
storeN
=
ALIGN
(
storeN
,
tplen
)
+
tplen
;
auto
name
=
regname
(
regmap
.
at
(
op
),
op
->
get_type
()
->
is_float_type
());
store_record
.
push_back
({
op
,
name
,
storeN
});
}
}
int
totalN
=
STACK_ALIGN
(
ALIGN
(
storeN
,
8
)
+
func_argN
);
// cout << "debug: " << STACK_ALIGN(12) << endl;
// stack space allocation
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
func_arg_N
[
func
]
));
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
totalN
));
string
instr_ir
,
suff
,
reg
;
// place the reserved regs
for
(
auto
[
op
,
reg
,
off
]
:
store_record
)
{
instr_ir
=
(
op
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
op
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
totalN
-
off
));
}
// place the arguments
for
(
int
i
=
1
;
i
<
instr
->
get_num_operand
();
i
++
)
{
auto
arg
=
instr
->
get_operand
(
i
);
// auto tplen = typeLen(arg->get_type());
instr_ir
=
(
arg
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
arg
->
get_type
());
reg
=
(
arg
->
get_type
()
->
is_float_type
()
?
"$fa0"
:
"$a0"
);
value2reg
(
arg
);
reg
=
value2reg
(
arg
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
func_arg_off
[
func
][
i
]
));
to_string
(
func_arg_off
.
at
(
func
).
at
(
i
)
));
}
output
.
push_back
(
"bl "
+
func
->
get_name
());
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
func_arg_N
[
func
]));
// bug here: maybe
gencopy
(
instr
,
instr
->
get_type
()
->
is_float_type
()
?
"$fa0"
:
"$a0"
);
// restore the reserved regs
for
(
auto
[
op
,
reg
,
off
]
:
store_record
)
{
instr_ir
=
(
op
->
get_type
()
->
is_float_type
()
?
"fld"
:
"ld"
);
suff
=
suffix
(
op
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
totalN
-
off
));
}
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
totalN
));
// output.push_back("addi.d $fp, $sp, " + to_string(stackN));
}
void
CodeGen
::
IR2assem
(
BinaryInst
*
instr
)
{
auto
is_float
=
instr
->
get_type
()
->
is_float_type
(
);
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
auto
reg1
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
instr
->
get_operand
(
1
),
1
);
auto
[
reg
,
_
]
=
getRegName
(
instr
);
string
instr_ir
=
instr
->
get_instr_op_name
();
if
(
instr_ir
==
"sdiv"
)
instr_ir
=
"div"
;
string
suff
=
suffix
(
instr
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
(
is_float
?
" $fa0, $fa0, $fa1"
:
" $a0, $a0, $a1"
)
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", "
+
reg1
+
", "
+
reg2
);
gencopy
(
instr
,
reg
);
}
void
CodeGen
::
IR2assem
(
GetElementPtrInst
*
instr
)
{
value2reg
(
instr
->
get_operand
(
0
),
0
);
assert
(
instr
->
get_num_operand
()
<=
3
);
auto
addr_reg
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
assert
(
addr_reg
==
"$t0"
);
Type
*
type
=
instr
->
get_operand
(
0
)
->
get_type
();
for
(
int
i
=
1
;
i
<
instr
->
get_num_operand
();
i
++
)
{
int
size
;
...
...
@@ -454,38 +516,52 @@ CodeGen::IR2assem(GetElementPtrInst *instr) {
type
=
type
->
get_pointer_element_type
();
}
else
assert
(
false
&&
"GEP translation error"
);
value2reg
(
instr
->
get_operand
(
i
),
1
);
value2reg
(
ConstantInt
::
get
(
size
,
m
),
2
);
output
.
push_back
(
"mul.w $a1, $a1, $a2"
);
output
.
push_back
(
"add.d $a0, $a0, $a1"
);
if
(
size
!=
4
)
{
// getelementptr [5 x i32], [5 x i32]* @w, i32 0, i32 4
assert
(
instr
->
get_operand
(
i
)
==
ConstantInt
::
get
(
0
,
m
)
&&
"cminus support only 1 dimension array, so first offset is "
"must 0"
);
continue
;
}
auto
off_reg
=
value2reg
(
instr
->
get_operand
(
i
),
1
);
// value2reg(ConstantInt::get(size, m), 2);
output
.
push_back
(
"slli.d "
+
off_reg
+
", "
+
off_reg
+
", 2"
);
output
.
push_back
(
"add.d "
+
addr_reg
+
", "
+
addr_reg
+
", "
+
off_reg
);
}
gencopy
(
instr
,
addr_reg
);
}
void
CodeGen
::
IR2assem
(
LoadInst
*
instr
)
{
// move the address to a0
ptrContent2reg
(
instr
->
get_lval
());
assert
(
instr
->
get_type
()
==
instr
->
get_load_type
())
;
auto
[
reg
,
find
]
=
getRegName
(
instr
);
ptrContent2reg
(
instr
->
get_lval
()
,
reg
);
if
(
not
find
)
// this if is just for logically clear
last_reg
=
reg
;
}
void
CodeGen
::
IR2assem
(
StoreInst
*
instr
)
{
value2reg
(
instr
->
get_rval
(),
0
);
value2reg
(
instr
->
get_lval
(),
1
);
auto
reg1
=
value2reg
(
instr
->
get_rval
(),
0
);
auto
reg2
=
value2reg
(
instr
->
get_lval
(),
1
);
bool
is_float
=
instr
->
get_rval
()
->
get_type
()
->
is_float_type
();
string
instr_ir
=
(
is_float
?
"fst"
:
"st"
);
string
suff
=
suffix
(
instr
->
get_rval
()
->
get_type
());
string
reg
=
(
is_float
?
"$fa0"
:
"$a0"
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $a1, 0"
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg1
+
", "
+
reg2
+
", 0"
);
}
void
CodeGen
::
IR2assem
(
ReturnInst
*
instr
)
{
if
(
not
instr
->
is_void_ret
())
{
auto
value
=
instr
->
get_operand
(
0
);
value2reg
(
value
);
auto
is_float
=
value
->
get_type
()
->
is_float_type
();
auto
reg
=
value2reg
(
value
);
if
(
is_float
and
reg
!=
"$fa0"
)
output
.
push_back
(
"fmov.s $fa0, "
+
reg
);
else
if
(
not
is_float
and
reg
!=
"$a0"
)
output
.
push_back
(
"or $a0, $zero "
+
reg
);
}
output
.
push_back
(
"b "
+
cur_func
->
get_name
()
+
"_end"
);
}
...
...
src/codegen/liverange.cpp
View file @
0454682c
...
...
@@ -11,6 +11,7 @@ LiveRangeAnalyzer::clear() {
OUT
.
clear
();
instr_id
.
clear
();
cpstmt_id
.
clear
();
intervalmap
.
clear
();
liveIntervals
.
clear
();
}
...
...
@@ -133,24 +134,23 @@ LiveRangeAnalyzer::run(Function *func) {
void
LiveRangeAnalyzer
::
make_interval
(
Function
*
)
{
map
<
Value
*
,
Interval
>
liverange
;
for
(
int
time
=
1
;
time
<=
ir_cnt
;
++
time
)
{
for
(
auto
op
:
IN
.
at
(
time
))
{
auto
&
interval
=
liverange
[
op
];
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
interval
.
i
=
time
-
1
;
else
interval
.
j
=
time
-
1
;
}
for
(
auto
op
:
OUT
.
at
(
time
))
{
auto
&
interval
=
liverange
[
op
];
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
interval
.
i
=
time
;
else
interval
.
j
=
time
;
}
}
for
(
auto
[
op
,
interval
]
:
liverange
)
for
(
auto
[
op
,
interval
]
:
intervalmap
)
liveIntervals
.
insert
({
interval
,
op
});
}
...
...
@@ -188,7 +188,7 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) {
}
void
LiveRangeAnalyzer
::
print
(
Function
*
func
,
bool
printSet
)
{
// for debug
LiveRangeAnalyzer
::
print
(
Function
*
func
,
bool
printSet
)
const
{
// for debug
cout
<<
"Function "
<<
func
->
get_name
()
<<
endl
;
for
(
auto
&
bb
:
func
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
{
...
...
@@ -200,7 +200,7 @@ LiveRangeAnalyzer::print(Function *func, bool printSet) { // for debug
for
(
auto
pr
:
phi_map
.
find
(
&
bb
)
->
second
)
{
auto
[
lv
,
rv
]
=
pr
;
auto
idx
=
cpstmt_id
.
at
(
pr
);
cout
<<
cpstmt_id
[
pr
]
<<
". "
<<
lv
->
get_name
()
<<
" = "
cout
<<
cpstmt_id
.
at
(
pr
)
<<
". "
<<
lv
->
get_name
()
<<
" = "
<<
(
rv
->
get_name
()
==
""
?
rv
->
print
()
:
rv
->
get_name
())
<<
endl
;
...
...
@@ -213,8 +213,8 @@ LiveRangeAnalyzer::print(Function *func, bool printSet) { // for debug
}
}
// normal ir
cout
<<
instr_id
[
&
instr
]
<<
". "
<<
instr
.
print
()
<<
" # "
<<
&
instr
<<
endl
;
cout
<<
instr_id
.
at
(
&
instr
)
<<
". "
<<
instr
.
print
()
<<
" # "
<<
&
instr
<<
endl
;
if
(
not
printSet
)
continue
;
auto
idx
=
instr_id
.
at
(
&
instr
);
...
...
src/codegen/regalloc.cpp
View file @
0454682c
#include "regalloc.hpp"
#include "Instruction.h"
#include "liverange.hpp"
#include <algorithm>
using
std
::
for_each
;
using
namespace
RA
;
bool
RA
::
no_reg_alloca
(
Value
*
v
)
{
auto
instr
=
static_cast
<
Instruction
*>
(
v
);
return
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
()
or
instr
->
is_zext
();
}
void
RegAllocator
::
reset
()
{
regmap
.
clear
();
active
.
clear
();
for_each
(
used
,
used
+
R
,
[](
bool
&
u
)
{
u
=
false
;
});
for_each
(
used
,
used
+
R
+
1
,
[](
bool
&
u
)
{
u
=
false
;
});
}
void
RegAllocator
::
LinearScan
(
set
<
LiveInterval
>
&
liveints
)
{
RegAllocator
::
LinearScan
(
const
LVITS
&
liveints
)
{
reset
();
int
reg
;
for
(
auto
liveint
:
liveints
)
{
if
(
no_reg_alloca
(
liveint
.
second
))
continue
;
ExpireOldIntervals
(
liveint
);
if
(
active
.
size
()
==
R
)
SpillAtInterval
(
liveint
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment