Skip to content

Commit 8c20e84

Browse files
WIP: Implement loop_info pass (works)
1 parent 3e3518e commit 8c20e84

File tree

5 files changed

+198
-15
lines changed

5 files changed

+198
-15
lines changed

include/blocks/dominance.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,26 @@ class dominator_analysis {
1818
// std::vector<std::shared_ptr<dominator_tree_>> child_nodes;
1919
// } dominator_tree;
2020
dominator_analysis(basic_block::cfg_block &cfg);
21+
basic_block::cfg_block &cfg_;
2122
std::vector<int> &get_postorder_bb_map();
2223
std::vector<int> &get_postorder();
2324
std::vector<int> &get_idom();
2425
std::map<int, std::vector<int>> &get_idom_map();
26+
std::vector<int> &get_postorder_idom_map();
2527
int get_idom(int bb_id);
2628
std::vector<int> get_idom_map(int bb_id);
29+
int get_postorder_idom_map(int idom_id);
2730
bool dominates(int bb1_id, int bb2_id);
2831
bool is_reachable_from_entry(int bb_id);
2932
void analyze();
3033

3134
private:
3235
std::vector<int> idom;
3336
std::map<int, std::vector<int>> idom_map;
37+
std::vector<int> postorder_idom;
3438
std::vector<int> postorder;
3539
std::vector<int> postorder_bb_map;
36-
basic_block::cfg_block &cfg_;
40+
void postorder_idom_helper(std::vector<bool> &visited, int id);
3741
void postorder_dfs_helper(std::vector<bool> &visited_bbs, int id);
3842
void postorder_dfs();
3943
int intersect(int bb1_id, int bb2_id);

include/blocks/loops.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
using namespace block;
99
class loop {
1010
public:
11-
loop() = default;
11+
loop(std::shared_ptr<basic_block> header): header_block(header) {}
1212

13-
private:
13+
// private:
1414
struct loop_bounds_ {
1515
stmt::Ptr ind_var;
1616
// MISS: intial value of ind var
@@ -22,17 +22,26 @@ class loop {
2222
stmt::Ptr entry_stmt;
2323
} loop_bounds;
2424

25-
basic_block::cfg_block exit_bbs;
25+
basic_block::cfg_block blocks;
26+
std::shared_ptr<loop> parent_loop;
27+
std::shared_ptr<basic_block> header_block;
28+
std::shared_ptr<basic_block> backedge_block;
29+
std::vector<std::shared_ptr<loop>> subloops;
2630
};
2731

2832
class loop_info {
2933
public:
30-
loop_info(basic_block::cfg_block ast, dominator_analysis dt): parent_ast(ast), dta(dt) {
34+
loop_info(basic_block::cfg_block ast, dominator_analysis &dt): parent_ast(ast), dta(dt) {
3135
analyze();
3236
}
37+
std::shared_ptr<loop> allocate_loop(std::shared_ptr<basic_block> header);
38+
std::vector<std::shared_ptr<loop>> loops;
39+
std::vector<std::shared_ptr<loop>> top_level_loops;
40+
3341
private:
3442
basic_block::cfg_block parent_ast;
3543
dominator_analysis dta;
44+
std::map<int, std::shared_ptr<loop>> bb_loop_map;
3645
// discover loops during traversal of the abstract syntax tree
3746
void analyze();
3847
};

src/blocks/dominance.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg)
1414
analyze();
1515
}
1616

17+
void dominator_analysis::postorder_idom_helper(std::vector<bool> &visited, int id) {
18+
for (int idom_id: idom_map[id]) {
19+
std::cerr << idom_id << "\n";
20+
if (idom_id != -1 && !visited[idom_id]) {
21+
visited[idom_id] = true;
22+
postorder_idom_helper(visited, idom_id);
23+
postorder_idom.push_back(idom_id);
24+
}
25+
}
26+
}
27+
1728
void dominator_analysis::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id) {
1829
for (auto child: cfg_[id]->successor) {
1930
if (!visited_bbs[child->id]) {
@@ -48,6 +59,10 @@ std::map<int, std::vector<int>> &dominator_analysis::get_idom_map() {
4859
return idom_map;
4960
}
5061

62+
std::vector<int> &dominator_analysis::get_postorder_idom_map() {
63+
return postorder_idom;
64+
}
65+
5166
int dominator_analysis::get_idom(int bb_id) {
5267
if (bb_id < 0 || bb_id >= (int)idom.size()) {
5368
return -1;
@@ -64,6 +79,14 @@ std::vector<int> dominator_analysis::get_idom_map(int bb_id) {
6479
return idom_map[bb_id];
6580
}
6681

82+
int dominator_analysis::get_postorder_idom_map(int idom_id) {
83+
if (idom_id < 0 || idom_id >= (int)postorder_idom.size()) {
84+
return -1;
85+
}
86+
87+
return postorder_idom[idom_id];
88+
}
89+
6790
bool dominator_analysis::dominates(int bb1_id, int bb2_id) {
6891
if (bb1_id == 0) {
6992
return true;
@@ -138,11 +161,11 @@ void dominator_analysis::analyze() {
138161
idom_map[i].push_back(-1);
139162
}
140163

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-
// }
164+
// build a postorder visit list of idom_tree
165+
std::vector<bool> visited_idom_nodes(idom_map.size());
166+
visited_idom_nodes.assign(visited_idom_nodes.size(), false);
167+
visited_idom_nodes[0] = true;
168+
169+
postorder_idom_helper(visited_idom_nodes, 0);
170+
postorder_idom.push_back(0);
148171
}

src/blocks/loops.cpp

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,133 @@
11
#include "blocks/loops.h"
22
#include <algorithm>
33

4+
std::shared_ptr<loop> loop_info::allocate_loop(std::shared_ptr<basic_block> header) {
5+
if (!header)
6+
return nullptr;
7+
8+
loops.push_back(std::make_shared<loop>(header));
9+
bb_loop_map[header->id] = loops.back();
10+
return loops.back();
11+
}
12+
413
void loop_info::analyze() {
514
std::vector<int> idom = dta.get_idom();
6-
for (unsigned int i = 0; i < idom.size(); i++) {
7-
std::cout << i << " : " << idom[i] << "\n";
15+
16+
for (int idom_id: dta.get_postorder_idom_map()) {
17+
std::vector<int> backedges;
18+
int header = idom_id;
19+
20+
for (auto backedge: dta.cfg_[header]->predecessor) {
21+
if (dta.dominates(header, backedge->id) && dta.is_reachable_from_entry(backedge->id)) {
22+
backedges.push_back(backedge->id);
23+
}
24+
}
25+
26+
for(int i: backedges) {
27+
std::cerr << i << "\n";
28+
}
29+
30+
if (!backedges.empty()) {
31+
std::shared_ptr<loop> new_loop = allocate_loop(dta.cfg_[header]);
32+
if (!new_loop)
33+
continue;
34+
35+
int num_blocks = 0;
36+
int num_subloops = 0;
37+
38+
auto backedge_iter = backedges.begin();
39+
// do a reverse CFG traversal to map basic blocks in this loop.
40+
basic_block::cfg_block worklist(backedges.size());
41+
std::generate(worklist.begin(), worklist.end(), [&backedge_iter, this](){
42+
return dta.cfg_[*(backedge_iter++)];
43+
});
44+
for (unsigned int i = 0; i < worklist.size(); i++) {
45+
std::cerr << worklist[i]->id << "\n";
46+
}
47+
std::cerr << "header-p: " << header << "\n";
48+
while (!worklist.empty()) {
49+
unsigned int predecessor_bb_id = worklist.back()->id;
50+
worklist.pop_back();
51+
52+
auto subloop_iter = bb_loop_map.find(predecessor_bb_id);
53+
if (subloop_iter == bb_loop_map.end()) {
54+
if (!dta.is_reachable_from_entry(predecessor_bb_id))
55+
continue;
56+
57+
bb_loop_map[predecessor_bb_id] = new_loop;
58+
std::cerr << "bb: " << predecessor_bb_id << "\n";
59+
std::cerr << "loop-h: " << new_loop->header_block->id << "\n";
60+
++num_blocks;
61+
std::cerr << "if 1\n";
62+
// loop has no blocks between header and backedge
63+
if (predecessor_bb_id == new_loop->header_block->id)
64+
continue;
65+
std::cerr << "if 2\n";
66+
67+
worklist.insert(worklist.end(), dta.cfg_[predecessor_bb_id]->predecessor.begin(), dta.cfg_[predecessor_bb_id]->predecessor.end());
68+
}
69+
else {
70+
// this block has already been discovered, mapped to some other loop
71+
// find the outermost loop
72+
std::shared_ptr<loop> subloop = subloop_iter->second;
73+
std::cerr << "header: " << subloop->header_block->id << "\n";
74+
while (subloop->parent_loop) {
75+
subloop = subloop->parent_loop;
76+
}
77+
std::cerr << "else 1\n";
78+
79+
if (subloop == new_loop)
80+
continue;
81+
82+
std::cerr << "else 2\n";
83+
std::cerr << "bb: " << predecessor_bb_id << "\n";
84+
85+
// discovered a subloop of this loop
86+
subloop->parent_loop = new_loop;
87+
++num_subloops;
88+
num_blocks = num_blocks + subloop->blocks.size();
89+
predecessor_bb_id = subloop->header_block->id;
90+
91+
for (auto pred: dta.cfg_[predecessor_bb_id]->predecessor) {
92+
auto loop_iter = bb_loop_map.find(pred->id);
93+
// do not check if loop_iter != bb_loop_map.end(), as a results
94+
// basic blocks that are not directly part of the natural loops
95+
// are skipped, like loop latches.
96+
if (loop_iter->second != subloop)
97+
worklist.push_back(pred);
98+
}
99+
}
100+
}
101+
new_loop->subloops.reserve(num_subloops);
102+
new_loop->blocks.reserve(num_blocks);
103+
}
8104
}
9-
}
105+
106+
// populate all subloops and loops with blocks
107+
for (auto bb_id: dta.get_postorder()) {
108+
auto subloop_iter = bb_loop_map.find(bb_id);
109+
std::shared_ptr<loop> subloop = nullptr;
110+
std::cerr << bb_id << " " << dta.cfg_[bb_id]->id << subloop_iter->second->header_block->id << "\n";
111+
if (subloop_iter != bb_loop_map.end() && (subloop = subloop_iter->second) && dta.cfg_[bb_id] == subloop_iter->second->header_block) {
112+
// check if it is the outermost loop
113+
std::cerr << "out::::" << subloop->header_block->id << "\n";
114+
if (subloop->parent_loop != nullptr) {
115+
std::cerr << "id::::" << subloop->header_block->id << "\n";
116+
subloop->parent_loop->subloops.push_back(subloop);
117+
}
118+
else {
119+
top_level_loops.push_back(subloop);
120+
}
121+
122+
std::reverse(subloop->blocks.begin(), subloop->blocks.end());
123+
std::reverse(subloop->subloops.begin(), subloop->subloops.end());
124+
125+
subloop = subloop->parent_loop;
126+
}
127+
128+
while (subloop) {
129+
subloop->blocks.push_back(dta.cfg_[bb_id]);
130+
subloop = subloop->parent_loop;
131+
}
132+
}
133+
}

src/builder/builder_context.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,32 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
356356
}
357357
std::cerr << "== idom map ==\n";
358358

359+
std::cerr << "== postorder idom ==\n";
360+
for (auto idom: dom.get_postorder_idom_map()) {
361+
std::cerr << idom << "\n";
362+
}
363+
std::cerr << "== postorder idom ==\n";
364+
359365
std::cerr << "++++++ dominance ++++++ \n";
360366

367+
std::cerr << "++++++ loop info ++++++ \n";
361368
loop_info LI(BBs, dom);
369+
int loop_num = 0;
370+
for (auto loop: LI.loops) {
371+
std::cerr << "++++++ loop " << loop_num++ << " ++++++ \n";
372+
373+
std::cerr << "loop headers: " << loop->header_block->id << "\n";
374+
std::cerr << "blocks: ";
375+
for (auto bb: loop->blocks) std::cerr << bb->id << " ";
376+
std::cerr << "\n";
377+
// std::cerr << "backedge: " << loop->backedge_block->id << "\n";
378+
std::cerr << "parent loop: (loop header: " << (loop->parent_loop ? (int)loop->parent_loop->header_block->id : -1) << ")\n";
379+
std::cerr << "subloops: ";
380+
for (auto subl: loop->subloops) std::cerr << "(loop header: " << subl->header_block->id << ") ";
381+
std::cerr << "\n";
382+
}
383+
std::cerr << "++++++ loop info ++++++ \n";
384+
362385
if (feature_unstructured)
363386
return ast;
364387

0 commit comments

Comments
 (0)