Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
2
2025ustc-jianmu-compiler
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
43
Merge Requests
43
CI / CD
CI / CD
Pipelines
Jobs
Schedules
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
compiler_staff
2025ustc-jianmu-compiler
Commits
f40efe88
Commit
f40efe88
authored
Dec 03, 2025
by
Yang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
publish lab4
parent
93702b62
Changes
32
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1903 additions
and
860 deletions
+1903
-860
CMakeLists.txt
CMakeLists.txt
+1
-1
include/cminusfc/cminusf_builder.hpp
include/cminusfc/cminusf_builder.hpp
+0
-5
include/codegen/CodeGen.hpp
include/codegen/CodeGen.hpp
+0
-14
include/codegen/Register.hpp
include/codegen/Register.hpp
+1
-1
include/lightir/BasicBlock.hpp
include/lightir/BasicBlock.hpp
+1
-2
include/lightir/Instruction.hpp
include/lightir/Instruction.hpp
+5
-3
include/passes/DeadCode.hpp
include/passes/DeadCode.hpp
+1
-1
include/passes/Dominators.hpp
include/passes/Dominators.hpp
+17
-17
include/passes/FuncInfo.hpp
include/passes/FuncInfo.hpp
+6
-2
include/passes/LICM.hpp
include/passes/LICM.hpp
+0
-4
include/passes/LoopDetection.hpp
include/passes/LoopDetection.hpp
+1
-0
lldb_formatters.py
lldb_formatters.py
+2
-1
src/cminusfc/cminusf_builder.cpp
src/cminusfc/cminusf_builder.cpp
+0
-17
src/cminusfc/main.cpp
src/cminusfc/main.cpp
+54
-35
src/codegen/CodeGen.cpp
src/codegen/CodeGen.cpp
+574
-300
src/io/io.c
src/io/io.c
+53
-6
src/io/io.h
src/io/io.h
+2
-2
src/lightir/BasicBlock.cpp
src/lightir/BasicBlock.cpp
+9
-9
src/lightir/Function.cpp
src/lightir/Function.cpp
+1
-10
src/lightir/IRprinter.cpp
src/lightir/IRprinter.cpp
+1
-1
src/lightir/Instruction.cpp
src/lightir/Instruction.cpp
+18
-2
src/lightir/Module.cpp
src/lightir/Module.cpp
+17
-17
src/lightir/User.cpp
src/lightir/User.cpp
+1
-1
src/passes/DeadCode.cpp
src/passes/DeadCode.cpp
+9
-8
src/passes/Dominators.cpp
src/passes/Dominators.cpp
+30
-33
src/passes/FuncInfo.cpp
src/passes/FuncInfo.cpp
+224
-209
src/passes/LICM.cpp
src/passes/LICM.cpp
+119
-130
src/passes/LoopDetection.cpp
src/passes/LoopDetection.cpp
+18
-1
src/passes/Mem2Reg.cpp
src/passes/Mem2Reg.cpp
+31
-26
tests/4-opt/CMakeLists.txt
tests/4-opt/CMakeLists.txt
+9
-0
tests/4-opt/eval_lab4.cpp
tests/4-opt/eval_lab4.cpp
+695
-0
tests/CMakeLists.txt
tests/CMakeLists.txt
+3
-2
No files found.
CMakeLists.txt
View file @
f40efe88
...
...
@@ -63,4 +63,4 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
include_directories
(
${
PROJECT_SOURCE_DIR
}
)
include_directories
(
${
PROJECT_BINARY_DIR
}
)
add_subdirectory
(
src
)
#
add_subdirectory(tests)
add_subdirectory
(
tests
)
include/cminusfc/cminusf_builder.hpp
View file @
f40efe88
...
...
@@ -67,15 +67,10 @@ class CminusfBuilder : public ASTVisitor {
auto
*
output_float_fun
=
Function
::
create
(
output_float_type
,
"outputFloat"
,
module
);
auto
*
neg_idx_except_type
=
FunctionType
::
get
(
TyVoid
,
{});
auto
*
neg_idx_except_fun
=
Function
::
create
(
neg_idx_except_type
,
"neg_idx_except"
,
module
);
scope
.
enter
();
scope
.
push
(
"input"
,
input_fun
);
scope
.
push
(
"output"
,
output_fun
);
scope
.
push
(
"outputFloat"
,
output_float_fun
);
scope
.
push
(
"neg_idx_except"
,
neg_idx_except_fun
);
}
Module
*
getModule
()
const
{
return
module
;
}
...
...
include/codegen/CodeGen.hpp
View file @
f40efe88
...
...
@@ -64,18 +64,6 @@ class CodeGen {
void
gen_fptosi
();
void
gen_epilogue
();
static
std
::
string
label_name
(
BasicBlock
*
bb
)
{
return
"."
+
bb
->
get_parent
()
->
get_name
()
+
"_"
+
bb
->
get_name
();
}
static
std
::
string
func_exit_label_name
(
Function
*
func
)
{
return
func
->
get_name
()
+
"_exit"
;
}
static
std
::
string
fcmp_label_name
(
BasicBlock
*
bb
,
unsigned
cnt
)
{
return
label_name
(
bb
)
+
"_fcmp_"
+
std
::
to_string
(
cnt
);
}
struct
{
/* 随着ir遍历设置 */
Function
*
func
{
nullptr
};
// 当前函数
...
...
@@ -84,14 +72,12 @@ class CodeGen {
/* 在allocate()中设置 */
unsigned
frame_size
{
0
};
// 当前函数的栈帧大小
std
::
unordered_map
<
Value
*
,
int
>
offset_map
{};
// 指针相对 fp 的偏移
unsigned
fcmp_cnt
{
0
};
// fcmp 的计数器, 用于创建 fcmp 需要的 label
void
clear
()
{
func
=
nullptr
;
bb
=
nullptr
;
inst
=
nullptr
;
frame_size
=
0
;
fcmp_cnt
=
0
;
offset_map
.
clear
();
}
...
...
include/codegen/Register.hpp
View file @
f40efe88
include/lightir/BasicBlock.hpp
View file @
f40efe88
...
...
@@ -20,8 +20,7 @@ class BasicBlock : public Value {
~
BasicBlock
()
override
;
static
BasicBlock
*
create
(
Module
*
m
,
const
std
::
string
&
name
,
Function
*
parent
)
{
auto
prefix
=
name
.
empty
()
?
""
:
"label_"
;
return
new
BasicBlock
(
m
,
prefix
+
name
,
parent
);
return
new
BasicBlock
(
m
,
name
,
parent
);
}
/****************api about cfg****************/
...
...
include/lightir/Instruction.hpp
View file @
f40efe88
...
...
@@ -214,6 +214,8 @@ public:
Value
*
get_condition
()
const
{
return
get_operand
(
0
);
}
void
replace_all_bb_match
(
BasicBlock
*
need_replace
,
BasicBlock
*
replace_to
);
std
::
string
print
()
override
;
};
...
...
@@ -251,8 +253,8 @@ class StoreInst : public Instruction {
public:
static
StoreInst
*
create_store
(
Value
*
val
,
Value
*
ptr
,
BasicBlock
*
bb
);
Value
*
get_
r
val
()
const
{
return
this
->
get_operand
(
0
);
}
Value
*
get_
lval
()
const
{
return
this
->
get_operand
(
1
);
}
Value
*
get_val
()
const
{
return
this
->
get_operand
(
0
);
}
Value
*
get_
ptr
()
const
{
return
this
->
get_operand
(
1
);
}
std
::
string
print
()
override
;
};
...
...
@@ -264,7 +266,7 @@ class LoadInst : public Instruction {
public:
static
LoadInst
*
create_load
(
Value
*
ptr
,
BasicBlock
*
bb
,
const
std
::
string
&
name
=
""
);
Value
*
get_
lval
()
const
{
return
this
->
get_operand
(
0
);
}
Value
*
get_
ptr
()
const
{
return
this
->
get_operand
(
0
);
}
Type
*
get_load_type
()
const
{
return
get_type
();
}
std
::
string
print
()
override
;
...
...
include/passes/DeadCode.hpp
View file @
f40efe88
include/passes/Dominators.hpp
View file @
f40efe88
...
...
@@ -20,11 +20,11 @@ class Dominators : public FunctionAnalysisPass {
void
run
()
override
;
// 获取基本块的直接支配节点
BasicBlock
*
get_idom
(
const
BasicBlock
*
bb
)
const
{
return
idom_
.
at
(
bb
);
}
const
std
::
set
<
BasicBlock
*>
&
get_dominance_frontier
(
const
BasicBlock
*
bb
)
{
BasicBlock
*
get_idom
(
BasicBlock
*
bb
)
const
{
return
idom_
.
at
(
bb
);
}
const
std
::
set
<
BasicBlock
*>
&
get_dominance_frontier
(
BasicBlock
*
bb
)
{
return
dom_frontier_
.
at
(
bb
);
}
const
std
::
set
<
BasicBlock
*>
&
get_dom_tree_succ_blocks
(
const
BasicBlock
*
bb
)
{
const
std
::
set
<
BasicBlock
*>
&
get_dom_tree_succ_blocks
(
BasicBlock
*
bb
)
{
return
dom_tree_succ_blocks_
.
at
(
bb
);
}
...
...
@@ -33,7 +33,7 @@ class Dominators : public FunctionAnalysisPass {
void
dump_dominator_tree
();
// functions for dominance tree
bool
is_dominate
(
const
BasicBlock
*
bb1
,
const
BasicBlock
*
bb2
)
const
{
bool
is_dominate
(
BasicBlock
*
bb1
,
BasicBlock
*
bb2
)
const
{
return
dom_tree_L_
.
at
(
bb1
)
<=
dom_tree_L_
.
at
(
bb2
)
&&
dom_tree_R_
.
at
(
bb1
)
>=
dom_tree_L_
.
at
(
bb2
);
}
...
...
@@ -54,33 +54,33 @@ class Dominators : public FunctionAnalysisPass {
void
create_dom_tree_succ
();
void
create_dom_dfs_order
();
BasicBlock
*
intersect
(
BasicBlock
*
b1
,
const
BasicBlock
*
b2
)
const
;
BasicBlock
*
intersect
(
BasicBlock
*
b1
,
BasicBlock
*
b2
)
const
;
void
create_reverse_post_order
();
void
set_idom
(
const
BasicBlock
*
bb
,
BasicBlock
*
idom
)
{
idom_
[
bb
]
=
idom
;
}
void
set_dominance_frontier
(
const
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>&
df
)
{
void
set_idom
(
BasicBlock
*
bb
,
BasicBlock
*
idom
)
{
idom_
[
bb
]
=
idom
;
}
void
set_dominance_frontier
(
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>&
df
)
{
dom_frontier_
[
bb
].
clear
();
dom_frontier_
[
bb
].
insert
(
df
.
begin
(),
df
.
end
());
}
void
add_dom_tree_succ_block
(
const
BasicBlock
*
bb
,
BasicBlock
*
dom_tree_succ_bb
)
{
void
add_dom_tree_succ_block
(
BasicBlock
*
bb
,
BasicBlock
*
dom_tree_succ_bb
)
{
dom_tree_succ_blocks_
[
bb
].
insert
(
dom_tree_succ_bb
);
}
unsigned
int
get_
post_order
(
const
BasicBlock
*
bb
)
const
{
return
post_order_
.
at
(
bb
);
unsigned
int
get_
reversed_post_order
(
BasicBlock
*
bb
)
const
{
return
reversed_
post_order_
.
at
(
bb
);
}
// for debug
void
print_idom
()
const
;
void
print_dominance_frontier
();
std
::
vector
<
BasicBlock
*>
post_order_vec_
{};
// 逆后序
std
::
map
<
const
BasicBlock
*
,
unsigned
int
>
post_order_
{};
// 逆后序
std
::
map
<
const
BasicBlock
*
,
BasicBlock
*>
idom_
{};
// 直接支配
std
::
map
<
const
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_frontier_
{};
// 支配边界集合
std
::
map
<
const
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_tree_succ_blocks_
{};
// 支配树中的后继节点
std
::
vector
<
BasicBlock
*>
reversed_
post_order_vec_
{};
// 逆后序
std
::
map
<
BasicBlock
*
,
unsigned
int
>
reversed_post_order_
{};
// 逆后序索引
std
::
map
<
BasicBlock
*
,
BasicBlock
*>
idom_
{};
// 直接支配
std
::
map
<
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_frontier_
{};
// 支配边界集合
std
::
map
<
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_tree_succ_blocks_
{};
// 支配树中的后继节点
// 支配树上的dfs序L,R
std
::
map
<
const
BasicBlock
*
,
unsigned
int
>
dom_tree_L_
;
std
::
map
<
const
BasicBlock
*
,
unsigned
int
>
dom_tree_R_
;
std
::
map
<
BasicBlock
*
,
unsigned
int
>
dom_tree_L_
;
std
::
map
<
BasicBlock
*
,
unsigned
int
>
dom_tree_R_
;
std
::
vector
<
BasicBlock
*>
dom_dfs_order_
;
std
::
vector
<
BasicBlock
*>
dom_post_order_
;
...
...
include/passes/FuncInfo.hpp
View file @
f40efe88
...
...
@@ -27,13 +27,17 @@ class FuncInfo : public ModuleAnalysisPass {
void
run
()
override
;
// 函数是否是纯函数
bool
is_pure
(
Function
*
func
)
{
return
!
func
->
is_declaration
()
&&
!
use_libs
.
count
(
func
)
&&
loads
[
func
].
empty
()
&&
stores
[
func
].
empty
();
}
bool
is_pure
(
Function
*
func
)
{
return
!
func
->
is_declaration
()
&&
!
use_libs
[
func
]
&&
loads
[
func
].
empty
()
&&
stores
[
func
].
empty
();
}
// 函数是否使用了 io
bool
use_io
(
Function
*
func
)
{
return
func
->
is_declaration
()
||
use_libs
[
func
];
}
// 返回 StoreInst 存入的变量(全局/局部变量或函数参数)
static
Value
*
store_ptr
(
const
StoreInst
*
st
);
// 返回 LoadInst 加载的变量(全局/局部变量或函数参数)
static
Value
*
load_ptr
(
const
LoadInst
*
ld
);
// 返回 CallInst 代表的函数调用间接存入的变量(全局/局部变量或函数参数)
std
::
unordered_set
<
Value
*>
get_stores
(
const
CallInst
*
call
);
// 返回 CallInst 代表的函数调用间接加载的变量(全局/局部变量或函数参数)
std
::
unordered_set
<
Value
*>
get_loads
(
const
CallInst
*
call
);
private:
// 函数存储的值
std
::
unordered_map
<
Function
*
,
UseMessage
>
stores
;
...
...
include/passes/LICM.hpp
View file @
f40efe88
...
...
@@ -18,8 +18,4 @@ class LoopInvariantCodeMotion : public TransformPass {
std
::
vector
<
Instruction
*>
collect_insts
(
Loop
*
loop
);
void
traverse_loop
(
Loop
*
loop
);
void
run_on_loop
(
Loop
*
loop
);
void
collect_loop_info
(
Loop
*
loop
,
std
::
set
<
Value
*>
&
loop_instructions
,
std
::
set
<
Value
*>
&
updated_global
,
bool
&
contains_impure_call
);
};
\ No newline at end of file
include/passes/LoopDetection.hpp
View file @
f40efe88
...
...
@@ -40,6 +40,7 @@ class Loop {
const
std
::
vector
<
Loop
*>&
get_sub_loops
()
{
return
sub_loops_
;
}
const
std
::
unordered_set
<
BasicBlock
*>&
get_latches
()
{
return
latches_
;
}
void
add_latch
(
BasicBlock
*
bb
)
{
latches_
.
insert
(
bb
);
}
std
::
string
safe_print
()
const
;
};
class
LoopDetection
:
public
FunctionAnalysisPass
{
...
...
lldb_formatters.py
View file @
f40efe88
...
...
@@ -25,7 +25,8 @@ def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
,
"BasicBlock"
,
"GlobalVariable"
,
"Instruction"
,
"IBinaryInst"
,
"FBinaryInst"
,
"ICmpInst"
,
"FCmpInst"
,
"CallInst"
,
"BranchInst"
,
"ReturnInst"
,
"GetElementPtrInst"
,
"StoreInst"
,
"LoadInst"
,
"AllocaInst"
,
"ZextInst"
,
"FpToSiInst"
,
"SiToFpInst"
,
"PhiInst"
,
"ASMInstruction"
,
"Reg"
,
"FReg"
,
"CFReg"
]
,
"ASMInstruction"
,
"Reg"
,
"FReg"
,
"CFReg"
,
"Loop"
]
for
i
in
types
:
debugger
.
HandleCommand
(
f"type summary add -F lldb_formatters.SafePrintSummary
{
i
}
-w my"
...
...
src/cminusfc/cminusf_builder.cpp
View file @
f40efe88
...
...
@@ -329,27 +329,10 @@ Value* CminusfBuilder::visit(ASTVar &node) {
}
}
else
{
auto
*
val
=
node
.
expression
->
accept
(
*
this
);
auto
*
exceptBB
=
BasicBlock
::
create
(
module
,
""
,
context
.
func
);
auto
*
contBB
=
BasicBlock
::
create
(
module
,
""
,
context
.
func
);
if
(
val
->
get_type
()
->
is_float_type
())
{
val
=
builder
->
create_fptosi
(
val
,
INT32_T
);
}
Value
*
is_neg
=
builder
->
create_icmp_lt
(
val
,
CONST_INT
(
0
));
builder
->
create_cond_br
(
is_neg
,
exceptBB
,
contBB
);
builder
->
set_insert_point
(
exceptBB
);
auto
*
neg_idx_except_fun
=
scope
.
find
(
"neg_idx_except"
);
builder
->
create_call
(
dynamic_cast
<
Function
*>
(
neg_idx_except_fun
),
{});
if
(
context
.
func
->
get_return_type
()
->
is_void_type
())
{
builder
->
create_void_ret
();
}
else
if
(
context
.
func
->
get_return_type
()
->
is_float_type
())
{
builder
->
create_ret
(
CONST_FP
(
0.
));
}
else
{
builder
->
create_ret
(
CONST_INT
(
0
));
}
builder
->
set_insert_point
(
contBB
);
Value
*
tmp_ptr
;
if
(
is_int
||
is_float
)
{
tmp_ptr
=
builder
->
create_gep
(
var
,
{
val
});
...
...
src/cminusfc/main.cpp
View file @
f40efe88
...
...
@@ -23,30 +23,30 @@ struct Config {
std
::
filesystem
::
path
input_file
;
std
::
filesystem
::
path
output_file
;
bool
emitast
{
false
};
bool
emitasm
{
false
};
bool
emitllvm
{
false
};
bool
emitast
{
false
};
bool
emitasm
{
false
};
bool
emitllvm
{
false
};
// optization conifg
bool
mem2reg
{
false
};
bool
licm
{
false
};
bool
mem2reg
{
false
};
bool
licm
{
false
};
Config
(
int
argc
,
char
**
argv
)
:
argc
(
argc
),
argv
(
argv
)
{
Config
(
int
argc
,
char
**
argv
)
:
argc
(
argc
),
argv
(
argv
)
{
parse_cmd_line
();
check
();
}
private:
int
argc
{
-
1
};
char
**
argv
{
nullptr
};
private:
int
argc
{
-
1
};
char
**
argv
{
nullptr
};
void
parse_cmd_line
();
void
check
();
// print helper infomation and exit
void
print_help
()
const
;
void
print_err
(
const
string
&
msg
)
const
;
void
print_err
(
const
string
&
msg
)
const
;
};
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
Config
config
(
argc
,
argv
);
auto
syntax_tree
=
parse
(
config
.
input_file
.
c_str
());
...
...
@@ -55,7 +55,8 @@ int main(int argc, char **argv) {
if
(
config
.
emitast
)
{
// if emit ast (lab1), print ast and return
ASTPrinter
printer
;
ast
.
run_visitor
(
printer
);
}
else
{
}
else
{
Module
*
m
;
CminusfBuilder
builder
;
ast
.
run_visitor
(
builder
);
...
...
@@ -63,11 +64,12 @@ int main(int argc, char **argv) {
PassManager
PM
(
m
);
// optimization
if
(
config
.
mem2reg
)
{
if
(
config
.
mem2reg
)
{
PM
.
add_pass
<
DeadCode
>
(
true
);
PM
.
add_pass
<
Mem2Reg
>
();
PM
.
add_pass
<
DeadCode
>
(
false
);
}
if
(
config
.
licm
)
{
if
(
config
.
licm
)
{
PM
.
add_pass
<
LoopInvariantCodeMotion
>
();
PM
.
add_pass
<
DeadCode
>
(
false
);
}
...
...
@@ -79,7 +81,14 @@ int main(int argc, char **argv) {
output_stream
<<
"; ModuleID = 'cminus'
\n
"
;
output_stream
<<
"source_filename = "
<<
abs_path
<<
"
\n\n
"
;
output_stream
<<
m
->
print
();
}
else
if
(
config
.
emitasm
)
{
}
else
if
(
config
.
emitasm
)
{
auto
abs_path
=
std
::
filesystem
::
canonical
(
config
.
input_file
);
config
.
output_file
.
replace_extension
(
"ll"
);
std
::
ofstream
output_stream2
(
config
.
output_file
);
output_stream2
<<
"; ModuleID = 'cminus'
\n
"
;
output_stream2
<<
"source_filename = "
<<
abs_path
<<
"
\n\n
"
;
output_stream2
<<
m
->
print
();
CodeGen
codegen
(
m
);
codegen
.
run
();
output_stream
<<
codegen
.
print
();
...
...
@@ -96,27 +105,36 @@ void Config::parse_cmd_line() {
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
if
(
argv
[
i
]
==
"-h"
s
||
argv
[
i
]
==
"--help"
s
)
{
print_help
();
}
else
if
(
argv
[
i
]
==
"-o"
s
)
{
}
else
if
(
argv
[
i
]
==
"-o"
s
)
{
if
(
output_file
.
empty
()
&&
i
+
1
<
argc
)
{
output_file
=
argv
[
i
+
1
];
i
+=
1
;
}
else
{
}
else
{
print_err
(
"bad output file"
);
}
}
else
if
(
argv
[
i
]
==
"-emit-ast"
s
)
{
}
else
if
(
argv
[
i
]
==
"-emit-ast"
s
)
{
emitast
=
true
;
}
else
if
(
argv
[
i
]
==
"-S"
s
)
{
}
else
if
(
argv
[
i
]
==
"-S"
s
)
{
emitasm
=
true
;
}
else
if
(
argv
[
i
]
==
"-emit-llvm"
s
)
{
}
else
if
(
argv
[
i
]
==
"-emit-llvm"
s
)
{
emitllvm
=
true
;
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
mem2reg
=
true
;
}
else
if
(
argv
[
i
]
==
"-licm"
s
)
{
}
else
if
(
argv
[
i
]
==
"-licm"
s
)
{
licm
=
true
;
}
else
{
}
else
{
if
(
input_file
.
empty
())
{
input_file
=
argv
[
i
];
}
else
{
}
else
{
string
err
=
"unrecognized command-line option
\'
"
s
+
argv
[
i
]
+
"
\'
"
s
;
print_err
(
err
);
...
...
@@ -143,11 +161,12 @@ void Config::check() {
}
if
(
output_file
.
empty
())
{
output_file
=
input_file
.
stem
();
}
if
(
emitllvm
)
{
output_file
.
replace_extension
(
".ll"
);
}
else
if
(
emitasm
)
{
output_file
.
replace_extension
(
".s"
);
}
else
if
(
emitasm
)
{
output_file
.
replace_extension
(
".s"
);
}
}
...
...
@@ -160,7 +179,7 @@ void Config::print_help() const {
exit
(
0
);
}
void
Config
::
print_err
(
const
string
&
msg
)
const
{
void
Config
::
print_err
(
const
string
&
msg
)
const
{
std
::
cout
<<
exe_name
<<
": "
<<
msg
<<
std
::
endl
;
exit
(
-
1
);
}
src/codegen/CodeGen.cpp
View file @
f40efe88
This diff is collapsed.
Click to expand it.
src/io/io.c
View file @
f40efe88
#include <stdio.h>
#include <stdlib.h>
int
input
()
{
#include <sys/time.h>
struct
timeval
time_start
,
time_end
;
int
end_set
;
int
flags
[
2
];
int
input
(
void
)
{
int
a
;
scanf
(
"%d"
,
&
a
);
gettimeofday
(
&
time_start
,
NULL
);
end_set
=
0
;
return
a
;
}
void
output
(
int
a
)
{
printf
(
"%d
\n
"
,
a
);
}
void
output
(
int
a
)
{
if
(
end_set
==
0
)
{
gettimeofday
(
&
time_end
,
NULL
);
end_set
=
1
;
}
printf
(
"%d
\n
"
,
a
);
}
void
outputFloat
(
float
a
)
{
if
(
end_set
==
0
)
{
gettimeofday
(
&
time_end
,
NULL
);
end_set
=
1
;
}
printf
(
"%f
\n
"
,
a
);
}
void
add_lab4_flag
(
int
idx
,
int
val
)
{
flags
[
idx
]
+=
val
;
}
void
outputFloat
(
float
a
)
{
printf
(
"%f
\n
"
,
a
);
}
__attribute
((
constructor
))
void
before_main
(
void
)
{
flags
[
0
]
=
0
;
flags
[
1
]
=
0
;
end_set
=
0
;
gettimeofday
(
&
time_start
,
NULL
);
}
void
neg_idx_except
()
{
printf
(
"negative index exception
\n
"
);
exit
(
0
);
__attribute
((
destructor
))
void
after_main
(
void
)
{
long
time_us
=
0
;
fprintf
(
stderr
,
"Allocate Size (bytes):
\n
%d
\n
"
,
flags
[
0
]);
fprintf
(
stderr
,
"Execute Cost:
\n
%d
\n
"
,
flags
[
1
]);
if
(
end_set
==
0
)
{
gettimeofday
(
&
time_end
,
NULL
);
}
time_us
+=
1000000L
*
(
time_end
.
tv_sec
-
time_start
.
tv_sec
)
+
time_end
.
tv_usec
-
time_start
.
tv_usec
;
fprintf
(
stderr
,
"Take Times (us):
\n
%ld
\n
"
,
time_us
);
}
src/io/io.h
View file @
f40efe88
int
input
();
int
input
(
void
);
void
output
(
int
a
);
void
outputFloat
(
float
a
);
void
neg_idx_except
(
);
void
add_lab4_flag
(
int
idx
,
int
val
);
\ No newline at end of file
src/lightir/BasicBlock.cpp
View file @
f40efe88
...
...
@@ -12,13 +12,13 @@
BasicBlock
::
BasicBlock
(
const
Module
*
m
,
const
std
::
string
&
name
=
""
,
Function
*
parent
=
nullptr
)
:
Value
(
m
->
get_label_type
(),
parent
==
nullptr
?
GLOBAL_BASICBLOCK_NAMES_
.
get_name
(
name
)
:
parent
->
names4blocks_
.
get_name
(
name
))
,
parent_
(
parent
)
{
parent
==
nullptr
?
GLOBAL_BASICBLOCK_NAMES_
.
get_name
(
name
)
:
parent
->
names4blocks_
.
get_name
(
name
))
,
parent_
(
parent
)
{
assert
(
parent
&&
"currently parent should not be nullptr"
);
parent_
->
add_basic_block
(
this
);
}
Module
*
BasicBlock
::
get_module
()
const
{
return
get_parent
()
->
get_parent
();
}
Module
*
BasicBlock
::
get_module
()
const
{
return
get_parent
()
->
get_parent
();
}
void
BasicBlock
::
erase_from_parent
()
{
this
->
get_parent
()
->
remove
(
this
);
}
bool
BasicBlock
::
is_terminated
()
const
{
...
...
@@ -34,18 +34,18 @@ bool BasicBlock::is_terminated() const {
}
}
Instruction
*
BasicBlock
::
get_terminator
()
const
Instruction
*
BasicBlock
::
get_terminator
()
const
{
assert
(
is_terminated
()
&&
"Trying to get terminator from an bb which is not terminated"
);
return
instr_list_
.
back
();
}
void
BasicBlock
::
add_instruction
(
Instruction
*
instr
)
{
void
BasicBlock
::
add_instruction
(
Instruction
*
instr
)
{
if
(
instr
->
is_alloca
()
||
instr
->
is_phi
())
{
auto
it
=
instr_list_
.
begin
();
for
(;
it
!=
instr_list_
.
end
()
&&
((
*
it
)
->
is_alloca
()
||
(
*
it
)
->
is_phi
());
++
it
)
{}
for
(;
it
!=
instr_list_
.
end
()
&&
((
*
it
)
->
is_alloca
()
||
(
*
it
)
->
is_phi
());
++
it
)
{}
instr_list_
.
emplace
(
it
,
instr
);
return
;
}
...
...
@@ -146,4 +146,4 @@ BasicBlock* BasicBlock::get_entry_block_of_same_function() const
return
parent_
->
get_entry_block
();
}
Names
GLOBAL_BASICBLOCK_NAMES_
{
"label"
,
"_"
};
\ No newline at end of file
Names
GLOBAL_BASICBLOCK_NAMES_
{
"label"
,
"_"
};
\ No newline at end of file
src/lightir/Function.cpp
View file @
f40efe88
...
...
@@ -7,17 +7,8 @@
#include <unordered_set>
#include <queue>
namespace
{
std
::
string
chopName
(
std
::
string
name
)
{
if
(
name
.
size
()
>
3
)
return
{
name
.
begin
(),
name
.
begin
()
+
3
};
return
name
;
}
}
Function
::
Function
(
FunctionType
*
ty
,
const
std
::
string
&
name
,
Module
*
parent
)
:
Value
(
ty
,
name
),
names4blocks_
(
"
label"
,
chopName
(
name
)
+
"_"
),
names4insts_
(
"op"
,
""
),
parent_
(
parent
),
seq_cnt_
(
0
)
{
:
Value
(
ty
,
name
),
names4blocks_
(
"
"
,
name
+
"_"
),
names4insts_
(
"op"
,
""
),
parent_
(
parent
),
seq_cnt_
(
0
)
{
// num_args_ = ty->getNumParams();
parent
->
add_function
(
this
);
// build args
...
...
src/lightir/IRprinter.cpp
View file @
f40efe88
...
...
@@ -382,7 +382,7 @@ std::string Instruction::safe_print() const
}
else
{
if
(
auto
fty
=
dynamic_cast
<
FunctionType
*>
(
ty
))
if
(
auto
fty
=
dynamic_cast
<
FunctionType
*>
(
op0
->
get_type
()
))
{
auto
ty3
=
fty
->
get_return_type
();
if
(
ty3
==
nullptr
)
...
...
src/lightir/Instruction.cpp
View file @
f40efe88
...
...
@@ -197,6 +197,23 @@ BranchInst *BranchInst::create_br(BasicBlock *if_true, BasicBlock *bb) {
return
new
BranchInst
(
nullptr
,
if_true
,
nullptr
,
bb
);
}
void
BranchInst
::
replace_all_bb_match
(
BasicBlock
*
need_replace
,
BasicBlock
*
replace_to
)
{
if
(
need_replace
==
nullptr
||
replace_to
==
nullptr
||
need_replace
==
replace_to
)
return
;
int
size
=
static_cast
<
int
>
(
get_operands
().
size
());
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
auto
op
=
get_operand
(
i
);
if
(
op
==
need_replace
)
set_operand
(
i
,
replace_to
);
}
auto
parent
=
get_parent
();
if
(
parent
==
nullptr
)
return
;
parent
->
remove_succ_basic_block
(
need_replace
);
need_replace
->
remove_pre_basic_block
(
parent
);
parent
->
add_succ_basic_block
(
replace_to
);
replace_to
->
add_pre_basic_block
(
parent
);
}
ReturnInst
::
ReturnInst
(
Value
*
val
,
BasicBlock
*
bb
)
:
Instruction
(
bb
->
get_module
()
->
get_void_type
(),
ret
,
""
,
bb
)
{
if
(
val
==
nullptr
)
{
...
...
@@ -352,14 +369,13 @@ SiToFpInst *SiToFpInst::create_sitofp(Value *val, BasicBlock *bb, const std::str
PhiInst
::
PhiInst
(
Type
*
ty
,
const
std
::
vector
<
Value
*>&
vals
,
const
std
::
vector
<
BasicBlock
*>&
val_bbs
,
BasicBlock
*
bb
,
const
std
::
string
&
name
)
:
Instruction
(
ty
,
phi
,
name
)
{
:
Instruction
(
ty
,
phi
,
name
,
bb
)
{
assert
(
vals
.
size
()
==
val_bbs
.
size
()
&&
"Unmatched vals and bbs"
);
for
(
unsigned
i
=
0
;
i
<
vals
.
size
();
i
++
)
{
assert
(
ty
==
vals
[
i
]
->
get_type
()
&&
"Bad type for phi"
);
add_operand
(
vals
[
i
]);
add_operand
(
val_bbs
[
i
]);
}
this
->
set_parent
(
bb
);
}
PhiInst
*
PhiInst
::
create_phi
(
Type
*
ty
,
BasicBlock
*
bb
,
...
...
src/lightir/Module.cpp
View file @
f40efe88
...
...
@@ -27,48 +27,48 @@ Module::~Module()
for
(
auto
i
:
global_list_
)
delete
i
;
}
Type
*
Module
::
get_void_type
()
const
{
return
void_ty_
;
}
Type
*
Module
::
get_label_type
()
const
{
return
label_ty_
;
}
IntegerType
*
Module
::
get_int1_type
()
const
{
return
int1_ty_
;
}
IntegerType
*
Module
::
get_int32_type
()
const
{
return
int32_ty_
;
}
FloatType
*
Module
::
get_float_type
()
const
{
return
float32_ty_
;
}
PointerType
*
Module
::
get_int32_ptr_type
()
{
Type
*
Module
::
get_void_type
()
const
{
return
void_ty_
;
}
Type
*
Module
::
get_label_type
()
const
{
return
label_ty_
;
}
IntegerType
*
Module
::
get_int1_type
()
const
{
return
int1_ty_
;
}
IntegerType
*
Module
::
get_int32_type
()
const
{
return
int32_ty_
;
}
FloatType
*
Module
::
get_float_type
()
const
{
return
float32_ty_
;
}
PointerType
*
Module
::
get_int32_ptr_type
()
{
return
get_pointer_type
(
int32_ty_
);
}
PointerType
*
Module
::
get_float_ptr_type
()
{
PointerType
*
Module
::
get_float_ptr_type
()
{
return
get_pointer_type
(
float32_ty_
);
}
PointerType
*
Module
::
get_pointer_type
(
Type
*
contained
)
{
PointerType
*
Module
::
get_pointer_type
(
Type
*
contained
)
{
if
(
pointer_map_
.
find
(
contained
)
==
pointer_map_
.
end
())
{
pointer_map_
[
contained
]
=
new
PointerType
(
contained
);
}
return
pointer_map_
[
contained
];
}
ArrayType
*
Module
::
get_array_type
(
Type
*
contained
,
unsigned
num_elements
)
{
if
(
array_map_
.
find
({
contained
,
num_elements
})
==
array_map_
.
end
())
{
ArrayType
*
Module
::
get_array_type
(
Type
*
contained
,
unsigned
num_elements
)
{
if
(
array_map_
.
find
({
contained
,
num_elements
})
==
array_map_
.
end
())
{
array_map_
[{
contained
,
num_elements
}]
=
new
ArrayType
(
contained
,
num_elements
);
}
return
array_map_
[{
contained
,
num_elements
}];
}
FunctionType
*
Module
::
get_function_type
(
Type
*
retty
,
std
::
vector
<
Type
*>
&
args
)
{
if
(
not
function_map_
.
count
({
retty
,
args
}))
{
FunctionType
*
Module
::
get_function_type
(
Type
*
retty
,
std
::
vector
<
Type
*>&
args
)
{
if
(
not
function_map_
.
count
({
retty
,
args
}))
{
function_map_
[{
retty
,
args
}]
=
new
FunctionType
(
retty
,
args
);
}
return
function_map_
[{
retty
,
args
}];
}
void
Module
::
add_function
(
Function
*
f
)
{
function_list_
.
push_back
(
f
);
}
std
::
list
<
Function
*>
&
Module
::
get_functions
()
{
return
function_list_
;
}
void
Module
::
add_global_variable
(
GlobalVariable
*
g
)
{
void
Module
::
add_function
(
Function
*
f
)
{
function_list_
.
push_back
(
f
);
}
std
::
list
<
Function
*>
&
Module
::
get_functions
()
{
return
function_list_
;
}
void
Module
::
add_global_variable
(
GlobalVariable
*
g
)
{
global_list_
.
push_back
(
g
);
}
std
::
list
<
GlobalVariable
*>
&
Module
::
get_global_variable
()
{
std
::
list
<
GlobalVariable
*>
&
Module
::
get_global_variable
()
{
return
global_list_
;
}
...
...
src/lightir/User.cpp
View file @
f40efe88
src/passes/DeadCode.cpp
View file @
f40efe88
...
...
@@ -15,6 +15,7 @@ void DeadCode::run() {
do
{
changed
=
false
;
for
(
auto
func
:
m_
->
get_functions
())
{
if
(
func
->
is_declaration
())
continue
;
if
(
remove_bb_
)
changed
|=
clear_basic_blocks
(
func
);
mark
(
func
);
changed
|=
sweep
(
func
);
...
...
src/passes/Dominators.cpp
View file @
f40efe88
...
...
@@ -62,13 +62,13 @@ void Dominators::run() {
* 该函数使用后序号来查找两个节点的最近公共支配者。
* 通过在支配树上向上遍历直到找到交点。
*/
BasicBlock
*
Dominators
::
intersect
(
BasicBlock
*
b1
,
const
BasicBlock
*
b2
)
const
BasicBlock
*
Dominators
::
intersect
(
BasicBlock
*
b1
,
BasicBlock
*
b2
)
const
{
while
(
b1
!=
b2
)
{
while
(
get_
post_order
(
b1
)
<
get
_post_order
(
b2
))
{
while
(
get_
reversed_post_order
(
b1
)
>
get_reversed
_post_order
(
b2
))
{
b1
=
get_idom
(
b1
);
}
while
(
get_
post_order
(
b2
)
<
get
_post_order
(
b1
))
{
while
(
get_
reversed_post_order
(
b2
)
>
get_reversed
_post_order
(
b1
))
{
b2
=
get_idom
(
b2
);
}
}
...
...
@@ -84,6 +84,12 @@ BasicBlock *Dominators::intersect(BasicBlock *b1, const BasicBlock *b2) const
void
Dominators
::
create_reverse_post_order
()
{
std
::
set
<
BasicBlock
*>
visited
;
dfs
(
f_
->
get_entry_block
(),
visited
);
int
size
=
static_cast
<
int
>
(
reversed_post_order_vec_
.
size
())
-
1
;
for
(
auto
&
it
:
reversed_post_order_
)
{
it
.
second
=
size
-
it
.
second
;
reversed_post_order_vec_
[
it
.
second
]
=
it
.
first
;
}
}
/**
...
...
@@ -100,8 +106,8 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) {
dfs
(
succ
,
visited
);
}
}
post_order_vec_
.
push_back
(
bb
);
post_order_
.
insert
({
bb
,
post_order_
.
size
()});
reversed_
post_order_vec_
.
push_back
(
bb
);
reversed_post_order_
.
insert
({
bb
,
reversed_
post_order_
.
size
()});
}
/**
...
...
@@ -111,38 +117,28 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) {
*/
void
Dominators
::
create_idom
()
{
// 可能有用的数据结构
// post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
//
post_order_ map<BasicBlock*, unsigned int>, 每个基本块在
post_order_vec_ 中的索引
//
reversed_
post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
//
reversed_post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 reversed_
post_order_vec_ 中的索引
// 可能有用的函数
// intersect(BasicBlock *, BasicBlock *) 寻找两个基本块在支配树上的最近祖先
// 需要填写
// idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a (或者 idom_[a] = a 代表 a 没有直接支配者)
// 代表基本块的直接支配者是否已经确定, 不会在迭代中改变 (默认初始化为 false)
bool
*
already_determined
=
new
bool
[
post_order_vec_
.
size
()]{};
int
bb_count
=
static_cast
<
int
>
(
reversed_post_order_vec_
.
size
());
int
bb_count
=
static_cast
<
int
>
(
post_order_vec_
.
size
());
for
(
int
i
=
0
;
i
<
bb_count
;
i
++
)
{
auto
bb
=
post_order_vec_
[
i
];
// TODO 填写可以直接确定直接支配者, 无需参与迭代的基本块的 idom_ 和 already_determined
throw
"Unimplemented create_idom"
;
}
idom_
[
reversed_post_order_vec_
[
0
]]
=
reversed_post_order_vec_
[
0
];
bool
changed
;
do
{
changed
=
false
;
for
(
int
i
=
0
;
i
<
bb_count
;
i
++
)
for
(
int
i
=
1
;
i
<
bb_count
;
i
++
)
{
if
(
already_determined
[
i
])
continue
;
auto
bb
=
post_order_vec_
[
i
];
auto
bb
=
reversed_post_order_vec_
[
i
];
// TODO 更新基本块 bb 的 idom_, 设置 changed(如果 idom_ 有变化)
throw
"Unimplemented create_idom"
;
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
)
;
}
}
while
(
changed
);
delete
[]
already_determined
;
}
/**
...
...
@@ -154,19 +150,19 @@ void Dominators::create_idom() {
*/
void
Dominators
::
create_dominance_frontier
()
{
// 可能有用的数据结构
// post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
//
post_order_ map<BasicBlock*, unsigned int>, 每个基本块在
post_order_vec_ 中的索引
//
reversed_
post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
//
reversed_post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 reversed_
post_order_vec_ 中的索引
// idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent
// (或者 idom_[a] = a 代表 a 没有直接支配者)
// 需要填写
// dom_frontier_ map<BasicBlock*, set<BasicBlock*>> 支配边界
int
bb_count
=
static_cast
<
int
>
(
post_order_vec_
.
size
());
int
bb_count
=
static_cast
<
int
>
(
reversed_
post_order_vec_
.
size
());
for
(
int
i
=
0
;
i
<
bb_count
;
i
++
)
{
auto
bb
=
post_order_vec_
[
i
];
auto
bb
=
reversed_
post_order_vec_
[
i
];
// TODO 计算 bb 的支配边界集合, 填入 dom_frontier_
throw
"Unimplemented create_dominance_frontier"
;
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
)
;
}
}
...
...
@@ -183,7 +179,8 @@ void Dominators::create_dom_tree_succ() {
// dom_tree_succ_blocks_ map<BasicBlock*, set<BasicBlock*>> 支配树中后继(孩子)节点
// TODO 分析得到 f_ 中各个基本块的支配树后继
throw
"Unimplemented create_dom_tree_succ"
;
// 注意如果 idom_[n] = n, 这意味着 n 没有直接支配者,因此 n 的后继中没有 n
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
}
/**
...
...
src/passes/FuncInfo.cpp
View file @
f40efe88
...
...
@@ -174,6 +174,21 @@ std::unordered_set<Value*> FuncInfo::get_stores(const CallInst* call)
return
ret
;
}
std
::
unordered_set
<
Value
*>
FuncInfo
::
get_loads
(
const
CallInst
*
call
)
{
auto
func
=
call
->
get_operand
(
0
)
->
as
<
Function
>
();
if
(
func
->
is_declaration
())
return
{};
std
::
unordered_set
<
Value
*>
ret
;
for
(
auto
i
:
loads
[
func
].
globals_
)
ret
.
emplace
(
i
);
for
(
auto
arg
:
loads
[
func
].
arguments_
)
{
int
arg_no
=
static_cast
<
int
>
(
arg
->
get_arg_no
());
auto
in
=
call
->
get_operand
(
arg_no
+
1
);
ret
.
emplace
(
trace_ptr
(
in
));
}
return
ret
;
}
void
FuncInfo
::
log
()
const
{
for
(
auto
it
:
use_libs
)
...
...
src/passes/LICM.cpp
View file @
f40efe88
...
...
@@ -67,21 +67,6 @@ std::vector<Instruction*> LoopInvariantCodeMotion::collect_insts(Loop* loop)
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
}
// TODO: 实现collect_loop_info函数
// 1. 遍历当前循环及其子循环的所有指令
// 2. 收集所有指令到loop_instructions中
// 3. 检查store指令是否修改了全局变量,如果是则添加到updated_global中
// 4. 检查是否包含非纯函数调用,如果有则设置contains_impure_call为true
void
LoopInvariantCodeMotion
::
collect_loop_info
(
Loop
*
loop
,
std
::
set
<
Value
*>&
loop_instructions
,
std
::
set
<
Value
*>&
updated_global
,
bool
&
contains_impure_call
)
{
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
}
enum
InstructionType
:
std
::
uint8_t
{
UNKNOWN
,
VARIANT
,
INVARIANT
...
...
@@ -99,19 +84,9 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
// 循环中的所有指令
std
::
vector
<
Instruction
*>
instructions
=
collect_insts
(
loop
);
int
insts_count
=
static_cast
<
int
>
(
instructions
.
size
());
// 循环的所有基本块
std
::
unordered_set
<
BasicBlock
*>
bbs
;
for
(
auto
i
:
loop
->
get_blocks
())
bbs
.
emplace
(
i
);
// val 是否在循环内定义,可以当成函数进行调用
auto
is_val_in_loop
=
[
&
bbs
](
Value
*
val
)
->
bool
{
auto
inst
=
dynamic_cast
<
Instruction
*>
(
val
);
if
(
inst
==
nullptr
)
return
true
;
return
bbs
.
count
(
inst
->
get_parent
());
};
// inst_type[i] 代表 instructions[i] 是循环变量(每次循环都会变)/ 循环不变量 还是 不知道
std
::
vector
<
InstructionType
>
inst_type
;
inst_type
.
resize
(
insts_count
);
// Value* 在 map 内说明它是循环内的指令,InstructionType 指示它是循环变量(每次循环都会变)/ 循环不变量 还是 不知道
std
::
unordered_map
<
Value
*
,
InstructionType
>
inst_type
;
for
(
auto
i
:
instructions
)
inst_type
[
i
]
=
UNKNOWN
;
// 遍历后是不是还有指令不知道 InstructionType
bool
have_inst_can_not_decide
;
...
...
@@ -123,10 +98,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
for
(
int
i
=
0
;
i
<
insts_count
;
i
++
)
{
Instruction
*
inst
=
instructions
[
i
];
InstructionType
type
=
inst_type
[
i
];
InstructionType
type
=
inst_type
[
inst
];
if
(
type
!=
UNKNOWN
)
continue
;
// 可能有用的函数
// FuncInfo::load_ptr
// FuncInfo::load_ptr, FuncInfo::get_stores, FuncInfo::use_io
// TODO: 识别循环不变式指令
// - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT
...
...
@@ -134,6 +109,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
// - 如果指令有 VARIANT 操作数,标记为 VARIANT
// - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant
// - 否则设置 have_inst_can_not_decide
// TODO: 外提循环不变的非纯函数调用
// 注意: 你不应该外提使用了 io 的函数调用
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
}
}
...
...
@@ -152,20 +131,26 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
for
(
auto
phi
:
loop
->
get_header
()
->
get_instructions
())
{
if
(
phi
->
get_instr_type
()
!=
Instruction
::
phi
)
break
;
// 可能有用的函数
// PhiInst::create_phi
// TODO: 分裂 phi 指令
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
}
// 可能有用的函数
// BranchInst::replace_all_bb_match
// TODO: 维护 bb, header, 与 header 前驱块的基本块关系
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
bb
->
add_instruction
(
BranchInst
::
create_br
(
header
,
bb
)
);
BranchInst
::
create_br
(
header
,
bb
);
// 若你想维护 LoopDetection 在 LICM 后保持正确
// auto loop2 = loop->get_parent();
// while (loop2 != nullptr)
// {
// loop2->get_parent()
->add_block(bb);
// loop2
->add_block(bb);
// loop2 = loop2->get_parent();
// }
}
...
...
@@ -177,8 +162,12 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
auto
terminator
=
preheader
->
get_instructions
().
back
();
preheader
->
get_instructions
().
pop_back
();
// 可以使用 Function::check_for_block_relation_error 检查基本块间的关系是否正确维护
// TODO: 外提循环不变指令
throw
std
::
runtime_error
(
"Lab4: 你有一个TODO需要完成!"
);
preheader
->
add_instruction
(
terminator
);
std
::
cerr
<<
"licm done
\n
"
;
}
src/passes/LoopDetection.cpp
View file @
f40efe88
...
...
@@ -54,6 +54,21 @@ void LoopDetection::run() {
delete
dominators_
;
}
std
::
string
Loop
::
safe_print
()
const
{
std
::
string
ret
;
if
(
header_
==
nullptr
)
ret
+=
"b<null>"
;
else
ret
+=
header_
->
get_name
();
ret
+=
" "
;
ret
+=
std
::
to_string
(
blocks_
.
size
());
ret
+=
"b "
;
ret
+=
std
::
to_string
(
latches_
.
size
());
ret
+=
"latch "
;
ret
+=
std
::
to_string
(
sub_loops_
.
size
());
ret
+=
"sub"
;
return
ret
;
}
/**
* @brief 发现循环及其子循环
* @param bb 循环的header块
...
...
@@ -69,10 +84,12 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set<BasicBl
// 5. 建立正确的循环嵌套关系
std
::
vector
<
BasicBlock
*>
work_list
=
{
latches
.
begin
(),
latches
.
end
()};
// 初始化工作表
std
::
unordered_set
<
BasicBlock
*>
already_in_work_list
=
{
latches
.
begin
(),
latches
.
end
()
};
// 已经在工作表,防止重复加入
while
(
!
work_list
.
empty
())
{
// 当工作表非空时继续处理
auto
bb2
=
work_list
.
back
();
work_list
.
pop_back
();
already_in_work_list
.
erase
(
bb2
);
// TODO-1: 处理未分配给任何循环的节点
if
(
bb_to_loop_
.
find
(
bb2
)
==
bb_to_loop_
.
end
())
{
...
...
src/passes/Mem2Reg.cpp
View file @
f40efe88
...
...
@@ -4,11 +4,12 @@
#include "Value.hpp"
//
l_val 是否是非数组 alloca 变量
static
bool
is_not_array_alloca
(
Value
*
l_val
)
//
ptr 是否是非数组 alloca 变量(是则转换为 AllocaInst)
static
AllocaInst
*
is_not_array_alloca
(
Value
*
ptr
)
{
auto
alloca
=
dynamic_cast
<
AllocaInst
*>
(
l_val
);
return
alloca
!=
nullptr
&&
!
alloca
->
get_alloca_type
()
->
is_array_type
();
auto
alloca
=
dynamic_cast
<
AllocaInst
*>
(
ptr
);
if
(
alloca
!=
nullptr
&&
!
alloca
->
get_alloca_type
()
->
is_array_type
())
return
alloca
;
return
nullptr
;
}
/**
...
...
@@ -43,7 +44,7 @@ void Mem2Reg::run() {
generate_phi
();
// 确保每个局部变量的栈都有初始值
for
(
auto
var
:
allocas_
)
var_val_stack
[
var
].
emplace_back
(
ConstantZero
::
get
(
var
->
get_alloca_type
(),
m_
));
var_val_stack
[
var
].
emplace_back
(
var
->
get_alloca_type
()
->
is_float_type
()
?
static_cast
<
Value
*>
(
ConstantFP
::
get
(
0
,
m_
))
:
static_cast
<
Value
*>
(
ConstantInt
::
get
(
0
,
m_
)
));
// 对应伪代码中重命名阶段
rename
(
func_
->
get_entry_block
());
}
...
...
@@ -80,11 +81,13 @@ void Mem2Reg::generate_phi() {
if
(
instr
->
is_store
())
{
// store i32 a, i32 *b
// a is r_val, b is l_val
auto
l_val
=
dynamic_cast
<
StoreInst
*>
(
instr
)
->
get_lval
();
if
(
is_not_array_alloca
(
l_val
))
{
auto
lalloca
=
dynamic_cast
<
AllocaInst
*>
(
instr
);
auto
l_val
=
dynamic_cast
<
StoreInst
*>
(
instr
)
->
get_ptr
();
if
(
auto
lalloca
=
is_not_array_alloca
(
l_val
))
{
if
(
!
not_array_allocas
.
count
(
lalloca
))
{
not_array_allocas
.
insert
(
lalloca
);
allocas_
.
emplace_back
(
lalloca
);
}
allocas_stored_bbs
[
lalloca
].
emplace_back
(
bb
);
}
}
...
...
@@ -115,7 +118,6 @@ void Mem2Reg::generate_phi() {
bb_dominance_frontier_bb
);
phi_to_alloca_
.
emplace
(
phi
,
var
);
bb_to_phi_
[
bb_dominance_frontier_bb
].
emplace_back
(
phi
);
bb_dominance_frontier_bb
->
add_instr_begin
(
phi
);
work_list
.
push_back
(
bb_dominance_frontier_bb
);
bb_has_var_phi
.
emplace
(
bb_dominance_frontier_bb
,
var
);
}
...
...
@@ -128,20 +130,23 @@ void Mem2Reg::rename(BasicBlock *bb) {
// 可能用到的数据结构
// list<AllocaInst*> allocas_ 所有 Mem2Reg 需要消除的局部变量,用于遍历
// map<AllocaInst*,vector<Value *>> var_val_stack 每个局部变量的存储值栈,还未进行任何操作时已经存进去了 0,不会为空
// map<PhiInst *, AllocaInst*>
; Phi 对应的局部变量
// map<BasicBlock*, list<PhiInst*>>
; 在某个基本块的 Phi
// map<PhiInst *, AllocaInst*> phi_to_alloca_
; Phi 对应的局部变量
// map<BasicBlock*, list<PhiInst*>> bb_to_phi_
; 在某个基本块的 Phi
// 可能用到的函数
// Value::replace_all_use_with(Value* a) 将所有用到 this 的指令对应 this 的操作数都替换为 a
// BasicBlock::erase_instrs(set<Instruction*>) 移除并 delete 列表中的指令
// StoreInst / LoadInst get_ptr 这些 Inst 所操作的变量
// is_not_array_alloca(Value* ptr) 一个变量是不是 Mem2Reg 所关心的非数组局部变量
// TODO
// 步骤一:对每个 alloca 非数组变量(局部变量), 在其存储值栈存入其当前的最新值(也就是目前的栈顶值)
// 步骤二:遍历基本块所有指令,执行操作并记录需要删除的 load/store/alloca 指令
// 步骤二:遍历基本块所有指令,执行操作并记录需要删除的 load/store/alloca 指令
(注意: 并非所有 load/store/alloca 都是 Mem2Reg 需要处理的)
// - 步骤三: 将 store 指令存储的值,作为其对应局部变量的最新值(更新栈顶)
// - 步骤四: 将 load 指令的所有使用替换为其读取的局部变量的最新值
// 步骤五:为所有后继块的 phi 添加参数
// 步骤六:对 bb 在支配树上的所有后继节点,递归执行 rename 操作
// 步骤七:pop 出所有局部变量的最新值
// 步骤八:删除需要删除的冗余指令
// - 步骤四: 将 phi 指令的所有使用替换为其对应的局部变量的最新值
// - 步骤五: 将 load 指令的所有使用替换为其读取的局部变量的最新值
// 步骤六:为所有后继块的 phi 添加参数
// 步骤七:对 bb 在支配树上的所有后继节点,递归执行 rename 操作
// 步骤八:pop 出所有局部变量的最新值
// 步骤九:删除需要删除的冗余指令
}
tests/4-opt/CMakeLists.txt
0 → 100644
View file @
f40efe88
add_executable
(
eval_lab4
eval_lab4.cpp
)
install
(
TARGETS eval_lab4
)
\ No newline at end of file
tests/4-opt/eval_lab4.cpp
0 → 100644
View file @
f40efe88
This diff is collapsed.
Click to expand it.
tests/CMakeLists.txt
View file @
f40efe88
add_subdirectory
(
"2-ir-gen/warmup"
)
add_subdirectory
(
"3-codegen/warmup"
)
\ No newline at end of file
# add_subdirectory("2-ir-gen/warmup")
# add_subdirectory("3-codegen/warmup")
add_subdirectory
(
"4-opt"
)
\ No newline at end of file
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