-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDominateTree.cpp
More file actions
116 lines (104 loc) · 3.17 KB
/
DominateTree.cpp
File metadata and controls
116 lines (104 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "BasicBlock.h"
#include "Function.h"
#include "Pass.h"
#include "DominateTree.h"
#include "internal_types.h"
namespace SysYF {
namespace IR {
void DominateTree::execute() {
for (auto f: module.lock()->get_functions()) {
if (f->get_basic_blocks().empty()) {
continue;
}
get_bb_idom(f);
get_bb_dom_front(f);
}
}
void DominateTree::get_post_order(Ptr<BasicBlock> bb, PtrSet<BasicBlock> &visited) {
visited.insert(bb);
auto children = bb->get_succ_basic_blocks();
for (auto child: children) {
auto is_visited = visited.find(child.lock());
if (is_visited == visited.end()) {
get_post_order(child.lock(), visited);
}
}
bb2int[bb] = reverse_post_order.size();
reverse_post_order.push_back(bb);
}
void DominateTree::get_revserse_post_order(Ptr<Function> f) {
doms.clear();
reverse_post_order.clear();
bb2int.clear();
auto entry = f->get_entry_block();
PtrSet<BasicBlock> visited = {};
get_post_order(entry, visited);
reverse_post_order.reverse();
}
//ref:https://www.cs.rice.edu/~keith/EMBED/dom.pdf
void DominateTree::get_bb_idom(Ptr<Function> f) {
get_revserse_post_order(f);
auto root = f->get_entry_block();
auto root_id = bb2int[root];
for(int i = 0;i < root_id;i++){
doms.push_back({});
}
doms.push_back(root);
bool changed = true;
while(changed){
changed = false;
for(auto bb:reverse_post_order){
if(bb.lock() == root){
continue;
}
auto preds = bb.lock()->get_pre_basic_blocks();
Ptr<BasicBlock> new_idom = nullptr;
for(auto pred_bb:preds){
if(doms[bb2int[pred_bb.lock()]].lock() != nullptr){
new_idom = pred_bb.lock();
break;
}
}
for(auto pred_bb:preds){
if(doms[bb2int[pred_bb.lock()]].lock() != nullptr){
new_idom = intersect(pred_bb.lock(),new_idom);
}
}
if(doms[bb2int[bb]].lock() != new_idom){
doms[bb2int[bb]] = new_idom;
changed = true;
}
}
}
for(auto bb:reverse_post_order){
bb.lock()->set_idom(doms[bb2int[bb]].lock()); }
}
void DominateTree::get_bb_dom_front(Ptr<Function> f) {
for(auto b:f->get_basic_blocks()){
auto b_pred = b->get_pre_basic_blocks();
if(b_pred.size() >= 2){
for(auto pred:b_pred){
auto runner = pred;
while(runner.lock()!=doms[bb2int[b]].lock()){
runner.lock()->add_dom_frontier(b);
runner = doms[bb2int[runner.lock()]];
}
}
}
}
}
Ptr<BasicBlock> DominateTree::intersect(Ptr<BasicBlock> b1, Ptr<BasicBlock> b2) {
auto finger1 = b1;
auto finger2 = b2;
while(finger1 != finger2){
while(bb2int[finger1]<bb2int[finger2]){
finger1 = doms[bb2int[finger1]].lock();
}
while(bb2int[finger2]<bb2int[finger1]){
finger2 = doms[bb2int[finger2]].lock();
}
}
return finger1;
}
}
}