Skip to content

Commit e34366c

Browse files
Generate idom_map and add loop info pass skeleton
This commit does the following things: 1) Cleans up the basic_block def by adding a typedef. 2) Adds code to generate a idom map, which makes it easy to iterate over the dominator tree. 3) Implements a skeleton class for loop analysis pass. 4) Adds relevant tests to builder_context.cpp to test the dominator_tree APIs 5) Rename the dominator_tree class to dominator_analysis class.
1 parent db9fc6a commit e34366c

File tree

8 files changed

+138
-24
lines changed

8 files changed

+138
-24
lines changed

include/blocks/basic_blocks.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
#ifndef BASIC_BLOCKS_H
22
#define BASIC_BLOCKS_H
3-
#include "blocks/block_visitor.h"
43
#include "blocks/stmt.h"
54
#include <vector>
65
#include <deque>
76
#include <string>
87

98
class basic_block {
109
public:
10+
typedef std::vector<std::shared_ptr<basic_block>> cfg_block;
1111
basic_block(std::string label): name(label) {};
1212

13-
std::vector<std::shared_ptr<basic_block>> predecessor;
14-
std::vector<std::shared_ptr<basic_block>> successor;
13+
cfg_block predecessor;
14+
cfg_block successor;
1515
block::expr::Ptr branch_expr;
1616
block::stmt::Ptr parent;
1717
unsigned int index;
1818
unsigned int id;
1919
std::string name;
2020
};
2121

22-
std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_block::Ptr ast);
22+
basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast);
2323

2424
#endif

include/blocks/dominance.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,37 @@
33
#include "blocks/block_visitor.h"
44
#include "blocks/basic_blocks.h"
55
#include "blocks/stmt.h"
6+
#include <map>
67
#include <vector>
78
#include <stack>
89
#include <string>
910
#include <bitset>
1011
#include <algorithm>
1112

12-
class dominator_tree {
13+
class dominator_analysis {
1314
public:
14-
dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg);
15+
// struct dominator_tree_ {
16+
// dominator_tree_(int id): bb_id(id);
17+
// int bb_id;
18+
// std::vector<std::shared_ptr<dominator_tree_>> child_nodes;
19+
// } dominator_tree;
20+
dominator_analysis(basic_block::cfg_block &cfg);
1521
std::vector<int> &get_postorder_bb_map();
1622
std::vector<int> &get_postorder();
1723
std::vector<int> &get_idom();
24+
std::map<int, std::vector<int>> &get_idom_map();
1825
int get_idom(int bb_id);
26+
std::vector<int> get_idom_map(int bb_id);
1927
bool dominates(int bb1_id, int bb2_id);
2028
bool is_reachable_from_entry(int bb_id);
2129
void analyze();
2230

2331
private:
2432
std::vector<int> idom;
33+
std::map<int, std::vector<int>> idom_map;
2534
std::vector<int> postorder;
2635
std::vector<int> postorder_bb_map;
27-
std::vector<std::shared_ptr<basic_block>> &cfg_;
36+
basic_block::cfg_block &cfg_;
2837
void postorder_dfs_helper(std::vector<bool> &visited_bbs, int id);
2938
void postorder_dfs();
3039
int intersect(int bb1_id, int bb2_id);

include/blocks/loops.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef LOOP_H
2+
#define LOOP_H
3+
#include "blocks/block_visitor.h"
4+
#include "blocks/basic_blocks.h"
5+
#include "blocks/dominance.h"
6+
#include "blocks/stmt.h"
7+
8+
using namespace block;
9+
class loop {
10+
public:
11+
loop() = default;
12+
13+
private:
14+
struct loop_bounds_ {
15+
stmt::Ptr ind_var;
16+
// MISS: intial value of ind var
17+
stmt::Ptr steps_ind_var;
18+
// MISS: value of the step
19+
// MISS: final value of the step
20+
stmt::Ptr cond_ind_var;
21+
// MISS: direction of step
22+
stmt::Ptr entry_stmt;
23+
} loop_bounds;
24+
25+
basic_block::cfg_block exit_bbs;
26+
};
27+
28+
class loop_info {
29+
public:
30+
loop_info(basic_block::cfg_block ast, dominator_analysis dt): parent_ast(ast), dta(dt) {
31+
analyze();
32+
}
33+
private:
34+
basic_block::cfg_block parent_ast;
35+
dominator_analysis dta;
36+
// discover loops during traversal of the abstract syntax tree
37+
void analyze();
38+
};
39+
40+
#endif

include/builder/builder_context.h

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

src/blocks/basic_blocks.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
using namespace block;
55

6-
std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_block::Ptr ast) {
6+
basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
77
std::deque<std::shared_ptr<basic_block>> work_list;
8-
std::vector<std::shared_ptr<basic_block>> return_list;
8+
basic_block::cfg_block return_list;
99
int basic_block_count = 0;
1010

1111
// step 1: fill the work_list
@@ -31,7 +31,7 @@ std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_bloc
3131
bb->name = "stmt" + bb->name;
3232

3333
if (stmt_block_->stmts.size() > 0) {
34-
std::vector<std::shared_ptr<basic_block>> stmt_block_list;
34+
basic_block::cfg_block stmt_block_list;
3535

3636
// convert all statements of this stmt_block into a basic block
3737
for (auto st: stmt_block_->stmts) {

src/blocks/dominance.cpp

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using namespace block;
44

5-
dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg) : cfg_(cfg) {
5+
dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) {
66
// TODO: Add a check for size, it should be greater than 2.
77
idom.reserve(cfg_.size());
88
idom.assign(cfg_.size(), -1);
@@ -14,7 +14,7 @@ dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg) :
1414
analyze();
1515
}
1616

17-
void dominator_tree::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id) {
17+
void dominator_analysis::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id) {
1818
for (auto child: cfg_[id]->successor) {
1919
if (!visited_bbs[child->id]) {
2020
visited_bbs[child->id] = true;
@@ -23,7 +23,7 @@ void dominator_tree::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id
2323
}
2424
}
2525
}
26-
void dominator_tree::postorder_dfs() {
26+
void dominator_analysis::postorder_dfs() {
2727
std::vector<bool> visited_bbs(cfg_.size());
2828
visited_bbs.assign(visited_bbs.size(), false);
2929
visited_bbs[0] = true;
@@ -32,26 +32,39 @@ void dominator_tree::postorder_dfs() {
3232
postorder.push_back(0);
3333
}
3434

35-
std::vector<int> &dominator_tree::get_postorder_bb_map() {
35+
std::vector<int> &dominator_analysis::get_postorder_bb_map() {
3636
return postorder_bb_map;
3737
}
3838

39-
std::vector<int> &dominator_tree::get_postorder() {
39+
std::vector<int> &dominator_analysis::get_postorder() {
4040
return postorder;
4141
}
4242

43-
std::vector<int> &dominator_tree::get_idom() {
43+
std::vector<int> &dominator_analysis::get_idom() {
4444
return idom;
4545
}
4646

47-
int dominator_tree::get_idom(int bb_id) {
48-
if (bb_id >= 0 && bb_id < idom.size()) {
47+
std::map<int, std::vector<int>> &dominator_analysis::get_idom_map() {
48+
return idom_map;
49+
}
50+
51+
int dominator_analysis::get_idom(int bb_id) {
52+
if (bb_id < 0 || bb_id >= (int)idom.size()) {
4953
return -1;
5054
}
5155

5256
return idom[bb_id];
5357
}
54-
bool dominator_tree::dominates(int bb1_id, int bb2_id) {
58+
59+
std::vector<int> dominator_analysis::get_idom_map(int bb_id) {
60+
if (bb_id < 0 || bb_id >= (int)idom_map.size()) {
61+
return {};
62+
}
63+
64+
return idom_map[bb_id];
65+
}
66+
67+
bool dominator_analysis::dominates(int bb1_id, int bb2_id) {
5568
if (bb1_id == 0) {
5669
return true;
5770
}
@@ -67,11 +80,11 @@ bool dominator_tree::dominates(int bb1_id, int bb2_id) {
6780
return false;
6881
}
6982

70-
bool dominator_tree::is_reachable_from_entry(int bb_id) {
83+
bool dominator_analysis::is_reachable_from_entry(int bb_id) {
7184
return dominates(0, bb_id);
7285
}
7386

74-
int dominator_tree::intersect(int bb1_id, int bb2_id) {
87+
int dominator_analysis::intersect(int bb1_id, int bb2_id) {
7588
while (bb1_id != bb2_id) {
7689
if (postorder_bb_map[bb1_id] < postorder_bb_map[bb2_id]) {
7790
bb1_id = idom[bb1_id];
@@ -84,7 +97,7 @@ int dominator_tree::intersect(int bb1_id, int bb2_id) {
8497
return bb1_id;
8598
}
8699

87-
void dominator_tree::analyze() {
100+
void dominator_analysis::analyze() {
88101
postorder_dfs();
89102
for (unsigned int i = 0; i < postorder.size(); i++) {
90103
postorder_bb_map[postorder[i]] = i;
@@ -113,4 +126,23 @@ void dominator_tree::analyze() {
113126
}
114127
}
115128
} while(change);
129+
130+
131+
// build a map of dominators for easy traversal.
132+
for (unsigned int i = 0; i < idom.size(); i++) {
133+
idom_map[idom[i]].push_back(i);
134+
}
135+
136+
for (unsigned int i = 0; i < idom.size(); i++) {
137+
if (idom_map[i].empty())
138+
idom_map[i].push_back(-1);
139+
}
140+
141+
// for (auto key: idom_map) {
142+
// std::cout << key.first << ": ";
143+
// for (int id: key.second) {
144+
// std::cout << id << " ";
145+
// }
146+
// std::cout << "\n";
147+
// }
116148
}

src/blocks/loops.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "blocks/loops.h"
2+
#include <algorithm>
3+
4+
void loop_info::analyze() {
5+
std::vector<int> idom = dta.get_idom();
6+
for (unsigned int i = 0; i < idom.size(); i++) {
7+
std::cout << i << " : " << idom[i] << "\n";
8+
}
9+
}

src/builder/builder_context.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
292292
block::eliminate_redundant_vars(ast);
293293
}
294294

295-
std::vector<std::shared_ptr<basic_block>> BBs = generate_basic_blocks(block::to<block::stmt_block>(ast));
295+
basic_block::cfg_block BBs = generate_basic_blocks(block::to<block::stmt_block>(ast));
296296

297297
std::cerr << "++++++ basic blocks ++++++ \n";
298298
for (auto bb: BBs) {
@@ -315,7 +315,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
315315
std::cerr << "++++++ basic blocks ++++++ \n";
316316

317317
std::cerr << "++++++ dominance ++++++ \n";
318-
dominator_tree dom(BBs);
318+
dominator_analysis dom(BBs);
319319

320320
std::cerr << "== postorder map ==\n";
321321
for (int i: dom.get_postorder_bb_map()) {
@@ -330,12 +330,35 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
330330
std::cerr << "== postorder ==\n";
331331

332332
std::cerr << "== idom ==\n";
333+
std::cerr << "get_idom(int) test: get_idom(0): " << dom.get_idom(0) << "\n";
334+
std::cerr << "get_idom(int) test: get_idom(-1): " << dom.get_idom(-1) << "\n";
335+
333336
for (int i: dom.get_idom()) {
334337
std::cerr << i << "\n";
335338
}
336339
std::cerr << "== idom ==\n";
340+
341+
std::cerr << "== idom map ==\n";
342+
std::cerr << "get_idom_map(int) test: get_idom_map(0): ";
343+
for (int i : dom.get_idom_map(0)) std::cerr << i << " ";
344+
std::cerr << "\n";
345+
346+
std::cerr << "get_idom_map(int) test: get_idom_map(-1): ";
347+
for (int i : dom.get_idom_map(-1)) std::cerr << i << " ";
348+
std::cerr << "\n";
349+
350+
for (auto children: dom.get_idom_map()) {
351+
std::cerr << children.first << ": ";
352+
for (int child: children.second) {
353+
std::cerr << child << " ";
354+
}
355+
std::cerr << "\n";
356+
}
357+
std::cerr << "== idom map ==\n";
358+
337359
std::cerr << "++++++ dominance ++++++ \n";
338360

361+
loop_info LI(BBs, dom);
339362
if (feature_unstructured)
340363
return ast;
341364

0 commit comments

Comments
 (0)