Skip to content

Commit db9fc6a

Browse files
Implement domaintor_tree analysis pass
Add support to build a domaintor tree for a given CFG, and add APIs to use the domaintor tree to find idoms and dominance information.
1 parent 7590972 commit db9fc6a

File tree

6 files changed

+180
-1
lines changed

6 files changed

+180
-1
lines changed

include/blocks/basic_blocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class basic_block {
1515
block::expr::Ptr branch_expr;
1616
block::stmt::Ptr parent;
1717
unsigned int index;
18+
unsigned int id;
1819
std::string name;
1920
};
2021

include/blocks/dominance.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef DOMINANCE_H
2+
#define DOMINANCE_H
3+
#include "blocks/block_visitor.h"
4+
#include "blocks/basic_blocks.h"
5+
#include "blocks/stmt.h"
6+
#include <vector>
7+
#include <stack>
8+
#include <string>
9+
#include <bitset>
10+
#include <algorithm>
11+
12+
class dominator_tree {
13+
public:
14+
dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg);
15+
std::vector<int> &get_postorder_bb_map();
16+
std::vector<int> &get_postorder();
17+
std::vector<int> &get_idom();
18+
int get_idom(int bb_id);
19+
bool dominates(int bb1_id, int bb2_id);
20+
bool is_reachable_from_entry(int bb_id);
21+
void analyze();
22+
23+
private:
24+
std::vector<int> idom;
25+
std::vector<int> postorder;
26+
std::vector<int> postorder_bb_map;
27+
std::vector<std::shared_ptr<basic_block>> &cfg_;
28+
void postorder_dfs_helper(std::vector<bool> &visited_bbs, int id);
29+
void postorder_dfs();
30+
int intersect(int bb1_id, int bb2_id);
31+
};
32+
33+
34+
#endif

include/builder/builder_context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef BUILDER_CONTEXT
22
#define BUILDER_CONTEXT
33
#include "blocks/basic_blocks.h"
4+
#include "blocks/dominance.h"
45
#include "blocks/expr.h"
56
#include "blocks/stmt.h"
67
#include "builder/forward_declarations.h"

src/blocks/basic_blocks.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,5 +169,10 @@ std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_bloc
169169
}
170170
}
171171

172+
// step 6: assign each basic_block an id
173+
for (unsigned int i = 0; i < return_list.size(); i++) {
174+
return_list[i]->id = i;
175+
}
176+
172177
return return_list;
173178
}

src/blocks/dominance.cpp

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "blocks/dominance.h"
2+
3+
using namespace block;
4+
5+
dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg) : cfg_(cfg) {
6+
// TODO: Add a check for size, it should be greater than 2.
7+
idom.reserve(cfg_.size());
8+
idom.assign(cfg_.size(), -1);
9+
postorder.reserve(cfg_.size());
10+
postorder_bb_map.reserve(cfg_.size());
11+
postorder_bb_map.assign(cfg_.size(), -1);
12+
13+
// and call the anaylse function
14+
analyze();
15+
}
16+
17+
void dominator_tree::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id) {
18+
for (auto child: cfg_[id]->successor) {
19+
if (!visited_bbs[child->id]) {
20+
visited_bbs[child->id] = true;
21+
postorder_dfs_helper(visited_bbs, child->id);
22+
postorder.push_back(child->id);
23+
}
24+
}
25+
}
26+
void dominator_tree::postorder_dfs() {
27+
std::vector<bool> visited_bbs(cfg_.size());
28+
visited_bbs.assign(visited_bbs.size(), false);
29+
visited_bbs[0] = true;
30+
31+
postorder_dfs_helper(visited_bbs, 0);
32+
postorder.push_back(0);
33+
}
34+
35+
std::vector<int> &dominator_tree::get_postorder_bb_map() {
36+
return postorder_bb_map;
37+
}
38+
39+
std::vector<int> &dominator_tree::get_postorder() {
40+
return postorder;
41+
}
42+
43+
std::vector<int> &dominator_tree::get_idom() {
44+
return idom;
45+
}
46+
47+
int dominator_tree::get_idom(int bb_id) {
48+
if (bb_id >= 0 && bb_id < idom.size()) {
49+
return -1;
50+
}
51+
52+
return idom[bb_id];
53+
}
54+
bool dominator_tree::dominates(int bb1_id, int bb2_id) {
55+
if (bb1_id == 0) {
56+
return true;
57+
}
58+
59+
int pointer = idom[bb2_id];
60+
while (pointer != 0) {
61+
if (pointer == bb1_id) {
62+
return true;
63+
}
64+
pointer = idom[pointer];
65+
}
66+
67+
return false;
68+
}
69+
70+
bool dominator_tree::is_reachable_from_entry(int bb_id) {
71+
return dominates(0, bb_id);
72+
}
73+
74+
int dominator_tree::intersect(int bb1_id, int bb2_id) {
75+
while (bb1_id != bb2_id) {
76+
if (postorder_bb_map[bb1_id] < postorder_bb_map[bb2_id]) {
77+
bb1_id = idom[bb1_id];
78+
}
79+
else {
80+
bb2_id = idom[bb2_id];
81+
}
82+
}
83+
84+
return bb1_id;
85+
}
86+
87+
void dominator_tree::analyze() {
88+
postorder_dfs();
89+
for (unsigned int i = 0; i < postorder.size(); i++) {
90+
postorder_bb_map[postorder[i]] = i;
91+
}
92+
93+
idom[0] = 0;
94+
bool change = false;
95+
96+
do {
97+
change = 0;
98+
for (int i = postorder.size() - 2; i >= 0; i--) {
99+
int postorder_bb_num = postorder[i];
100+
std::shared_ptr<basic_block> bb = cfg_[postorder_bb_num];
101+
int bb_id_idom = bb->predecessor[0]->id;
102+
103+
for (unsigned int j = 1; j < bb->predecessor.size(); j++) {
104+
int bb_id_idom_next = bb->predecessor[j]->id;
105+
if (idom[bb_id_idom_next] != -1) {
106+
bb_id_idom = intersect(bb_id_idom, bb_id_idom_next);
107+
}
108+
}
109+
110+
if (idom[postorder_bb_num] != bb_id_idom) {
111+
idom[postorder_bb_num] = bb_id_idom;
112+
change = 1;
113+
}
114+
}
115+
} while(change);
116+
}

src/builder/builder_context.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
296296

297297
std::cerr << "++++++ basic blocks ++++++ \n";
298298
for (auto bb: BBs) {
299-
std::cerr << bb->name << ":" << " ; ";
299+
std::cerr << bb->id << ":" << bb->name << ":" << " ; ";
300300
for (auto pred: bb->predecessor) {
301301
std::cerr << pred->name << ", ";
302302
}
@@ -314,6 +314,28 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
314314
}
315315
std::cerr << "++++++ basic blocks ++++++ \n";
316316

317+
std::cerr << "++++++ dominance ++++++ \n";
318+
dominator_tree dom(BBs);
319+
320+
std::cerr << "== postorder map ==\n";
321+
for (int i: dom.get_postorder_bb_map()) {
322+
std::cerr << i << "\n";
323+
}
324+
std::cerr << "== postorder map ==\n";
325+
326+
std::cerr << "== postorder ==\n";
327+
for (int i: dom.get_postorder()) {
328+
std::cerr << i << "\n";
329+
}
330+
std::cerr << "== postorder ==\n";
331+
332+
std::cerr << "== idom ==\n";
333+
for (int i: dom.get_idom()) {
334+
std::cerr << i << "\n";
335+
}
336+
std::cerr << "== idom ==\n";
337+
std::cerr << "++++++ dominance ++++++ \n";
338+
317339
if (feature_unstructured)
318340
return ast;
319341

0 commit comments

Comments
 (0)