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
08898ecb
Commit
08898ecb
authored
Dec 06, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
now shuold pass loop3!
parent
b1f2b21d
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
244 additions
and
67 deletions
+244
-67
include/optimization/GVN.h
include/optimization/GVN.h
+22
-8
src/optimization/GVN.cpp
src/optimization/GVN.cpp
+218
-59
tests/4-ir-opt/testcases/GVN/functional/.gitignore
tests/4-ir-opt/testcases/GVN/functional/.gitignore
+3
-0
tests/4-ir-opt/testcases/GVN/functional/clear.sh
tests/4-ir-opt/testcases/GVN/functional/clear.sh
+1
-0
No files found.
include/optimization/GVN.h
View file @
08898ecb
...
@@ -69,6 +69,8 @@ class ConstantExpression : public Expression {
...
@@ -69,6 +69,8 @@ class ConstantExpression : public Expression {
}
}
ConstantExpression
(
Constant
*
c
)
:
Expression
(
e_constant
),
c_
(
c
)
{}
ConstantExpression
(
Constant
*
c
)
:
Expression
(
e_constant
),
c_
(
c
)
{}
Constant
*
get_val
()
{
return
c_
;
}
private:
private:
Constant
*
c_
;
Constant
*
c_
;
};
};
...
@@ -199,20 +201,24 @@ class GEPExpression : public Expression {
...
@@ -199,20 +201,24 @@ class GEPExpression : public Expression {
// unique expression: not equal to any one else
// unique expression: not equal to any one else
class
UniqueExpression
:
public
Expression
{
class
UniqueExpression
:
public
Expression
{
public:
public:
static
std
::
shared_ptr
<
UniqueExpression
>
create
(
Instruction
*
instr
)
{
static
std
::
shared_ptr
<
UniqueExpression
>
create
(
Instruction
*
instr
,
return
std
::
make_shared
<
UniqueExpression
>
(
instr
);
size_t
index
)
{
return
std
::
make_shared
<
UniqueExpression
>
(
instr
,
index
);
}
}
virtual
std
::
string
print
()
{
return
"(UNIQUE "
+
instr_
->
print
()
+
")"
;
}
// virtual std::string print() { return "(UNIQUE " + instr_->print() + ")";
// }
virtual
std
::
string
print
()
{
return
"v"
+
std
::
to_string
(
index_
);
}
bool
equiv
(
const
UniqueExpression
*
other
)
const
{
bool
equiv
(
const
UniqueExpression
*
other
)
const
{
return
instr_
==
other
->
instr_
;
return
instr_
==
other
->
instr_
;
}
}
UniqueExpression
(
Instruction
*
instr
)
UniqueExpression
(
Instruction
*
instr
,
size_t
index
)
:
Expression
(
e_unique
),
instr_
(
instr
)
{}
:
Expression
(
e_unique
),
instr_
(
instr
)
,
index_
(
index
)
{}
private:
private:
Instruction
*
instr_
;
Instruction
*
instr_
;
size_t
index_
;
};
};
}
// namespace GVNExpression
}
// namespace GVNExpression
...
@@ -276,7 +282,8 @@ class GVN : public Pass {
...
@@ -276,7 +282,8 @@ class GVN : public Pass {
partitions
transferFunction
(
BasicBlock
*
bb
);
partitions
transferFunction
(
BasicBlock
*
bb
);
std
::
shared_ptr
<
GVNExpression
::
PhiExpression
>
valuePhiFunc
(
std
::
shared_ptr
<
GVNExpression
::
PhiExpression
>
valuePhiFunc
(
std
::
shared_ptr
<
GVNExpression
::
Expression
>
,
std
::
shared_ptr
<
GVNExpression
::
Expression
>
,
BasicBlock
*
bb
);
BasicBlock
*
bb
,
Instruction
*
instr
);
std
::
shared_ptr
<
GVNExpression
::
Expression
>
valueExpr
(
std
::
shared_ptr
<
GVNExpression
::
Expression
>
valueExpr
(
Instruction
*
instr
,
Instruction
*
instr
,
const
partitions
&
part
);
const
partitions
&
part
);
...
@@ -308,6 +315,7 @@ class GVN : public Pass {
...
@@ -308,6 +315,7 @@ class GVN : public Pass {
std
::
map
<
BasicBlock
*
,
bool
>
_TOP
;
std
::
map
<
BasicBlock
*
,
bool
>
_TOP
;
partitions
join_helper
(
BasicBlock
*
pre1
,
BasicBlock
*
pre2
);
partitions
join_helper
(
BasicBlock
*
pre1
,
BasicBlock
*
pre2
);
BasicBlock
*
curr_bb
;
BasicBlock
*
curr_bb
;
std
::
map
<
std
::
pair
<
Instruction
*
,
Value
*>
,
size_t
>
start_idx_
;
//
//
// self add function
// self add function
//
//
...
@@ -317,11 +325,17 @@ class GVN : public Pass {
...
@@ -317,11 +325,17 @@ class GVN : public Pass {
Value
*
v
,
Value
*
v
,
const
partitions
&
part
);
const
partitions
&
part
);
std
::
vector
<
std
::
shared_ptr
<
GVNExpression
::
Expression
>>
core_
(
std
::
vector
<
std
::
shared_ptr
<
GVNExpression
::
Expression
>>
valueExpr_
core_
(
Instruction
*
instr
,
Instruction
*
instr
,
const
partitions
&
part
,
const
partitions
&
part
,
size_t
count
,
const
size_t
count
,
bool
fold_
=
true
);
bool
fold_
=
true
);
Constant
*
constFold_core
(
const
size_t
count
,
const
partitions
&
part
,
Instruction
*
instr
,
const
std
::
vector
<
Value
*>
&
operands
);
void
assign_start_idx_
();
void
dump_tmp
(
Function
&
);
};
};
bool
operator
==
(
const
GVN
::
partitions
&
p1
,
const
GVN
::
partitions
&
p2
);
bool
operator
==
(
const
GVN
::
partitions
&
p1
,
const
GVN
::
partitions
&
p2
);
src/optimization/GVN.cpp
View file @
08898ecb
...
@@ -199,6 +199,8 @@ dump_bb2partition(const std::map<BasicBlock *, GVN::partitions> &map) {
...
@@ -199,6 +199,8 @@ dump_bb2partition(const std::map<BasicBlock *, GVN::partitions> &map) {
static
void
static
void
print_partitions
(
const
GVN
::
partitions
&
p
)
{
print_partitions
(
const
GVN
::
partitions
&
p
)
{
if
(
p
.
empty
())
{
if
(
p
.
empty
())
{
// to del
// std::cout << "empty partitions\n";
LOG_DEBUG
<<
"empty partitions
\n
"
;
LOG_DEBUG
<<
"empty partitions
\n
"
;
return
;
return
;
}
}
...
@@ -206,13 +208,14 @@ print_partitions(const GVN::partitions &p) {
...
@@ -206,13 +208,14 @@ print_partitions(const GVN::partitions &p) {
for
(
auto
&
cc
:
p
)
for
(
auto
&
cc
:
p
)
log
+=
print_congruence_class
(
*
cc
);
log
+=
print_congruence_class
(
*
cc
);
LOG_DEBUG
<<
log
;
// please don't use std::cout
LOG_DEBUG
<<
log
;
// please don't use std::cout
// to del
// std::cout << log;
}
}
}
// namespace utils
}
// namespace utils
GVN
::
partitions
GVN
::
partitions
GVN
::
join_helper
(
BasicBlock
*
pre1
,
BasicBlock
*
pre2
)
{
GVN
::
join_helper
(
BasicBlock
*
pre1
,
BasicBlock
*
pre2
)
{
assert
(
not
_TOP
[
pre1
]
or
not
_TOP
[
pre2
]
&&
"should flow here, not jump"
);
assert
(
not
_TOP
[
pre1
]
or
not
_TOP
[
pre2
]
&&
"should flow here, not jump"
);
if
(
_TOP
[
pre1
])
if
(
_TOP
[
pre1
])
return
pout_
[
pre2
];
return
pout_
[
pre2
];
else
if
(
_TOP
[
pre2
])
else
if
(
_TOP
[
pre2
])
...
@@ -260,25 +263,70 @@ GVN::intersect(shared_ptr<CongruenceClass> ci, shared_ptr<CongruenceClass> cj) {
...
@@ -260,25 +263,70 @@ GVN::intersect(shared_ptr<CongruenceClass> ci, shared_ptr<CongruenceClass> cj) {
if
(
c
->
members_
.
size
())
// not empty
if
(
c
->
members_
.
size
())
// not empty
{
{
if
(
c
->
index_
==
0
)
{
if
(
c
->
index_
==
0
)
{
c
->
index_
=
new_number
();
// it must be a phi instruction
// and be separated to 2 copy statement
// we should use the copy-stmt int the previous block
auto
instr
=
static_cast
<
Instruction
*>
(
*
c
->
members_
.
begin
());
auto
instr_phi
=
dynamic_cast
<
PhiInst
*>
(
instr
);
int
exact_idx
;
// trick here: use the exact value number
if
(
instr_phi
)
{
auto
exact_pre_bb
=
*
(
instr_phi
->
get_parent
()
->
get_pre_basic_blocks
().
begin
());
auto
e
=
instr_phi
->
get_operand
(
pretend_copy_stmt
(
instr_phi
,
exact_pre_bb
));
exact_idx
=
start_idx_
.
at
(
std
::
make_pair
(
instr_phi
,
e
));
}
else
{
exact_idx
=
start_idx_
.
at
(
std
::
make_pair
(
instr
,
nullptr
));
}
c
->
index_
=
exact_idx
;
c
->
value_expr_
=
c
->
value_phi_
=
c
->
value_expr_
=
c
->
value_phi_
=
PhiExpression
::
create
(
ci
->
value_expr_
,
cj
->
value_expr_
);
PhiExpression
::
create
(
ci
->
value_expr_
,
cj
->
value_expr_
);
}
}
// ??
c
->
leader_
=
*
c
->
members_
.
begin
();
c
->
leader_
=
*
c
->
members_
.
begin
();
}
}
return
c
;
return
c
;
}
}
// assign start index for each instruction, including copy statement
// ther logic here:
// - use the same traver order as main run
// - assign an incremental number for each instruction
void
GVN
::
assign_start_idx_
()
{
int
res
;
for
(
auto
&
bb
:
func_
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
{
if
(
not
instr
.
is_phi
()
and
not
instr
.
is_void
())
start_idx_
[
std
::
make_pair
(
&
instr
,
nullptr
)]
=
new_number
();
}
// and the phi instruction in all the successors
for
(
auto
succ
:
bb
.
get_succ_basic_blocks
())
{
for
(
auto
&
instr
:
succ
->
get_instructions
())
{
if
(
instr
.
is_phi
())
{
if
((
res
=
pretend_copy_stmt
(
&
instr
,
&
bb
))
==
-
1
)
continue
;
start_idx_
[
std
::
make_pair
(
&
instr
,
instr
.
get_operand
(
res
))]
=
new_number
();
}
}
}
}
next_value_number_
=
1
;
}
void
void
GVN
::
detectEquivalences
()
{
GVN
::
detectEquivalences
()
{
int
times
=
0
;
bool
changed
;
bool
changed
;
std
::
cout
<<
"all the instruction address:"
<<
std
::
endl
;
std
::
cout
<<
"all the instruction address:"
<<
std
::
endl
;
for
(
auto
&
bb
:
func_
->
get_basic_blocks
())
{
for
(
auto
&
bb
:
func_
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
for
(
auto
&
instr
:
bb
.
get_instructions
())
std
::
cout
<<
&
instr
<<
"
\t
"
<<
instr
.
print
()
<<
std
::
endl
;
std
::
cout
<<
&
instr
<<
"
\t
"
<<
instr
.
print
()
<<
std
::
endl
;
}
}
assign_start_idx_
();
// initialize pout with top
// initialize pout with top
for
(
auto
&
bb
:
func_
->
get_basic_blocks
())
{
for
(
auto
&
bb
:
func_
->
get_basic_blocks
())
{
_TOP
[
&
bb
]
=
true
;
_TOP
[
&
bb
]
=
true
;
...
@@ -293,6 +341,7 @@ GVN::detectEquivalences() {
...
@@ -293,6 +341,7 @@ GVN::detectEquivalences() {
// iterate until converge
// iterate until converge
do
{
do
{
changed
=
false
;
changed
=
false
;
std
::
cout
<<
++
times
<<
"th iteration"
<<
std
::
endl
;
for
(
auto
&
_bb
:
func_
->
get_basic_blocks
())
{
for
(
auto
&
_bb
:
func_
->
get_basic_blocks
())
{
auto
bb
=
&
_bb
;
auto
bb
=
&
_bb
;
if
(
bb
==
Entry
)
if
(
bb
==
Entry
)
...
@@ -306,12 +355,12 @@ GVN::detectEquivalences() {
...
@@ -306,12 +355,12 @@ GVN::detectEquivalences() {
case
2
:
{
case
2
:
{
auto
pre_1
=
*
pre_bbs_
.
begin
();
auto
pre_1
=
*
pre_bbs_
.
begin
();
auto
pre_2
=
*
(
++
pre_bbs_
.
begin
());
auto
pre_2
=
*
(
++
pre_bbs_
.
begin
());
pin_
[
bb
]
=
join_helper
(
pre_1
,
pre_2
);
pin_
[
bb
]
=
clone
(
join_helper
(
pre_1
,
pre_2
)
);
break
;
break
;
}
}
case
1
:
{
case
1
:
{
auto
pre
=
*
(
pre_bbs_
.
begin
());
auto
pre
=
*
(
pre_bbs_
.
begin
());
pin_
[
bb
]
=
pout_
[
pre
]
;
pin_
[
bb
]
=
clone
(
pout_
[
pre
])
;
break
;
break
;
}
}
default:
default:
...
@@ -324,9 +373,15 @@ GVN::detectEquivalences() {
...
@@ -324,9 +373,15 @@ GVN::detectEquivalences() {
// check changes in pout
// check changes in pout
changed
|=
not
(
part
==
pout_
[
bb
]);
changed
|=
not
(
part
==
pout_
[
bb
]);
pout_
[
bb
]
=
part
;
pout_
[
bb
]
=
clone
(
part
)
;
_TOP
[
bb
]
=
false
;
_TOP
[
bb
]
=
false
;
/* std::cout << "//-------\n"
* << "//after transferFunction(basic-block="
* << bb->get_name() << "), all pout:" << std::endl; */
// dump_tmp(*func_);
}
}
// reset value number
}
while
(
changed
);
}
while
(
changed
);
}
}
...
@@ -343,11 +398,51 @@ GVN::search_ve(Value *v, const GVN::partitions &part) {
...
@@ -343,11 +398,51 @@ GVN::search_ve(Value *v, const GVN::partitions &part) {
return
nullptr
;
return
nullptr
;
}
}
// try constant fold for `count` operands
// the related instr is `instr`
Constant
*
GVN
::
constFold_core
(
const
size_t
count
,
const
partitions
&
part
,
Instruction
*
instr
,
const
std
::
vector
<
Value
*>
&
operands
)
{
assert
(
count
==
1
or
count
==
2
);
Constant
*
res
=
nullptr
;
// the first operand
auto
op0_const_value
=
dynamic_cast
<
Constant
*>
(
operands
[
0
]);
auto
op0_search_
=
search_ve
(
operands
[
0
],
part
);
auto
op0_const_expr
=
op0_search_
?
dynamic_cast
<
ConstantExpression
*>
(
op0_search_
.
get
())
:
nullptr
;
if
((
op0_const_value
or
op0_const_expr
))
{
auto
op0_const
=
op0_const_value
?
op0_const_value
:
op0_const_expr
->
get_val
();
// by now: the type cast instruction can do constant fold
if
(
count
==
1
)
res
=
folder_
->
compute
(
instr
,
op0_const
);
if
(
count
==
2
)
{
// the second operand
auto
op1_const_value
=
dynamic_cast
<
Constant
*>
(
operands
[
1
]);
auto
op1_search_
=
search_ve
(
operands
[
1
],
part
);
auto
op1_const_expr
=
op1_search_
?
dynamic_cast
<
ConstantExpression
*>
(
op1_search_
.
get
())
:
nullptr
;
if
(
op1_const_value
or
op1_const_expr
)
{
auto
op1_const
=
op1_const_value
?
op1_const_value
:
op1_const_expr
->
get_val
();
res
=
folder_
->
compute
(
instr
,
op0_const
,
op1_const
);
}
}
}
return
res
;
}
// for each op, try to find the
// for each op, try to find the
std
::
vector
<
shared_ptr
<
Expression
>>
std
::
vector
<
shared_ptr
<
Expression
>>
GVN
::
core_
(
Instruction
*
instr
,
GVN
::
valueExpr_
core_
(
Instruction
*
instr
,
const
partitions
&
part
,
const
partitions
&
part
,
size_t
count
,
const
size_t
count
,
bool
fold_
)
{
bool
fold_
)
{
assert
(
not
(
fold_
and
count
>
2
));
assert
(
not
(
fold_
and
count
>
2
));
...
@@ -357,23 +452,13 @@ GVN::core_(Instruction *instr,
...
@@ -357,23 +452,13 @@ GVN::core_(Instruction *instr,
std
::
vector
<
shared_ptr
<
Expression
>>
ret
;
std
::
vector
<
shared_ptr
<
Expression
>>
ret
;
// if able to fold, then fold
// if able to fold, then fold
fold_
&=
bool
(
dynamic_cast
<
Constant
*>
(
operands
[
0
]));
if
(
count
==
2
)
fold_
&=
bool
(
dynamic_cast
<
Constant
*>
(
operands
[
1
]));
if
(
fold_
)
{
if
(
fold_
)
{
Constant
*
res
;
Constant
*
res
=
nullptr
;
if
(
count
==
1
)
{
if
((
res
=
constFold_core
(
count
,
part
,
instr
,
operands
)))
{
res
=
folder_
->
compute
(
instr
,
dynamic_cast
<
Constant
*>
(
operands
[
0
]));
}
else
{
// count == 2
res
=
folder_
->
compute
(
instr
,
dynamic_cast
<
Constant
*>
(
operands
[
0
]),
dynamic_cast
<
Constant
*>
(
operands
[
1
]));
}
ret
.
push_back
(
ConstantExpression
::
create
(
res
));
ret
.
push_back
(
ConstantExpression
::
create
(
res
));
return
ret
;
return
ret
;
}
}
}
// normal case:
// normal case:
// - try to find expression that already exists
// - try to find expression that already exists
...
@@ -405,7 +490,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
...
@@ -405,7 +490,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
return
tmp
;
return
tmp
;
if
(
instr
->
isBinary
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
())
{
if
(
instr
->
isBinary
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
())
{
res
=
core_
(
instr
,
part
,
2
);
res
=
valueExpr_
core_
(
instr
,
part
,
2
);
if
(
res
.
size
()
==
1
)
// constant fold
if
(
res
.
size
()
==
1
)
// constant fold
return
res
[
0
];
return
res
[
0
];
else
else
...
@@ -414,7 +499,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
...
@@ -414,7 +499,7 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
}
else
if
(
instr
->
is_phi
())
{
}
else
if
(
instr
->
is_phi
())
{
err
=
"phi"
;
err
=
"phi"
;
}
else
if
(
instr
->
is_fp2si
()
or
instr
->
is_si2fp
()
or
instr
->
is_zext
())
{
}
else
if
(
instr
->
is_fp2si
()
or
instr
->
is_si2fp
()
or
instr
->
is_zext
())
{
res
=
core_
(
instr
,
part
,
1
);
res
=
valueExpr_
core_
(
instr
,
part
,
1
);
if
(
res
[
0
]
->
get_expr_type
()
==
Expression
::
e_constant
)
if
(
res
[
0
]
->
get_expr_type
()
==
Expression
::
e_constant
)
return
res
[
0
];
return
res
[
0
];
Type
*
dest_type
;
Type
*
dest_type
;
...
@@ -439,12 +524,16 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
...
@@ -439,12 +524,16 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
instr
->
get_instr_type
(),
res
[
0
],
dest_type
);
instr
->
get_instr_type
(),
res
[
0
],
dest_type
);
}
}
}
else
if
(
instr
->
is_gep
())
{
}
else
if
(
instr
->
is_gep
())
{
res
=
core_
(
instr
,
part
,
instr
->
get_operands
().
size
(),
false
);
res
=
valueExpr_
core_
(
instr
,
part
,
instr
->
get_operands
().
size
(),
false
);
auto
ptr
=
res
[
0
];
auto
ptr
=
res
[
0
];
res
.
erase
(
res
.
begin
());
res
.
erase
(
res
.
begin
());
return
GEPExpression
::
create
(
ptr
,
res
);
return
GEPExpression
::
create
(
ptr
,
res
);
}
else
if
(
instr
->
is_load
()
or
instr
->
is_alloca
()
or
instr
->
is_call
())
{
}
else
if
(
instr
->
is_load
()
or
instr
->
is_alloca
()
or
instr
->
is_call
())
{
return
UniqueExpression
::
create
(
instr
);
auto
ret
=
search_ve
(
instr
,
part
);
if
(
ret
)
return
ret
;
else
return
UniqueExpression
::
create
(
instr
,
next_value_number_
);
}
}
std
::
cerr
<<
"Undefined case: "
<<
err
<<
std
::
endl
;
std
::
cerr
<<
"Undefined case: "
<<
err
<<
std
::
endl
;
...
@@ -459,8 +548,10 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
...
@@ -459,8 +548,10 @@ GVN::valueExpr(Instruction *instr, const partitions &part) {
//
//
/// \param bb basic block in which the transfer function is called
/// \param bb basic block in which the transfer function is called
GVN
::
partitions
GVN
::
partitions
GVN
::
transferFunction
(
Instruction
*
x
,
Value
*
e
,
partitions
pin
)
{
GVN
::
transferFunction
(
Instruction
*
instr
,
Value
*
e
,
partitions
pin
)
{
partitions
pout
=
pin
;
next_value_number_
=
start_idx_
[
std
::
make_pair
(
instr
,
e
)];
partitions
pout
=
clone
(
pin
);
// TODO: deal with copy-stmt case
// TODO: deal with copy-stmt case
// ?? deal with copy statement
// ?? deal with copy statement
auto
e_instr
=
dynamic_cast
<
Instruction
*>
(
e
);
auto
e_instr
=
dynamic_cast
<
Instruction
*>
(
e
);
...
@@ -469,10 +560,13 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
...
@@ -469,10 +560,13 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
"A value must be from an instruction or constant"
);
"A value must be from an instruction or constant"
);
// erase the old record for x
// erase the old record for x
std
::
set
<
Value
*>::
iterator
it
;
std
::
set
<
Value
*>::
iterator
it
;
for
(
auto
c
:
p
in
)
for
(
auto
c
:
p
out
)
if
((
it
=
std
::
find
(
c
->
members_
.
begin
(),
c
->
members_
.
end
(),
x
))
!=
if
((
it
=
std
::
find
(
c
->
members_
.
begin
(),
c
->
members_
.
end
(),
instr
))
!=
c
->
members_
.
end
())
{
c
->
members_
.
end
())
{
c
->
members_
.
erase
(
it
);
c
->
members_
.
erase
(
it
);
if
(
c
->
members_
.
empty
())
pout
.
erase
(
c
);
break
;
}
}
// TODO: get different ValueExpr by Instruction::OpID, modify pout
// TODO: get different ValueExpr by Instruction::OpID, modify pout
...
@@ -483,25 +577,29 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
...
@@ -483,25 +577,29 @@ GVN::transferFunction(Instruction *x, Value *e, partitions pin) {
if
(
e_const
)
if
(
e_const
)
ve
=
ConstantExpression
::
create
(
e_const
);
ve
=
ConstantExpression
::
create
(
e_const
);
else
else
ve
=
valueExpr
(
e_instr
,
p
in
);
ve
=
valueExpr
(
e_instr
,
p
out
);
}
else
}
else
ve
=
valueExpr
(
x
,
pin
);
ve
=
valueExpr
(
instr
,
pout
);
auto
vpf
=
valuePhiFunc
(
ve
,
curr_bb
);
auto
vpf
=
valuePhiFunc
(
ve
,
curr_bb
,
instr
);
// TODO: set leader
// TODO: set leader
for
(
auto
c
:
pout
)
{
for
(
auto
c
:
pout
)
{
if
(
ve
==
c
->
value_expr_
or
if
(
ve
==
c
->
value_expr_
or
(
vpf
and
c
->
value_phi_
and
*
vpf
==
*
c
->
value_phi_
))
{
(
vpf
and
c
->
value_phi_
and
*
vpf
==
*
c
->
value_phi_
))
{
c
->
value_expr_
=
ve
;
//
c->value_expr_ = ve;
c
->
members_
.
insert
(
x
);
c
->
members_
.
insert
(
instr
);
return
pout
;
return
pout
;
}
}
}
}
auto
c
=
createCongruenceClass
(
new_number
());
auto
c
=
createCongruenceClass
(
new_number
());
c
->
members_
.
insert
(
x
);
c
->
members_
.
insert
(
instr
);
c
->
leader_
=
x
;
c
->
value_expr_
=
ve
;
c
->
value_expr_
=
ve
;
c
->
value_phi_
=
vpf
;
c
->
value_phi_
=
vpf
;
if
(
c
->
value_expr_
->
get_expr_type
()
==
Expression
::
e_constant
)
c
->
leader_
=
static_cast
<
ConstantExpression
*>
(
c
->
value_expr_
.
get
())
->
get_val
();
else
c
->
leader_
=
instr
;
pout
.
insert
(
c
);
pout
.
insert
(
c
);
return
pout
;
return
pout
;
}
}
...
@@ -520,8 +618,6 @@ GVN::transferFunction(BasicBlock *bb) {
...
@@ -520,8 +618,6 @@ GVN::transferFunction(BasicBlock *bb) {
* utils::print_partitions(pin_[bb]);
* utils::print_partitions(pin_[bb]);
* LOG_INFO << "pout before:\n";
* LOG_INFO << "pout before:\n";
* utils::print_partitions(pout_[bb]); */
* utils::print_partitions(pout_[bb]); */
std
::
cout
<<
"for basic block "
<<
bb
->
get_name
()
<<
", pin:"
<<
std
::
endl
;
utils
::
print_partitions
(
pin_
[
bb
]);
// iterate through all instructions in the block
// iterate through all instructions in the block
for
(
auto
&
instr
:
bb
->
get_instructions
())
{
for
(
auto
&
instr
:
bb
->
get_instructions
())
{
...
@@ -539,39 +635,88 @@ GVN::transferFunction(BasicBlock *bb) {
...
@@ -539,39 +635,88 @@ GVN::transferFunction(BasicBlock *bb) {
}
}
}
}
}
}
/* LOG_INFO << "pout after:\n";
std
::
cout
<<
"-------
\n
"
* utils::print_partitions(part)
;
<<
"for basic block "
<<
bb
->
get_name
()
<<
", pout:"
<<
std
::
endl
;
* std::cout << std::endl; */
utils
::
print_partitions
(
part
);
return
part
;
return
part
;
}
}
// NOTE: only instruction op matter
shared_ptr
<
PhiExpression
>
shared_ptr
<
PhiExpression
>
GVN
::
valuePhiFunc
(
shared_ptr
<
Expression
>
ve
,
BasicBlock
*
bb
)
{
GVN
::
valuePhiFunc
(
shared_ptr
<
Expression
>
ve
,
BasicBlock
*
bb
,
Instruction
*
instr
)
{
// TODO
// TODO
// get 2 predecessors
auto
pre_bbs_
=
bb
->
get_pre_basic_blocks
();
if
(
pre_bbs_
.
size
()
==
1
)
return
nullptr
;
auto
pre_1
=
*
pre_bbs_
.
begin
();
auto
pre_2
=
*
(
++
pre_bbs_
.
begin
());
// check expression form
if
(
ve
->
get_expr_type
()
!=
Expression
::
e_bin
)
if
(
ve
->
get_expr_type
()
!=
Expression
::
e_bin
)
return
nullptr
;
return
nullptr
;
auto
ve_bin
=
static_cast
<
BinaryExpression
*>
(
ve
.
get
());
auto
ve_bin
=
static_cast
<
BinaryExpression
*>
(
ve
.
get
());
if
(
ve_bin
->
lhs_
->
get_expr_type
()
!=
Expression
::
e_phi
or
if
(
ve_bin
->
lhs_
->
get_expr_type
()
!=
Expression
::
e_phi
and
ve_bin
->
rhs_
->
get_expr_type
()
!=
Expression
::
e_phi
)
ve_bin
->
rhs_
->
get_expr_type
()
!=
Expression
::
e_phi
)
return
nullptr
;
return
nullptr
;
shared_ptr
<
Expression
>
vi
{},
vj
{};
shared_ptr
<
BinaryExpression
>
vl_merge
{},
vr_merge
{};
shared_ptr
<
Expression
>
vl_merge_E
{},
vr_merge_E
{};
// get 2 phi expressions
// get 2 phi expressions
auto
lhs
=
static_cast
<
PhiExpression
*>
(
ve_bin
->
lhs_
.
get
());
auto
lhs_phi
=
dynamic_cast
<
PhiExpression
*>
(
ve_bin
->
lhs_
.
get
());
auto
rhs
=
static_cast
<
PhiExpression
*>
(
ve_bin
->
rhs_
.
get
());
auto
rhs_phi
=
dynamic_cast
<
PhiExpression
*>
(
ve_bin
->
rhs_
.
get
());
// get 2 predecessors
auto
pre_bbs_
=
bb
->
get_pre_basic_blocks
();
auto
pre_1
=
*
pre_bbs_
.
begin
();
auto
pre_2
=
*
(
++
pre_bbs_
.
begin
());
// set vl_merge and vr_merge
if
(
ve_bin
->
lhs_
->
get_expr_type
()
==
Expression
::
e_phi
and
ve_bin
->
rhs_
->
get_expr_type
()
==
Expression
::
e_phi
)
{
// try to get the merged value expression
// try to get the merged value expression
auto
vl_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs
->
lhs_
,
rhs
->
lhs_
);
vl_merge
=
auto
vr_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs
->
rhs_
,
rhs
->
rhs_
);
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs_phi
->
lhs_
,
rhs_phi
->
lhs_
);
auto
vi
=
getVN
(
pout_
[
pre_1
],
vl_merge
);
vr_merge
=
auto
vj
=
getVN
(
pout_
[
pre_2
],
vr_merge
);
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs_phi
->
rhs_
,
rhs_phi
->
rhs_
);
}
else
if
(
ve_bin
->
lhs_
->
get_expr_type
()
==
Expression
::
e_phi
)
{
vl_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs_phi
->
lhs_
,
ve_bin
->
rhs_
);
vr_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
lhs_phi
->
rhs_
,
ve_bin
->
rhs_
);
}
else
{
vl_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
ve_bin
->
lhs_
,
rhs_phi
->
lhs_
);
vr_merge
=
BinaryExpression
::
create
(
ve_bin
->
op_
,
ve_bin
->
lhs_
,
rhs_phi
->
rhs_
);
}
// constant fold
if
(
vl_merge
->
lhs_
->
get_expr_type
()
==
Expression
::
e_constant
and
vl_merge
->
rhs_
->
get_expr_type
()
==
Expression
::
e_constant
)
{
auto
vl_merge_l
=
dynamic_cast
<
ConstantExpression
*>
(
vl_merge
->
lhs_
.
get
());
auto
vl_merge_r
=
dynamic_cast
<
ConstantExpression
*>
(
vl_merge
->
rhs_
.
get
());
vl_merge_E
=
ConstantExpression
::
create
(
folder_
->
compute
(
instr
,
vl_merge_l
->
get_val
(),
vl_merge_r
->
get_val
()));
}
else
vl_merge_E
=
vl_merge
;
if
(
vr_merge
->
lhs_
->
get_expr_type
()
==
Expression
::
e_constant
and
vr_merge
->
rhs_
->
get_expr_type
()
==
Expression
::
e_constant
)
{
auto
vr_merge_l
=
dynamic_cast
<
ConstantExpression
*>
(
vr_merge
->
lhs_
.
get
());
auto
vr_merge_r
=
dynamic_cast
<
ConstantExpression
*>
(
vr_merge
->
rhs_
.
get
());
vr_merge_E
=
ConstantExpression
::
create
(
folder_
->
compute
(
instr
,
vr_merge_l
->
get_val
(),
vr_merge_r
->
get_val
()));
}
else
vr_merge_E
=
vr_merge
;
vi
=
getVN
(
pout_
[
pre_1
],
vl_merge_E
);
vj
=
getVN
(
pout_
[
pre_2
],
vr_merge_E
);
if
(
vi
==
nullptr
)
if
(
vi
==
nullptr
)
vi
=
valuePhiFunc
(
vl_merge
,
pre_1
);
vi
=
valuePhiFunc
(
vl_merge
_E
,
pre_1
,
instr
);
if
(
vj
==
nullptr
)
if
(
vj
==
nullptr
)
vj
=
valuePhiFunc
(
vr_merge
,
pre_2
);
vj
=
valuePhiFunc
(
vr_merge
_E
,
pre_2
,
instr
);
if
(
vi
and
vj
)
if
(
vi
and
vj
)
return
PhiExpression
::
create
(
vi
,
vj
);
return
PhiExpression
::
create
(
vi
,
vj
);
...
@@ -688,6 +833,19 @@ GVN::run() {
...
@@ -688,6 +833,19 @@ GVN::run() {
gvn_json
<<
"]"
;
gvn_json
<<
"]"
;
}
}
void
GVN
::
dump_tmp
(
Function
&
f
)
{
std
::
string
gvn_json
;
if
(
dump_json_
)
{
gvn_json
+=
"{
\n\"
function
\"
: "
;
gvn_json
+=
"
\"
"
+
f
.
get_name
()
+
"
\"
, "
;
gvn_json
+=
"
\n\"
pout
\"
: "
+
utils
::
dump_bb2partition
(
pout_
);
gvn_json
+=
"},"
;
}
gvn_json
+=
"]"
;
std
::
cout
<<
gvn_json
<<
std
::
endl
;
}
template
<
typename
T
>
template
<
typename
T
>
static
bool
static
bool
equiv_as
(
const
Expression
&
lhs
,
const
Expression
&
rhs
)
{
equiv_as
(
const
Expression
&
lhs
,
const
Expression
&
rhs
)
{
...
@@ -729,6 +887,7 @@ GVN::partitions
...
@@ -729,6 +887,7 @@ GVN::partitions
GVN
::
clone
(
const
partitions
&
p
)
{
GVN
::
clone
(
const
partitions
&
p
)
{
partitions
data
;
partitions
data
;
for
(
auto
&
cc
:
p
)
{
for
(
auto
&
cc
:
p
)
{
assert
(
not
cc
->
members_
.
empty
());
data
.
insert
(
std
::
make_shared
<
CongruenceClass
>
(
*
cc
));
data
.
insert
(
std
::
make_shared
<
CongruenceClass
>
(
*
cc
));
}
}
return
data
;
return
data
;
...
...
tests/4-ir-opt/testcases/GVN/functional/.gitignore
View file @
08898ecb
*.ll
*.ll
*th
tmp*
gvn.json
tests/4-ir-opt/testcases/GVN/functional/clear.sh
View file @
08898ecb
rm
-rf
*
.ll
rm
-rf
*
.ll
rm
-rf
gvn.json
rm
-rf
gvn.json
rm
-rf
`
ls
|
grep
-v
"
\.
"
`
rm
-rf
`
ls
|
grep
-v
"
\.
"
`
rm
-rf
tmp
*
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