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
18fa0178
Commit
18fa0178
authored
2 years ago
by
陈清源
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lab4 publish
parent
720f0a57
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
866 additions
and
16 deletions
+866
-16
Documentations/4.1-ssa/README.md
Documentations/4.1-ssa/README.md
+305
-0
Documentations/4.1-ssa/ssa.pdf
Documentations/4.1-ssa/ssa.pdf
+0
-0
include/optimization/Dominators.h
include/optimization/Dominators.h
+67
-0
include/optimization/Mem2Reg.hpp
include/optimization/Mem2Reg.hpp
+28
-0
include/optimization/PassManager.hpp
include/optimization/PassManager.hpp
+42
-0
src/CMakeLists.txt
src/CMakeLists.txt
+2
-1
src/cminusfc/cminusfc.cpp
src/cminusfc/cminusfc.cpp
+15
-15
src/optimization/CMakeLists.txt
src/optimization/CMakeLists.txt
+5
-0
src/optimization/Dominators.cpp
src/optimization/Dominators.cpp
+223
-0
src/optimization/Mem2Reg.cpp
src/optimization/Mem2Reg.cpp
+179
-0
No files found.
Documentations/4.1-ssa/README.md
0 → 100644
View file @
18fa0178
This diff is collapsed.
Click to expand it.
Documentations/4.1-ssa/ssa.pdf
0 → 100644
View file @
18fa0178
File added
This diff is collapsed.
Click to expand it.
include/optimization/Dominators.h
0 → 100644
View file @
18fa0178
#ifndef SYSYC_DOMINATORS_HPP
#define SYSYC_DOMINATORS_HPP
#include "BasicBlock.h"
#include "PassManager.hpp"
#include <list>
#include <map>
#include <set>
class
Dominators
:
public
Pass
{
public:
explicit
Dominators
(
Module
*
m
)
:
Pass
(
m
)
{}
~
Dominators
()
=
default
;
void
run
()
override
;
void
create_doms
(
Function
*
f
);
void
create_reverse_post_order
(
Function
*
f
);
void
create_idom
(
Function
*
f
);
void
create_dominance_frontier
(
Function
*
f
);
void
create_dom_tree_succ
(
Function
*
f
);
// for debug
void
print_idom
(
Function
*
f
);
void
print_dominance_frontier
(
Function
*
f
);
/****************api about Dominator****************/
void
add_dom
(
BasicBlock
*
bb
,
BasicBlock
*
dom_bb
)
{
doms_
[
bb
].
insert
(
dom_bb
);
}
std
::
set
<
BasicBlock
*>
&
get_doms
(
BasicBlock
*
bb
)
{
return
doms_
[
bb
];
}
void
set_doms
(
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>
&
doms
)
{
doms_
[
bb
].
clear
();
doms_
[
bb
].
insert
(
doms
.
begin
(),
doms
.
end
());
}
BasicBlock
*
get_idom
(
BasicBlock
*
bb
)
{
return
idom_
[
bb
];
}
void
set_idom
(
BasicBlock
*
bb
,
BasicBlock
*
idom
)
{
idom_
[
bb
]
=
idom
;
}
void
add_dominance_frontier
(
BasicBlock
*
bb
,
BasicBlock
*
dom_frontier_bb
)
{
dom_frontier_
[
bb
].
insert
(
dom_frontier_bb
);
}
std
::
set
<
BasicBlock
*>
&
get_dominance_frontier
(
BasicBlock
*
bb
)
{
return
dom_frontier_
[
bb
];
}
void
set_dominance_frontier
(
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>
&
df
)
{
dom_frontier_
[
bb
].
clear
();
dom_frontier_
[
bb
].
insert
(
df
.
begin
(),
df
.
end
());
}
// successor blocks of this node in dominance tree
std
::
set
<
BasicBlock
*>
get_dom_tree_succ_blocks
(
BasicBlock
*
bb
)
{
return
dom_tree_succ_blocks_
[
bb
];
}
void
add_dom_tree_succ_block
(
BasicBlock
*
bb
,
BasicBlock
*
dom_tree_succ_bb
)
{
dom_tree_succ_blocks_
[
bb
].
insert
(
dom_tree_succ_bb
);
}
/****************api about Dominator****************/
private:
void
post_order_visit
(
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>
&
visited
);
BasicBlock
*
intersect
(
BasicBlock
*
b1
,
BasicBlock
*
b2
);
std
::
list
<
BasicBlock
*>
reverse_post_order_
{};
std
::
map
<
BasicBlock
*
,
int
>
post_order_id_
{};
// the root has highest ID
std
::
map
<
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
doms_
{};
// dominance set
std
::
map
<
BasicBlock
*
,
BasicBlock
*>
idom_
{};
// immediate dominance
std
::
map
<
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_frontier_
{};
// dominance frontier set
std
::
map
<
BasicBlock
*
,
std
::
set
<
BasicBlock
*>>
dom_tree_succ_blocks_
{};
};
#endif
This diff is collapsed.
Click to expand it.
include/optimization/Mem2Reg.hpp
0 → 100644
View file @
18fa0178
#ifndef SYSYC_MEM2REG_HPP
#define SYSYC_MEM2REG_HPP
#include "BasicBlock.h"
#include "Dominators.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Instruction.h"
#include "Module.h"
#include "PassManager.hpp"
#include <memory>
class
Mem2Reg
:
public
Pass
{
private:
Function
*
func_
;
std
::
unique_ptr
<
Dominators
>
dominators_
;
public:
Mem2Reg
(
Module
*
m
)
:
Pass
(
m
)
{}
~
Mem2Reg
(){};
void
run
()
override
;
void
generate_phi
();
void
re_name
(
BasicBlock
*
bb
);
void
remove_alloca
();
};
#endif
\ No newline at end of file
This diff is collapsed.
Click to expand it.
include/optimization/PassManager.hpp
0 → 100644
View file @
18fa0178
#ifndef PASSMANAGER_HPP
#define PASSMANAGER_HPP
#include "Module.h"
#include <memory>
#include <vector>
class
Pass
{
public:
Pass
(
Module
*
m
)
:
m_
(
m
)
{}
virtual
~
Pass
()
=
default
;
virtual
void
run
()
=
0
;
protected:
Module
*
m_
;
};
class
PassManager
{
public:
PassManager
(
Module
*
m
)
:
m_
(
m
)
{}
template
<
typename
PassType
,
typename
...
Args
>
void
add_pass
(
bool
print_ir
,
Args
&&
...
args
)
{
passes_
.
push_back
(
std
::
pair
<
std
::
unique_ptr
<
Pass
>
,
bool
>
(
new
PassType
(
m_
,
std
::
forward
<
Args
>
(
args
)...),
print_ir
));
}
void
run
()
{
for
(
auto
&
pass
:
passes_
)
{
pass
.
first
->
run
();
if
(
pass
.
second
)
{
m_
->
set_print_name
();
std
::
cout
<<
m_
->
print
();
}
}
}
private:
std
::
vector
<
std
::
pair
<
std
::
unique_ptr
<
Pass
>
,
bool
>>
passes_
;
Module
*
m_
;
};
#endif
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/CMakeLists.txt
View file @
18fa0178
...
@@ -2,4 +2,5 @@ add_subdirectory(parser)
...
@@ -2,4 +2,5 @@ add_subdirectory(parser)
add_subdirectory
(
common
)
add_subdirectory
(
common
)
add_subdirectory
(
io
)
add_subdirectory
(
io
)
add_subdirectory
(
lightir
)
add_subdirectory
(
lightir
)
add_subdirectory
(
cminusfc
)
add_subdirectory
(
cminusfc
)
\ No newline at end of file
add_subdirectory
(
optimization
)
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/cminusfc/cminusfc.cpp
View file @
18fa0178
#include "Dominators.h"
#include "Mem2Reg.hpp"
#include "PassManager.hpp"
#include "cminusf_builder.hpp"
#include "cminusf_builder.hpp"
#include "logging.hpp"
#include <fstream>
#include <fstream>
#include <iostream>
#include <iostream>
#include <memory>
#include <memory>
...
@@ -6,20 +11,15 @@
...
@@ -6,20 +11,15 @@
using
namespace
std
::
literals
::
string_literals
;
using
namespace
std
::
literals
::
string_literals
;
void
print_help
(
std
::
string
exe_name
)
{
void
print_help
(
std
::
string
exe_name
)
{
std
::
cout
<<
"Usage: "
<<
exe_name
<<
std
::
cout
<<
"Usage: "
<<
exe_name
<<
" [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] [-mem2reg] <input-file>"
" [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] <input-file>"
<<
std
::
endl
;
<<
std
::
endl
;
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
std
::
string
target_path
;
std
::
string
target_path
;
std
::
string
input_path
;
std
::
string
input_path
;
bool
mem2reg
=
false
;
bool
mem2reg
=
false
;
bool
const_propagation
=
false
;
bool
activevars
=
false
;
bool
loop_inv_hoist
=
false
;
bool
loop_search
=
false
;
bool
emit
=
false
;
bool
emit
=
false
;
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
...
@@ -38,14 +38,6 @@ int main(int argc, char **argv) {
...
@@ -38,14 +38,6 @@ int main(int argc, char **argv) {
emit
=
true
;
emit
=
true
;
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
mem2reg
=
true
;
mem2reg
=
true
;
}
else
if
(
argv
[
i
]
==
"-loop-search"
s
)
{
loop_search
=
true
;
}
else
if
(
argv
[
i
]
==
"-loop-inv-hoist"
s
)
{
loop_inv_hoist
=
true
;
}
else
if
(
argv
[
i
]
==
"-const-propagation"
s
)
{
const_propagation
=
true
;
}
else
if
(
argv
[
i
]
==
"-active-vars"
s
)
{
activevars
=
true
;
}
else
{
}
else
{
if
(
input_path
.
empty
())
{
if
(
input_path
.
empty
())
{
input_path
=
argv
[
i
];
input_path
=
argv
[
i
];
...
@@ -85,6 +77,14 @@ int main(int argc, char **argv) {
...
@@ -85,6 +77,14 @@ int main(int argc, char **argv) {
auto
m
=
builder
.
getModule
();
auto
m
=
builder
.
getModule
();
m
->
set_print_name
();
PassManager
PM
(
m
.
get
());
if
(
mem2reg
)
{
PM
.
add_pass
<
Mem2Reg
>
(
emit
);
}
PM
.
run
();
auto
IR
=
m
->
print
();
auto
IR
=
m
->
print
();
std
::
ofstream
output_stream
;
std
::
ofstream
output_stream
;
...
...
This diff is collapsed.
Click to expand it.
src/optimization/CMakeLists.txt
0 → 100644
View file @
18fa0178
add_library
(
OP_lib STATIC
Dominators.cpp
Mem2Reg.cpp
)
This diff is collapsed.
Click to expand it.
src/optimization/Dominators.cpp
0 → 100644
View file @
18fa0178
#include "Dominators.h"
#include <algorithm>
#include <string>
void
Dominators
::
run
()
{
for
(
auto
&
f1
:
m_
->
get_functions
())
{
auto
f
=
&
f1
;
if
(
f
->
get_basic_blocks
().
size
()
==
0
)
continue
;
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
doms_
.
insert
({
bb
,
{}});
idom_
.
insert
({
bb
,
{}});
dom_frontier_
.
insert
({
bb
,
{}});
dom_tree_succ_blocks_
.
insert
({
bb
,
{}});
}
create_reverse_post_order
(
f
);
create_idom
(
f
);
create_dominance_frontier
(
f
);
create_dom_tree_succ
(
f
);
// for debug
// print_idom(f);
// print_dominance_frontier(f);
}
}
void
Dominators
::
create_doms
(
Function
*
f
)
{
// init
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
add_dom
(
bb
,
bb
);
}
// iterate
bool
changed
=
true
;
std
::
vector
<
BasicBlock
*>
ret
(
f
->
get_num_basic_blocks
());
std
::
vector
<
BasicBlock
*>
pre
(
f
->
get_num_basic_blocks
());
while
(
changed
)
{
changed
=
false
;
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
auto
&
bbs
=
bb
->
get_pre_basic_blocks
();
auto
&
first
=
get_doms
((
*
bbs
.
begin
()));
pre
.
insert
(
pre
.
begin
(),
first
.
begin
(),
first
.
end
());
pre
.
resize
(
first
.
size
());
ret
.
resize
(
f
->
get_num_basic_blocks
());
for
(
auto
iter
=
++
bbs
.
begin
();
iter
!=
bbs
.
end
();
++
iter
)
{
auto
&
now
=
get_doms
((
*
iter
));
auto
it
=
std
::
set_intersection
(
pre
.
begin
(),
pre
.
end
(),
now
.
begin
(),
now
.
end
(),
ret
.
begin
());
ret
.
resize
(
it
-
ret
.
begin
());
pre
.
resize
(
ret
.
size
());
pre
.
insert
(
pre
.
begin
(),
ret
.
begin
(),
ret
.
end
());
}
std
::
set
<
BasicBlock
*>
doms
;
doms
.
insert
(
bb
);
doms
.
insert
(
pre
.
begin
(),
pre
.
end
());
if
(
get_doms
(
bb
)
!=
doms
)
{
set_doms
(
bb
,
doms
);
changed
=
true
;
}
}
}
}
void
Dominators
::
create_reverse_post_order
(
Function
*
f
)
{
reverse_post_order_
.
clear
();
post_order_id_
.
clear
();
std
::
set
<
BasicBlock
*>
visited
;
post_order_visit
(
f
->
get_entry_block
(),
visited
);
reverse_post_order_
.
reverse
();
}
void
Dominators
::
post_order_visit
(
BasicBlock
*
bb
,
std
::
set
<
BasicBlock
*>
&
visited
)
{
visited
.
insert
(
bb
);
for
(
auto
b
:
bb
->
get_succ_basic_blocks
())
{
if
(
visited
.
find
(
b
)
==
visited
.
end
())
post_order_visit
(
b
,
visited
);
}
post_order_id_
[
bb
]
=
reverse_post_order_
.
size
();
reverse_post_order_
.
push_back
(
bb
);
}
void
Dominators
::
create_idom
(
Function
*
f
)
{
// init
for
(
auto
&
bb
:
f
->
get_basic_blocks
())
set_idom
(
&
bb
,
nullptr
);
auto
root
=
f
->
get_entry_block
();
set_idom
(
root
,
root
);
// iterate
bool
changed
=
true
;
while
(
changed
)
{
changed
=
false
;
for
(
auto
bb
:
this
->
reverse_post_order_
)
{
if
(
bb
==
root
)
{
continue
;
}
// find one pred which has idom
BasicBlock
*
pred
=
nullptr
;
for
(
auto
p
:
bb
->
get_pre_basic_blocks
())
{
if
(
get_idom
(
p
))
{
pred
=
p
;
break
;
}
}
assert
(
pred
);
BasicBlock
*
new_idom
=
pred
;
for
(
auto
p
:
bb
->
get_pre_basic_blocks
())
{
if
(
p
==
pred
)
continue
;
if
(
get_idom
(
p
))
{
new_idom
=
intersect
(
p
,
new_idom
);
}
}
if
(
get_idom
(
bb
)
!=
new_idom
)
{
set_idom
(
bb
,
new_idom
);
changed
=
true
;
}
}
}
}
// find closest parent of b1 and b2
BasicBlock
*
Dominators
::
intersect
(
BasicBlock
*
b1
,
BasicBlock
*
b2
)
{
while
(
b1
!=
b2
)
{
while
(
post_order_id_
[
b1
]
<
post_order_id_
[
b2
])
{
assert
(
get_idom
(
b1
));
b1
=
get_idom
(
b1
);
}
while
(
post_order_id_
[
b2
]
<
post_order_id_
[
b1
])
{
assert
(
get_idom
(
b2
));
b2
=
get_idom
(
b2
);
}
}
return
b1
;
}
void
Dominators
::
create_dominance_frontier
(
Function
*
f
)
{
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
if
(
bb
->
get_pre_basic_blocks
().
size
()
>=
2
)
{
for
(
auto
p
:
bb
->
get_pre_basic_blocks
())
{
auto
runner
=
p
;
while
(
runner
!=
get_idom
(
bb
))
{
add_dominance_frontier
(
runner
,
bb
);
runner
=
get_idom
(
runner
);
}
}
}
}
}
void
Dominators
::
create_dom_tree_succ
(
Function
*
f
)
{
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
auto
idom
=
get_idom
(
bb
);
// e.g, entry bb
if
(
idom
!=
bb
)
{
add_dom_tree_succ_block
(
idom
,
bb
);
}
}
}
void
Dominators
::
print_idom
(
Function
*
f
)
{
int
counter
=
0
;
std
::
map
<
BasicBlock
*
,
std
::
string
>
bb_id
;
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
if
(
bb
->
get_name
().
empty
())
bb_id
[
bb
]
=
"bb"
+
std
::
to_string
(
counter
);
else
bb_id
[
bb
]
=
bb
->
get_name
();
counter
++
;
}
printf
(
"Immediate dominance of function %s:
\n
"
,
f
->
get_name
().
c_str
());
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
std
::
string
output
;
output
=
bb_id
[
bb
]
+
": "
;
if
(
get_idom
(
bb
))
{
output
+=
bb_id
[
get_idom
(
bb
)];
}
else
{
output
+=
"null"
;
}
printf
(
"%s
\n
"
,
output
.
c_str
());
}
}
void
Dominators
::
print_dominance_frontier
(
Function
*
f
)
{
int
counter
=
0
;
std
::
map
<
BasicBlock
*
,
std
::
string
>
bb_id
;
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
if
(
bb
->
get_name
().
empty
())
bb_id
[
bb
]
=
"bb"
+
std
::
to_string
(
counter
);
else
bb_id
[
bb
]
=
bb
->
get_name
();
counter
++
;
}
printf
(
"Dominance Frontier of function %s:
\n
"
,
f
->
get_name
().
c_str
());
for
(
auto
&
bb1
:
f
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
std
::
string
output
;
output
=
bb_id
[
bb
]
+
": "
;
if
(
get_dominance_frontier
(
bb
).
empty
())
{
output
+=
"null"
;
}
else
{
bool
first
=
true
;
for
(
auto
df
:
get_dominance_frontier
(
bb
))
{
if
(
first
)
{
first
=
false
;
}
else
{
output
+=
", "
;
}
output
+=
bb_id
[
df
];
}
}
printf
(
"%s
\n
"
,
output
.
c_str
());
}
}
This diff is collapsed.
Click to expand it.
src/optimization/Mem2Reg.cpp
0 → 100644
View file @
18fa0178
#include "Mem2Reg.hpp"
#include "IRBuilder.h"
#include <memory>
// 判断是否是全局变量地址
#define IS_GLOBAL_VARIABLE(l_val) dynamic_cast<GlobalVariable *>(l_val)
// 判断是否是 getelementptr 指令
#define IS_GEP_INSTR(l_val) dynamic_cast<GetElementPtrInst *>(l_val)
std
::
map
<
Value
*
,
std
::
vector
<
Value
*>>
var_val_stack
;
// 全局变量初值提前存入栈中
void
Mem2Reg
::
run
()
{
// 创建支配树分析 Pass 的实例
dominators_
=
std
::
make_unique
<
Dominators
>
(
m_
);
// 建立支配树
dominators_
->
run
();
// 以函数为单元遍历实现 Mem2Reg 算法
for
(
auto
&
f
:
m_
->
get_functions
())
{
func_
=
&
f
;
if
(
func_
->
get_basic_blocks
().
size
()
>=
1
)
{
// 对应伪代码中 phi 指令插入的阶段
generate_phi
();
// 对应伪代码中重命名阶段
re_name
(
func_
->
get_entry_block
());
}
// 移除冗余的局部变量的分配空间
remove_alloca
();
}
}
void
Mem2Reg
::
generate_phi
()
{
// global_live_var_name 是全局名字集合,以 alloca 出的局部变量来统计。
// 步骤一:找到活跃在多个 block 的全局名字集合,以及它们所属的 bb 块
std
::
set
<
Value
*>
global_live_var_name
;
std
::
map
<
Value
*
,
std
::
set
<
BasicBlock
*>>
live_var_2blocks
;
for
(
auto
&
bb1
:
func_
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
std
::
set
<
Value
*>
var_is_killed
;
for
(
auto
&
instr1
:
bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
if
(
instr
->
is_store
())
{
// store i32 a, i32 *b
// a is r_val, b is l_val
auto
r_val
=
static_cast
<
StoreInst
*>
(
instr
)
->
get_rval
();
auto
l_val
=
static_cast
<
StoreInst
*>
(
instr
)
->
get_lval
();
if
(
!
IS_GLOBAL_VARIABLE
(
l_val
)
&&
!
IS_GEP_INSTR
(
l_val
))
{
global_live_var_name
.
insert
(
l_val
);
live_var_2blocks
[
l_val
].
insert
(
bb
);
}
}
}
}
// 步骤二:从支配树获取支配边界信息,并在对应位置插入 phi 指令
std
::
map
<
std
::
pair
<
BasicBlock
*
,
Value
*>
,
bool
>
bb_has_var_phi
;
// bb has phi for var
for
(
auto
var
:
global_live_var_name
)
{
std
::
vector
<
BasicBlock
*>
work_list
;
work_list
.
assign
(
live_var_2blocks
[
var
].
begin
(),
live_var_2blocks
[
var
].
end
());
for
(
int
i
=
0
;
i
<
work_list
.
size
();
i
++
)
{
auto
bb
=
work_list
[
i
];
for
(
auto
bb_dominance_frontier_bb
:
dominators_
->
get_dominance_frontier
(
bb
))
{
if
(
bb_has_var_phi
.
find
({
bb_dominance_frontier_bb
,
var
})
==
bb_has_var_phi
.
end
())
{
// generate phi for bb_dominance_frontier_bb & add bb_dominance_frontier_bb to work list
auto
phi
=
PhiInst
::
create_phi
(
var
->
get_type
()
->
get_pointer_element_type
(),
bb_dominance_frontier_bb
);
phi
->
set_lval
(
var
);
bb_dominance_frontier_bb
->
add_instr_begin
(
phi
);
work_list
.
push_back
(
bb_dominance_frontier_bb
);
bb_has_var_phi
[{
bb_dominance_frontier_bb
,
var
}]
=
true
;
}
}
}
}
}
void
Mem2Reg
::
re_name
(
BasicBlock
*
bb
)
{
std
::
vector
<
Instruction
*>
wait_delete
;
// 步骤三:将 phi 指令作为 lval 的最新定值,lval 即是为局部变量 alloca 出的地址空间
for
(
auto
&
instr1
:
bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
if
(
instr
->
is_phi
())
{
auto
l_val
=
static_cast
<
PhiInst
*>
(
instr
)
->
get_lval
();
var_val_stack
[
l_val
].
push_back
(
instr
);
}
}
for
(
auto
&
instr1
:
bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
// 步骤四:用 lval 最新的定值替代对应的load指令
if
(
instr
->
is_load
())
{
auto
l_val
=
static_cast
<
LoadInst
*>
(
instr
)
->
get_lval
();
if
(
!
IS_GLOBAL_VARIABLE
(
l_val
)
&&
!
IS_GEP_INSTR
(
l_val
))
{
if
(
var_val_stack
.
find
(
l_val
)
!=
var_val_stack
.
end
())
{
// 此处指令替换会维护 UD 链与 DU 链
instr
->
replace_all_use_with
(
var_val_stack
[
l_val
].
back
());
wait_delete
.
push_back
(
instr
);
}
}
}
// 步骤五:将 store 指令的 rval,也即被存入内存的值,作为 lval 的最新定值
if
(
instr
->
is_store
())
{
auto
l_val
=
static_cast
<
StoreInst
*>
(
instr
)
->
get_lval
();
auto
r_val
=
static_cast
<
StoreInst
*>
(
instr
)
->
get_rval
();
if
(
!
IS_GLOBAL_VARIABLE
(
l_val
)
&&
!
IS_GEP_INSTR
(
l_val
))
{
var_val_stack
[
l_val
].
push_back
(
r_val
);
wait_delete
.
push_back
(
instr
);
}
}
}
// 步骤六:为 lval 对应的 phi 指令参数补充完整
for
(
auto
succ_bb
:
bb
->
get_succ_basic_blocks
())
{
for
(
auto
&
instr1
:
succ_bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
if
(
instr
->
is_phi
())
{
auto
l_val
=
static_cast
<
PhiInst
*>
(
instr
)
->
get_lval
();
if
(
var_val_stack
.
find
(
l_val
)
!=
var_val_stack
.
end
())
{
assert
(
var_val_stack
[
l_val
].
size
()
!=
0
);
static_cast
<
PhiInst
*>
(
instr
)
->
add_phi_pair_operand
(
var_val_stack
[
l_val
].
back
(),
bb
);
}
// 对于 phi 参数只有一个前驱定值的情况,将会输出 [ undef, bb ] 的参数格式
}
}
}
// 步骤七:对 bb 在支配树上的所有后继节点,递归执行 re_name 操作
for
(
auto
dom_succ_bb
:
dominators_
->
get_dom_tree_succ_blocks
(
bb
))
{
re_name
(
dom_succ_bb
);
}
// 步骤八:pop出 lval 的最新定值
for
(
auto
&
instr1
:
bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
if
(
instr
->
is_store
())
{
auto
l_val
=
static_cast
<
StoreInst
*>
(
instr
)
->
get_lval
();
if
(
!
IS_GLOBAL_VARIABLE
(
l_val
)
&&
!
IS_GEP_INSTR
(
l_val
))
{
var_val_stack
[
l_val
].
pop_back
();
}
}
else
if
(
instr
->
is_phi
())
{
auto
l_val
=
static_cast
<
PhiInst
*>
(
instr
)
->
get_lval
();
if
(
var_val_stack
.
find
(
l_val
)
!=
var_val_stack
.
end
())
{
var_val_stack
[
l_val
].
pop_back
();
}
}
}
// 清除冗余的指令
for
(
auto
instr
:
wait_delete
)
{
bb
->
erase_instr
(
instr
);
}
}
void
Mem2Reg
::
remove_alloca
()
{
for
(
auto
&
bb1
:
func_
->
get_basic_blocks
())
{
auto
bb
=
&
bb1
;
std
::
vector
<
Instruction
*>
wait_delete
;
for
(
auto
&
instr1
:
bb
->
get_instructions
())
{
auto
instr
=
&
instr1
;
auto
is_alloca
=
dynamic_cast
<
AllocaInst
*>
(
instr
);
if
(
is_alloca
)
{
bool
is_int
=
is_alloca
->
get_type
()
->
get_pointer_element_type
()
->
is_integer_type
();
bool
is_float
=
is_alloca
->
get_type
()
->
get_pointer_element_type
()
->
is_float_type
();
if
(
is_int
||
is_float
)
{
wait_delete
.
push_back
(
instr
);
}
}
}
for
(
auto
instr
:
wait_delete
)
{
bb
->
erase_instr
(
instr
);
}
}
}
This diff is collapsed.
Click to expand it.
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