Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
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
0
Merge Requests
0
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
b4870a73
Commit
b4870a73
authored
Feb 05, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
have too many bugs now, use lab3 testcases to debug
parent
0454682c
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
234 additions
and
83 deletions
+234
-83
Reports/5-bonus/report.md
Reports/5-bonus/report.md
+25
-1
include/codegen/codegen.hpp
include/codegen/codegen.hpp
+13
-5
include/codegen/liverange.hpp
include/codegen/liverange.hpp
+1
-1
include/codegen/regalloc.hpp
include/codegen/regalloc.hpp
+15
-7
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+68
-55
src/codegen/liverange.cpp
src/codegen/liverange.cpp
+11
-7
src/codegen/regalloc.cpp
src/codegen/regalloc.cpp
+52
-7
tests/5-bonus/testcases/16-argparse.cminus
tests/5-bonus/testcases/16-argparse.cminus
+29
-0
tests/5-bonus/testcases/16-argparse.in
tests/5-bonus/testcases/16-argparse.in
+10
-0
tests/5-bonus/testcases/16-argparse.out
tests/5-bonus/testcases/16-argparse.out
+10
-0
No files found.
Reports/5-bonus/report.md
View file @
b4870a73
...
...
@@ -113,7 +113,7 @@ op6: <8, 8>
程序有
`$a`
系列寄存器8个,
`$t`
系列9个,拿出
`$t0`
、
`$t1`
做IR生成汇编过程中的临时寄存器(这个方案仅在cminus下成立),所以可以自由分配的寄存器一共15个。
首先完成对于局部变量
的寄存器分配,即全局变量、传参依旧通过栈进行
。
首先完成对于局部变量
和参数的整形寄存器分配
。
程序分配寄存器时会对部分指令做特殊处理,具体如下:
...
...
@@ -135,4 +135,28 @@ op6: <8, 8>
-
`call`
指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖
`call`
指令的程序点。
参数传递:固定为前8个参数分配
`$a0`
\~
`$a7`
,超过8个使用栈传递。
#### 4. 局部优化
-
基于跳转的bool变量翻译。
-
GEP取值的优化:两个0的情况
-
常量取值的优化
-
#### 5. 测试样例
功能正确性由以下几部分测试样例作为证明:
-
`/tests/5-bonus/testcases`
-
`tests/3-ir-gen/testcases`
而性能主要向gcc看齐,主要测试样例为
-
`tests/4-ir-opt/testcases/GVN/performance`
-
include/codegen/codegen.hpp
View file @
b4870a73
...
...
@@ -11,9 +11,13 @@
#include "liverange.hpp"
#include "regalloc.hpp"
#include <string>
#define __PRINT_ORI__
#define __RO_PART__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2
#define ARG_R 8
#include <map>
#include <ostream>
...
...
@@ -29,7 +33,7 @@ using std::vector;
class
CodeGen
{
public:
CodeGen
(
Module
*
m_
)
:
m
(
m_
),
LRA
(
m_
,
phi_map
),
RA
(
R_USABLE
)
{}
CodeGen
(
Module
*
m_
)
:
m
(
m_
),
LRA
(
m_
,
phi_map
),
RA
(
R_USABLE
,
ARG_R
)
{}
string
print
()
{
string
result
;
...
...
@@ -74,9 +78,8 @@ class CodeGen {
void
stackMemDealloc
();
// 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
);
// choose from from $t0 or $t1 based on id, or the input string(not "")
__attribute__
((
warn_unused_result
))
string
value2reg
(
Value
*
,
int
i
=
0
,
string
=
""
);
// load the content in ptr to specified register.
void
ptrContent2reg
(
Value
*
,
string
);
void
compute_arg_info
(
Function
*
);
...
...
@@ -104,13 +107,16 @@ class CodeGen {
return
false
;
}
auto
is_float
=
lhs
->
get_type
()
->
is_float_type
();
gencopy
(
lhs_reg
,
rhs_reg
,
is_float
);
return
true
;
}
void
gencopy
(
string
lhs_reg
,
string
rhs_reg
,
bool
is_float
=
false
)
{
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
)
const
{
...
...
@@ -186,6 +192,8 @@ class CodeGen {
name
=
"$a"
+
to_string
(
i
-
1
);
else
if
(
9
<=
i
and
i
<=
R_USABLE
)
name
=
"$t"
+
to_string
(
i
-
9
+
2
);
else
name
=
"WRONG_REG"
+
to_string
(
i
);
}
return
name
;
}
...
...
include/codegen/liverange.hpp
View file @
b4870a73
...
...
@@ -49,7 +49,7 @@ class LiveRangeAnalyzer {
// void run();
void
run
(
Function
*
);
void
clear
();
void
print
(
Function
*
func
,
bool
printSet
=
tru
e
)
const
;
void
print
(
Function
*
func
,
bool
printSet
=
false
,
bool
printInt
=
fals
e
)
const
;
string
print_liveSet
(
const
LiveSet
&
ls
)
const
{
string
s
=
"[ "
;
for
(
auto
k
:
ls
)
...
...
include/codegen/regalloc.hpp
View file @
b4870a73
#ifndef REGALLOCA_HPP
#define REGALLOCA_HPP
#include "Function.h"
#include "Value.h"
#include "liverange.hpp"
...
...
@@ -6,16 +9,12 @@
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
)
...
...
@@ -27,11 +26,14 @@ struct ActiveCMP {
class
RegAllocator
{
public:
RegAllocator
(
const
uint
R_
)
:
R
(
R_
),
used
{
false
}
{
assert
(
R
<=
MAXR
);
}
RegAllocator
(
const
uint
R_
,
const
uint
ARG_R_
)
:
R
(
R_
),
ARG_MAX_R
(
ARG_R_
),
used
{
false
}
{
assert
(
R
<=
MAXR
);
}
RegAllocator
()
=
delete
;
bool
no_reg_alloca
(
Value
*
v
)
const
;
// input set is sorted by increasing start point
void
LinearScan
(
const
LVITS
&
liveints
);
void
reset
();
void
LinearScan
(
const
LVITS
&
,
Function
*
);
const
map
<
Value
*
,
int
>
&
get
()
const
{
return
regmap
;
}
void
print
(
string
(
*
regname
)(
int
))
{
for
(
auto
[
op
,
reg
]
:
regmap
)
...
...
@@ -39,13 +41,19 @@ class RegAllocator {
}
private:
Function
*
cur_func
;
const
uint
R
;
const
uint
ARG_MAX_R
;
bool
used
[
MAXR
+
1
];
// index range: 1 ~ R
map
<
Value
*
,
int
>
regmap
;
// sorted by increasing end point
set
<
LiveInterval
,
ActiveCMP
>
active
;
void
reset
(
Function
*
=
nullptr
);
int
ReserveForArg
(
const
LVITS
&
);
void
ExpireOldIntervals
(
LiveInterval
);
void
SpillAtInterval
(
LiveInterval
);
};
}
// namespace RA
#endif
src/codegen/codegen.cpp
View file @
b4870a73
...
...
@@ -12,6 +12,7 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <ostream>
#include <sstream>
#include <string>
#include <sys/types.h>
...
...
@@ -19,6 +20,8 @@
#include <utility>
#include <vector>
#define CONST_0 ConstantInt::get(0, m)
// $r0 $zero constant 0
// $r1 $ra return address
// $r2 $tp thread pointer
...
...
@@ -31,6 +34,7 @@
// $r23 - $r31 $s0 - $s8 static
using
std
::
to_string
;
using
std
::
operator
""
s
;
pair
<
string
,
bool
>
CodeGen
::
getRegName
(
Value
*
v
,
int
i
)
const
{
...
...
@@ -89,7 +93,7 @@ CodeGen::run() {
for
(
auto
&
func
:
m
->
get_functions
())
{
if
(
not
func
.
is_declaration
())
{
LRA
.
run
(
&
func
);
RA
.
LinearScan
(
LRA
.
get
());
RA
.
LinearScan
(
LRA
.
get
()
,
&
func
);
std
::
cout
<<
"register map for function: "
<<
func
.
get_name
()
<<
std
::
endl
;
...
...
@@ -149,8 +153,8 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) {
string
suff
=
suffix
(
ele_tp
);
auto
[
addr_reg
,
find
]
=
getRegName
(
ptr
,
1
);
if
(
not
find
)
addr_reg
=
"$t1"
;
/*
if (not find)
* addr_reg = "$t1"; */
if
(
dynamic_cast
<
GlobalVariable
*>
(
ptr
))
{
output
.
push_back
(
"la.local "
+
addr_reg
+
", "
+
ptr
->
get_name
());
...
...
@@ -174,15 +178,17 @@ CodeGen::ptrContent2reg(Value *ptr, string reg_name) {
}
string
CodeGen
::
value2reg
(
Value
*
v
,
int
i
)
{
CodeGen
::
value2reg
(
Value
*
v
,
int
i
,
string
recommend
)
{
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
string
tmp_ireg
=
"$t"
+
to_string
(
i
);
auto
[
reg_name
,
find
]
=
getRegName
(
v
,
i
);
if
(
find
)
return
reg_name
;
else
if
(
recommend
!=
""
)
reg_name
=
recommend
;
// now is the stack allocation case
if
(
dynamic_cast
<
Constant
*>
(
v
))
{
if
(
v
==
C
onstantInt
::
get
(
0
,
m
)
)
if
(
v
==
C
ONST_0
)
return
"$zero"
;
auto
constant
=
static_cast
<
Constant
*>
(
v
);
#ifdef __RO_PART__
...
...
@@ -239,10 +245,14 @@ CodeGen::value2reg(Value *v, int i) {
for
(
auto
iter
=
args
.
begin
();
id
<=
args
.
size
();
++
iter
,
++
id
)
if
(
*
iter
==
v
)
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
.
at
(
cur_func
).
at
(
id
)));
if
(
id
<=
ARG_R
)
return
regname
(
ARG_R
);
else
{
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $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
+
...
...
@@ -258,15 +268,19 @@ CodeGen::compute_arg_info(Function *func) {
auto
func_tp
=
func
->
get_function_type
();
auto
&
arg_off
=
func_arg_off
[
func
];
int
argN
=
0
,
arg_id
=
func
->
get_num_of_args
();
// only alloca stack memory for argk, k >= 8;
auto
rend
=
func_tp
->
param_begin
();
for
(
int
i
=
0
;
i
<
ARG_R
and
rend
!=
func_tp
->
param_end
();
++
i
,
++
rend
)
;
// reserve space
for
(
auto
iter
=
func_tp
->
param_end
();
iter
!=
func_tp
->
param_begin
()
;)
{
for
(
auto
iter
=
func_tp
->
param_end
();
iter
!=
rend
;)
{
--
iter
;
auto
tplen
=
typeLen
(
*
iter
);
argN
=
ALIGN
(
argN
,
tplen
)
+
tplen
;
arg_off
[
arg_id
--
]
=
argN
;
}
for
(
arg_id
=
1
;
arg_id
<=
func
->
get_num_of_args
();
++
arg_id
)
arg_off
[
arg_id
]
=
argN
-
arg_off
[
arg_id
]
;
for
(
arg_id
=
ARG_R
+
1
;
arg_id
<=
func
->
get_num_of_args
();
++
arg_id
)
arg_off
.
at
(
arg_id
)
=
argN
-
arg_off
.
at
(
arg_id
)
;
func_arg_N
[
func
]
=
argN
;
}
...
...
@@ -349,7 +363,7 @@ CodeGen::bool2branch(Instruction *instr) {
break
;
case
CmpInst
::
NE
:
{
instr_ir
=
"bne"
;
if
(
instr
->
get_operand
(
1
)
==
C
onstantInt
::
get
(
0
,
m
)
and
if
(
instr
->
get_operand
(
1
)
==
C
ONST_0
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
->
is_zext
())
{
// something like:
...
...
@@ -440,7 +454,7 @@ CodeGen::IR2assem(CallInst *instr) {
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
)
)
if
(
RA
.
no_reg_alloca
(
op
)
or
regmap
.
at
(
op
)
==
1
)
continue
;
if
(
interval
.
i
<=
cur_i
and
cur_i
<=
interval
.
j
)
{
int
tplen
=
typeLen
(
op
->
get_type
());
...
...
@@ -452,8 +466,9 @@ CodeGen::IR2assem(CallInst *instr) {
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
(
totalN
));
string
instr_ir
,
suff
,
reg
;
if
(
totalN
)
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
totalN
));
string
instr_ir
,
suff
,
v_reg
;
// place the reserved regs
for
(
auto
[
op
,
reg
,
off
]
:
store_record
)
{
instr_ir
=
(
op
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
...
...
@@ -461,15 +476,18 @@ CodeGen::IR2assem(CallInst *instr) {
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
=
value2reg
(
arg
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
func_arg_off
.
at
(
func
).
at
(
i
)));
// pass arguments
for
(
int
arg_i
=
1
;
arg_i
<
instr
->
get_num_operand
();
arg_i
++
)
{
auto
arg_value
=
instr
->
get_operand
(
arg_i
);
v_reg
=
value2reg
(
arg_value
);
if
(
arg_i
<=
ARG_R
)
{
// pass by register
gencopy
(
regname
(
arg_i
),
v_reg
);
}
else
{
// pass by stack
instr_ir
=
(
arg_value
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
arg_value
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
v_reg
+
", $sp, "
+
to_string
(
func_arg_off
.
at
(
func
).
at
(
arg_i
)));
}
}
output
.
push_back
(
"bl "
+
func
->
get_name
());
// bug here: maybe
...
...
@@ -481,8 +499,8 @@ CodeGen::IR2assem(CallInst *instr) {
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(stack
N));
if
(
totalN
)
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
total
N
));
}
void
...
...
@@ -502,34 +520,27 @@ CodeGen::IR2assem(BinaryInst *instr) {
void
CodeGen
::
IR2assem
(
GetElementPtrInst
*
instr
)
{
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
;
if
(
type
->
is_array_type
())
{
size
=
type
->
get_array_element_type
()
->
get_size
();
type
=
type
->
get_array_element_type
();
}
else
if
(
type
->
is_pointer_type
())
{
size
=
type
->
get_size
();
type
=
type
->
get_pointer_element_type
();
}
else
assert
(
false
&&
"GEP translation error"
);
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
);
auto
[
dest_reg
,
_
]
=
getRegName
(
instr
);
auto
off
=
instr
->
get_operand
(
instr
->
get_num_operand
()
==
3
?
2
:
1
);
if
(
off
==
CONST_0
)
{
auto
final_reg
=
value2reg
(
instr
->
get_operand
(
0
),
0
,
dest_reg
);
gencopy
(
instr
,
final_reg
);
return
;
}
if
(
instr
->
get_num_operand
()
==
3
)
{
// %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32 %op41
assert
(
instr
->
get_operand
(
1
)
==
CONST_0
);
}
else
{
// %op38 = getelementptr i32, i32* %arg1, i32 %op34
}
gencopy
(
instr
,
addr_reg
);
auto
addr_reg
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
off_reg
=
value2reg
(
off
,
1
);
auto
tmp_reg
=
"$t1"
s
;
output
.
push_back
(
"slli.d "
+
tmp_reg
+
", "
+
off_reg
+
", 2"
);
output
.
push_back
(
"add.d "
+
dest_reg
+
", "
+
addr_reg
+
", "
+
tmp_reg
);
gencopy
(
instr
,
dest_reg
);
}
void
...
...
@@ -559,7 +570,7 @@ CodeGen::IR2assem(ReturnInst *instr) {
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
(
"or $a0, $zero
,
"
+
reg
);
}
output
.
push_back
(
"b "
+
cur_func
->
get_name
()
+
"_end"
);
...
...
@@ -569,7 +580,9 @@ void
CodeGen
::
IR2assem
(
Instruction
&
instr
,
BasicBlock
&
bb
)
{
if
(
instr
.
is_br
()
or
instr
.
is_ret
())
copystmt
(
&
bb
);
#ifdef __PRINT_ORI__
output
.
push_back
(
"# "
+
instr
.
print
());
#endif
switch
(
instr
.
get_instr_type
())
{
case
Instruction
::
ret
:
IR2assem
(
static_cast
<
ReturnInst
*>
(
&
instr
));
...
...
src/codegen/liverange.cpp
View file @
b4870a73
#include "liverange.hpp"
#include "Function.h"
using
std
::
cout
;
using
std
::
endl
;
using
namespace
LRA
;
...
...
@@ -58,9 +60,6 @@ void
LiveRangeAnalyzer
::
run
(
Function
*
func
)
{
clear
();
make_id
(
func
);
#ifdef __LRA_PRINT__
print
(
func
,
false
);
#endif
bool
cont
=
true
;
while
(
cont
)
{
cont
=
false
;
...
...
@@ -128,7 +127,7 @@ LiveRangeAnalyzer::run(Function *func) {
make_interval
(
func
);
#ifdef __LRA_PRINT__
print
(
func
);
print
(
func
,
false
,
true
);
#endif
}
...
...
@@ -166,12 +165,15 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) {
// - function
// - Constant
// - instruction
// - argument
// - argument
*
// - BasicBlock
auto
ins
=
dynamic_cast
<
Instruction
*>
(
op
);
auto
arg
=
dynamic_cast
<
Argument
*>
(
op
);
if
(
ins
)
{
assert
(
not
ins
->
is_void
()
&&
"instr as op should not be void"
);
use
.
insert
(
op
);
}
else
if
(
arg
)
{
use
.
insert
(
op
);
}
}
// in = use + (out - def)
...
...
@@ -188,7 +190,9 @@ LiveRangeAnalyzer::transferFunction(Instruction *instr) {
}
void
LiveRangeAnalyzer
::
print
(
Function
*
func
,
bool
printSet
)
const
{
// for debug
LiveRangeAnalyzer
::
print
(
Function
*
func
,
bool
printSet
,
bool
printInt
)
const
{
// for debug
cout
<<
"Function "
<<
func
->
get_name
()
<<
endl
;
for
(
auto
&
bb
:
func
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
{
...
...
@@ -225,7 +229,7 @@ LiveRangeAnalyzer::print(Function *func, bool printSet) const { // for debug
}
}
if
(
print
Se
t
)
{
if
(
print
In
t
)
{
for
(
auto
[
interval
,
op
]
:
liveIntervals
)
cout
<<
op
->
get_name
()
<<
": "
<<
print_interval
(
interval
)
<<
endl
;
}
...
...
src/codegen/regalloc.cpp
View file @
b4870a73
#include "regalloc.hpp"
#include "Function.h"
#include "Instruction.h"
#include "liverange.hpp"
...
...
@@ -9,25 +10,67 @@ using std::for_each;
using
namespace
RA
;
int
get_arg_id
(
Argument
*
arg
)
{
auto
args
=
arg
->
get_parent
()
->
get_args
();
int
id
=
1
;
for
(
auto
a
:
args
)
{
if
(
a
==
arg
)
break
;
++
id
;
}
return
id
;
}
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
();
RegAllocator
::
no_reg_alloca
(
Value
*
v
)
const
{
auto
instr
=
dynamic_cast
<
Instruction
*>
(
v
);
auto
arg
=
dynamic_cast
<
Argument
*>
(
v
);
if
(
instr
)
return
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
()
or
instr
->
is_zext
();
if
(
arg
)
{
return
get_arg_id
(
arg
)
>
ARG_MAX_R
;
}
else
assert
(
false
&&
"only instruction and argument's LiveInterval exits"
);
}
void
RegAllocator
::
reset
()
{
RegAllocator
::
reset
(
Function
*
func
)
{
cur_func
=
func
;
regmap
.
clear
();
active
.
clear
();
for_each
(
used
,
used
+
R
+
1
,
[](
bool
&
u
)
{
u
=
false
;
});
}
int
RegAllocator
::
ReserveForArg
(
const
LVITS
&
Liveints
)
{
auto
args
=
cur_func
->
get_args
();
auto
it_int
=
Liveints
.
begin
();
auto
it_arg
=
args
.
begin
();
int
reg
;
for
(
reg
=
1
;
reg
<=
args
.
size
()
and
reg
<=
ARG_MAX_R
;
++
reg
)
{
auto
arg
=
*
it_arg
;
auto
liveint
=
*
it_int
;
assert
(
arg
==
liveint
.
second
&&
"arg should be in order in liveints"
);
used
[
reg
]
=
true
;
regmap
[
arg
]
=
reg
;
active
.
insert
(
liveint
);
++
it_arg
,
++
it_int
;
}
return
reg
;
}
void
RegAllocator
::
LinearScan
(
const
LVITS
&
liveints
)
{
reset
();
RegAllocator
::
LinearScan
(
const
LVITS
&
liveints
,
Function
*
func
)
{
reset
(
func
);
ReserveForArg
(
liveints
);
int
reg
;
for
(
auto
liveint
:
liveints
)
{
if
(
dynamic_cast
<
Argument
*>
(
liveint
.
second
))
{
continue
;
}
if
(
no_reg_alloca
(
liveint
.
second
))
continue
;
ExpireOldIntervals
(
liveint
);
...
...
@@ -54,6 +97,8 @@ RegAllocator::ExpireOldIntervals(LiveInterval liveint) {
void
RegAllocator
::
SpillAtInterval
(
LiveInterval
liveint
)
{
auto
spill
=
*
active
.
rbegin
();
if
(
dynamic_cast
<
Argument
*>
(
spill
.
second
))
return
;
if
(
spill
.
first
.
j
>
liveint
.
first
.
j
)
{
// cancel reg allocation for spill
regmap
[
liveint
.
second
]
=
regmap
.
at
(
spill
.
second
);
...
...
tests/5-bonus/testcases/16-argparse.cminus
0 → 100644
View file @
b4870a73
int getarg(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j)
{
output(a);
output(b);
output(c);
output(d);
output(e);
output(f);
output(g);
output(h);
output(i);
output(j);
}
int main(void)
{
int arr[100];
arr[0] = input();
arr[1] = input();
arr[2] = input();
arr[3] = input();
arr[4] = input();
arr[5] = input();
arr[6] = input();
arr[7] = input();
arr[8] = input();
arr[9] = input();
getarg(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8], arr[9]);
return 0;
}
tests/5-bonus/testcases/16-argparse.in
0 → 100644
View file @
b4870a73
826
-652
-395
146
704
859
728
556
609
-822
tests/5-bonus/testcases/16-argparse.out
0 → 100644
View file @
b4870a73
826
-652
-395
146
704
859
728
556
609
-822
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