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
06a9b882
Commit
06a9b882
authored
Feb 08, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
the order matters for data flow analysis!
parent
baff6088
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
82 additions
and
37 deletions
+82
-37
include/codegen/codegen.hpp
include/codegen/codegen.hpp
+10
-2
include/optimization/GVN.h
include/optimization/GVN.h
+2
-0
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+44
-33
src/optimization/GVN.cpp
src/optimization/GVN.cpp
+26
-2
No files found.
include/codegen/codegen.hpp
View file @
06a9b882
...
...
@@ -129,15 +129,23 @@ class CodeGen {
string
reg2
,
int
imm
,
string
tinstr
,
int
tid
=
0
,
int
bits
=
12
,
string
treg
=
"$t0"
,
bool
u
=
false
)
{
/* this function will tranfser
* `addi.d $a0, $fp, imm` to `add.d $a0, $fp, tmp_ireg` if imm
* overfloats for `addi.d`. During the time we move `imm` to `tmp_ireg`,
* another tmp ireg will be used, they can be same, but we must specify
* it.
*/
auto
treg
=
tmpregname
(
tid
,
false
);
assert
(
treg
!=
reg2
&&
"it's possible to write tid before reg2's use"
);
auto
[
l
,
h
]
=
immRange
(
bits
,
u
);
if
(
l
<=
imm
and
imm
<=
h
)
output
.
push_back
(
instr_ir
+
" "
+
reg1
+
", "
+
reg2
+
", "
+
to_string
(
imm
));
else
{
assert
(
value2reg
(
ConstantInt
::
get
(
imm
,
m
),
0
,
treg
)
==
treg
);
assert
(
value2reg
(
ConstantInt
::
get
(
imm
,
m
),
tid
,
treg
)
==
treg
);
output
.
push_back
(
tinstr
+
" "
+
reg1
+
", "
+
reg2
+
", "
+
treg
);
}
}
...
...
include/optimization/GVN.h
View file @
06a9b882
...
...
@@ -450,6 +450,7 @@ class GVN : public Pass {
std
::
unique_ptr
<
FuncInfo
>
func_info_
;
std
::
unique_ptr
<
GVNExpression
::
ConstFolder
>
folder_
;
std
::
unique_ptr
<
DeadCode
>
dce_
;
std
::
vector
<
BasicBlock
*>
BB_DFS_Order
;
// self add member
// std::uint64_t start_number_;
...
...
@@ -463,6 +464,7 @@ class GVN : public Pass {
//
// self add function
//
void
get_dfs_order
(
Function
*
func
);
void
add_map_
();
std
::
uint64_t
new_number
()
{
return
next_value_number_
++
;
}
void
deal_with_entry
(
BasicBlock
*
Entry
);
...
...
src/codegen/codegen.cpp
View file @
06a9b882
...
...
@@ -215,8 +215,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) {
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
v
))
{
// auto alloc_instr = dynamic_cast<AllocaInst *>(v);
// give the stack address
makeSureInRange
(
"addi.d"
,
reg_name
,
FP
,
-
off
.
at
(
v
),
"add.d"
,
12
,
reg_name
);
makeSureInRange
(
"addi.d"
,
reg_name
,
FP
,
-
off
.
at
(
v
),
"add.d"
,
i
);
/* output.push_back("addi.d " + reg_name + ", $fp, -" +
* to_string(off.at(v))); */
}
else
if
(
dynamic_cast
<
Argument
*>
(
v
))
{
...
...
@@ -235,8 +234,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) {
FP
,
func_arg_off
.
at
(
cur_func
).
at
(
id
),
instr_ir
+
"x"
+
suff
,
12
,
reg_name
);
i
);
/* output.push_back(instr_ir + suff + " " + reg_name + ", $fp, " +
* to_string(func_arg_off.at(cur_func).at(id))); */
}
...
...
@@ -248,8 +246,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) {
FP
,
-
off
.
at
(
v
),
instr_ir
+
"x"
+
suff
,
12
,
reg_name
);
i
);
/* output.push_back(instr_ir + suff + " " + reg_name +
* ", $fp, -" + to_string(off.at(v))); */
}
...
...
@@ -350,10 +347,10 @@ CodeGen::IR2assem(SiToFpInst *instr) {
}
string
CodeGen
::
bool2branch
(
Instruction
*
instr
)
{
assert
(
instr
->
get_type
()
==
m
->
get_int1_type
());
auto
icmp_instr
=
dynamic_cast
<
CmpInst
*>
(
instr
);
auto
fcmp_instr
=
dynamic_cast
<
FCmpInst
*>
(
instr
);
CodeGen
::
bool2branch
(
Instruction
*
cond
)
{
assert
(
cond
->
get_type
()
==
m
->
get_int1_type
());
auto
icmp_instr
=
dynamic_cast
<
CmpInst
*>
(
cond
);
auto
fcmp_instr
=
dynamic_cast
<
FCmpInst
*>
(
cond
);
assert
(
icmp_instr
or
fcmp_instr
);
string
instr_ir
;
...
...
@@ -365,9 +362,9 @@ CodeGen::bool2branch(Instruction *instr) {
break
;
case
CmpInst
::
NE
:
{
instr_ir
=
"bne"
;
if
(
instr
->
get_operand
(
1
)
==
CONST_0
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
if
(
cond
->
get_operand
(
1
)
==
CONST_0
and
dynamic_cast
<
Instruction
*>
(
cond
->
get_operand
(
0
))
and
dynamic_cast
<
Instruction
*>
(
cond
->
get_operand
(
0
))
->
is_zext
())
{
// something like:
// %op0 = icmp slt i32 1, 2 # deepest
...
...
@@ -375,7 +372,7 @@ CodeGen::bool2branch(Instruction *instr) {
// %op2 = icmp ne i32 %op1, 0
// br i1 %op2, label %label3, label %label5
auto
deepest
=
static_cast
<
Instruction
*>
(
static_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
static_cast
<
Instruction
*>
(
cond
->
get_operand
(
0
))
->
get_operand
(
0
));
return
bool2branch
(
deepest
);
}
...
...
@@ -395,11 +392,11 @@ CodeGen::bool2branch(Instruction *instr) {
reverse
=
true
;
break
;
}
auto
reg1
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
instr
->
get_operand
(
1
),
1
);
auto
reg1
=
value2reg
(
cond
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
cond
->
get_operand
(
1
),
1
);
return
instr_ir
+
" "
+
(
reverse
?
(
reg2
+
", "
+
reg1
)
:
(
reg1
+
", "
+
reg2
))
+
","
;
}
else
{
}
else
if
(
fcmp_instr
)
{
switch
(
fcmp_instr
->
get_cmp_op
())
{
case
FCmpInst
::
EQ
:
instr_ir
=
"fcmp.ceq.s $fcc0"
;
...
...
@@ -422,11 +419,12 @@ CodeGen::bool2branch(Instruction *instr) {
instr_ir
=
"fcmp.cle.s $fcc0"
;
break
;
}
auto
reg1
=
value2reg
(
instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
instr
->
get_operand
(
1
),
1
);
auto
reg1
=
value2reg
(
cond
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
cond
->
get_operand
(
1
),
1
);
output
.
push_back
(
instr_ir
+
", "
+
reg1
+
", "
+
reg2
);
return
(
reverse
?
"bceqz $fcc0,"
:
"bcnez $fcc0,"
);
}
}
else
assert
(
false
);
}
void
...
...
@@ -435,10 +433,20 @@ CodeGen::IR2assem(BranchInst *instr) {
auto
TBB
=
static_cast
<
BasicBlock
*>
(
instr
->
get_operand
(
1
));
auto
FBB
=
static_cast
<
BasicBlock
*>
(
instr
->
get_operand
(
2
));
// value2reg(instr->get_operand(0));
auto
cond
=
instr
->
get_operand
(
0
);
if
(
dynamic_cast
<
ConstantInt
*>
(
cond
))
{
auto
const_bool
=
static_cast
<
ConstantInt
*>
(
cond
);
assert
(
const_bool
->
get_type
()
->
is_integer_type
()
and
static_cast
<
IntegerType
*>
(
const_bool
->
get_type
())
->
get_num_bits
()
==
1
);
bool
cond_value
=
const_bool
->
get_value
();
output
.
push_back
(
"b "
+
label_in_assem
(
cond_value
?
TBB
:
FBB
));
}
else
{
string
instr_ir
=
bool2branch
(
static_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
)));
output
.
push_back
(
instr_ir
+
" "
+
label_in_assem
(
TBB
));
output
.
push_back
(
"b "
+
label_in_assem
(
FBB
));
}
}
else
{
auto
bb
=
static_cast
<
BasicBlock
*>
(
instr
->
get_operand
(
0
));
output
.
push_back
(
"b "
+
label_in_assem
(
bb
));
...
...
@@ -513,16 +521,15 @@ CodeGen::pass_arguments(CallInst *instr) {
vis
[
i
]
=
true
;
}
order
.
clear
();
for
(
int
arg_id
=
1
;
arg_id
<
instr
->
get_num_operand
();
arg_id
++
)
order
.
push_back
(
arg_id
);
// initialize
// 3. pass arguments' value
assert
(
order
.
size
()
==
func
->
get_num_of_args
());
map
<
string
,
bool
>
wroten
;
int
passed
=
0
;
// assert(order.size() >= func->get_num_of_args());
map
<
string
,
bool
>
changed
;
// bool assigned[8] = {false};
string
t0_contained
;
for
(
auto
arg_id
:
order
)
{
if
(
arg_id
>
func
->
get_num_of_args
())
continue
;
auto
arg_value
=
instr
->
get_operand
(
arg_id
);
auto
arg_is_float
=
arg_value
->
get_type
()
->
is_float_type
();
auto
arg_reg_aid
=
regname
(
arg_id
,
arg_is_float
);
...
...
@@ -531,12 +538,12 @@ CodeGen::pass_arguments(CallInst *instr) {
// arg_reg_aid(only right when arg_id <= 8)
v_reg
=
value2reg
(
arg_value
,
1
);
if
(
backup
[
arg_id
])
{
// a_id still relied by some argument due to cycle
assert
(
not
wroten
[
arg_reg_aid
]);
assert
(
not
changed
[
arg_reg_aid
]);
gencopy
(
t_reg
,
arg_reg_aid
,
arg_is_float
);
t0_contained
=
arg_reg_aid
;
}
// in case that the src register has been wroten
if
(
wroten
[
v_reg
])
{
if
(
changed
[
v_reg
])
{
assert
(
t0_contained
==
v_reg
);
v_reg
=
arg_value
->
get_type
()
->
is_float_type
()
?
"$ft0"
:
"$t0"
;
}
...
...
@@ -555,8 +562,12 @@ CodeGen::pass_arguments(CallInst *instr) {
* $sp, " + to_string(func_arg_off.at(func).at(arg_id)));
*/
}
wroten
[
arg_reg_aid
]
=
true
;
if
(
arg_reg_aid
!=
v_reg
)
{
changed
[
arg_reg_aid
]
=
true
;
}
passed
++
;
}
assert
(
passed
==
func
->
get_num_of_args
());
}
void
...
...
src/optimization/GVN.cpp
View file @
06a9b882
...
...
@@ -11,6 +11,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <deque>
#include <fstream>
#include <memory>
#include <sstream>
...
...
@@ -386,8 +387,10 @@ GVN::detectEquivalences() {
#ifdef __DEBUG__
std
::
cout
<<
++
times
<<
"th iteration"
<<
std
::
endl
;
#endif
for
(
auto
&
_bb
:
func_
->
get_basic_blocks
())
{
auto
bb
=
&
_bb
;
/* for (auto &_bb : func_->get_basic_blocks()) {
* std::cout << _bb.get_name() << std::endl;
* auto bb = &_bb; */
for
(
auto
&
bb
:
BB_DFS_Order
)
{
if
(
bb
==
Entry
)
continue
;
// get PIN of bb from predecessor(s)
...
...
@@ -922,6 +925,7 @@ GVN::run() {
for
(
auto
&
f
:
m_
->
get_functions
())
{
if
(
f
.
get_basic_blocks
().
empty
())
continue
;
get_dfs_order
(
&
f
);
func_
=
&
f
;
initPerFunction
();
LOG_INFO
<<
"Processing "
<<
f
.
get_name
();
...
...
@@ -953,6 +957,26 @@ GVN::run() {
gvn_json
<<
"]"
;
}
void
GVN
::
get_dfs_order
(
Function
*
func
)
{
std
::
map
<
BasicBlock
*
,
bool
>
vis
;
std
::
deque
<
BasicBlock
*>
Q
;
BB_DFS_Order
.
clear
();
Q
.
push_back
(
func
->
get_entry_block
());
while
(
not
Q
.
empty
())
{
auto
bb
=
Q
.
front
();
Q
.
pop_front
();
if
(
vis
[
bb
])
continue
;
vis
[
bb
]
=
true
;
BB_DFS_Order
.
push_back
(
bb
);
for
(
auto
succ
:
bb
->
get_succ_basic_blocks
())
Q
.
push_front
(
succ
);
}
}
void
GVN
::
dump_tmp
(
Function
&
f
)
{
std
::
string
gvn_json
;
...
...
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