Skip to content

Commit 94be2dd

Browse files
WIP: Add infra to construct a while loop using the loop_info analysis
1 parent 17634dd commit 94be2dd

File tree

6 files changed

+244
-5
lines changed

6 files changed

+244
-5
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 ast_index;
18+
unsigned int ast_depth;
1819
unsigned int id;
1920
std::string name;
2021
};

include/blocks/loops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class loop {
2323
stmt::Ptr entry_stmt;
2424
} loop_bounds;
2525

26+
unsigned int loop_id;
2627
basic_block::cfg_block blocks;
2728
std::unordered_set<int> blocks_id_map;
2829
std::shared_ptr<loop> parent_loop;
@@ -37,13 +38,16 @@ class loop_info {
3738
analyze();
3839
}
3940
std::shared_ptr<loop> allocate_loop(std::shared_ptr<basic_block> header);
41+
block::stmt_block::Ptr convert_to_ast(block::stmt_block::Ptr ast);
42+
std::map<unsigned int, std::vector<int>> postorder_loops_map;
4043
std::vector<std::shared_ptr<loop>> loops;
4144
std::vector<std::shared_ptr<loop>> top_level_loops;
4245

4346
private:
4447
basic_block::cfg_block parent_ast;
4548
dominator_analysis dta;
4649
std::map<int, std::shared_ptr<loop>> bb_loop_map;
50+
void postorder_dfs_helper(std::vector<int> &postorder_loops_map, std::vector<bool> &visited_loops, int id);
4751
// discover loops during traversal of the abstract syntax tree
4852
void analyze();
4953
};

src/blocks/basic_blocks.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
1414
auto bb = std::make_shared<basic_block>(std::to_string(basic_block_count));
1515
bb->parent = st;
1616
bb->ast_index = ast_index_counter++;
17+
bb->ast_depth = 0;
1718
work_list.push_back(bb);
1819
basic_block_count++;
1920
}
@@ -40,6 +41,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
4041
stmt_block_list.push_back(std::make_shared<basic_block>(std::to_string(basic_block_count++)));
4142
stmt_block_list.back()->parent = st;
4243
stmt_block_list.back()->ast_index = ast_index_counter++;
44+
stmt_block_list.back()->ast_depth = bb->ast_depth + 1;
4345
}
4446

4547
// set the basic block successors
@@ -77,6 +79,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
7779
auto exit_bb = std::make_shared<basic_block>("exit" + std::to_string(basic_block_count));
7880
// assign it a empty stmt_block as parent
7981
exit_bb->parent = std::make_shared<stmt_block>();
82+
// set the ast depth of the basic block
83+
exit_bb->ast_depth = bb->ast_depth;
8084
// check if this is the last block, if yes the successor will be empty
8185
if (bb->successor.size()) {
8286
// set the successor to the block that if_stmt successor pointer to earlier
@@ -94,6 +98,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
9498
auto then_bb = std::make_shared<basic_block>(std::to_string(++basic_block_count));
9599
// set the parent of this block as the then stmts
96100
then_bb->parent = if_stmt_->then_stmt;
101+
// set the ast depth of the basic block
102+
then_bb->ast_depth = bb->ast_depth;
97103
// set the successor of this block to be the exit block
98104
then_bb->successor.push_back(exit_bb);
99105
// set the successor of the original if_stmt block to be this then block
@@ -106,6 +112,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
106112
auto else_bb = std::make_shared<basic_block>(std::to_string(++basic_block_count));
107113
// set the parent of this block as the else stmts
108114
else_bb->parent = if_stmt_->else_stmt;
115+
// set the ast depth of the basic block
116+
else_bb->ast_depth = bb->ast_depth;
109117
// set the successor of this block to be the exit block
110118
else_bb->successor.push_back(exit_bb);
111119
// set the successor of the orignal if_stmt block to be this else block

src/blocks/dominance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg)
1616

1717
void dominator_analysis::postorder_idom_helper(std::vector<bool> &visited, int id) {
1818
for (int idom_id: idom_map[id]) {
19-
std::cerr << idom_id << "\n";
19+
// std::cerr << idom_id << "\n";
2020
if (idom_id != -1 && !visited[idom_id]) {
2121
visited[idom_id] = true;
2222
postorder_idom_helper(visited, idom_id);

src/blocks/loops.cpp

Lines changed: 210 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ std::shared_ptr<loop> loop_info::allocate_loop(std::shared_ptr<basic_block> head
1010
return loops.back();
1111
}
1212

13+
void loop_info::postorder_dfs_helper(std::vector<int> &postorder_loops_map, std::vector<bool> &visited_loops, int id) {
14+
for (auto subloop: loops[id]->subloops) {
15+
if (!visited_loops[subloop->loop_id]) {
16+
visited_loops[subloop->loop_id] = true;
17+
postorder_dfs_helper(postorder_loops_map, visited_loops, subloop->loop_id);
18+
postorder_loops_map.push_back(subloop->loop_id);
19+
}
20+
}
21+
}
22+
1323
void loop_info::analyze() {
1424
std::vector<int> idom = dta.get_idom();
1525

@@ -126,4 +136,203 @@ void loop_info::analyze() {
126136
}
127137
}
128138
}
129-
}
139+
140+
// Assign id to the loops
141+
for (unsigned int i = 0; i < loops.size(); i++) {
142+
loops[i]->loop_id = i;
143+
}
144+
145+
// build a loop tree
146+
std::vector<bool> visited_loops(loops.size());
147+
visited_loops.assign(visited_loops.size(), false);
148+
for (auto loop: top_level_loops) {
149+
std::vector<int> postorder_loop_tree;
150+
visited_loops[loop->loop_id] = true;
151+
152+
postorder_dfs_helper(postorder_loop_tree, visited_loops, loop->loop_id);
153+
postorder_loop_tree.push_back(loop->loop_id);
154+
postorder_loops_map[loop->loop_id] = postorder_loop_tree;
155+
}
156+
}
157+
158+
static stmt::Ptr get_loop_block(std::shared_ptr<basic_block> loop_header, block::stmt_block::Ptr ast) {
159+
block::stmt::Ptr current_ast = to<block::stmt>(ast);
160+
std::vector<stmt::Ptr> current_block = to<block::stmt_block>(current_ast)->stmts;
161+
// unsigned int ast_index = loop_header->ast_index;
162+
std::deque<stmt::Ptr> worklist;
163+
std::map<stmt::Ptr, stmt::Ptr> ast_parent_map;
164+
165+
for (auto stmt: current_block) {
166+
ast_parent_map[stmt] = current_ast;
167+
}
168+
worklist.insert(worklist.end(), current_block.begin(), current_block.end());
169+
170+
while (worklist.size()) {
171+
stmt::Ptr worklist_top = worklist.front();
172+
worklist.pop_front();
173+
174+
if (isa<block::stmt_block>(worklist_top)) {
175+
stmt_block::Ptr wl_stmt_block = to<stmt_block>(worklist_top);
176+
for (auto stmt: wl_stmt_block->stmts) {
177+
ast_parent_map[stmt] = worklist_top;
178+
}
179+
worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end());
180+
}
181+
else if (isa<block::if_stmt>(worklist_top)) {
182+
if_stmt::Ptr wl_if_stmt = to<if_stmt>(worklist_top);
183+
184+
if (to<stmt_block>(wl_if_stmt->then_stmt)->stmts.size() != 0) {
185+
stmt_block::Ptr wl_if_then_stmt = to<stmt_block>(wl_if_stmt->then_stmt);
186+
for (auto stmt: wl_if_then_stmt->stmts) {
187+
ast_parent_map[stmt] = worklist_top;
188+
}
189+
worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end());
190+
}
191+
if (to<stmt_block>(wl_if_stmt->else_stmt)->stmts.size() != 0) {
192+
stmt_block::Ptr wl_if_else_stmt = to<stmt_block>(wl_if_stmt->else_stmt);
193+
for (auto stmt: wl_if_else_stmt->stmts) {
194+
ast_parent_map[stmt] = worklist_top;
195+
}
196+
worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end());
197+
}
198+
}
199+
else if (isa<block::label_stmt>(worklist_top)) {
200+
label_stmt::Ptr wl_label_stmt = to<label_stmt>(worklist_top);
201+
if (worklist_top == loop_header->parent)
202+
return ast_parent_map[worklist_top];
203+
}
204+
else if (isa<block::goto_stmt>(worklist_top)) {
205+
goto_stmt::Ptr wl_goto_stmt = to<goto_stmt>(worklist_top);
206+
if (worklist_top == loop_header->parent)
207+
return ast_parent_map[worklist_top];
208+
}
209+
}
210+
211+
return nullptr;
212+
}
213+
214+
static void replace_loop_latches(std::shared_ptr<loop> loop, block::stmt_block::Ptr ast) {
215+
for (auto latch : loop->loop_latch_blocks) {
216+
stmt::Ptr loop_latch_ast = get_loop_block(latch, ast);
217+
if (isa<stmt_block>(loop_latch_ast)) {
218+
std::vector<stmt::Ptr> &temp_loop_ast = to<stmt_block>(loop_latch_ast)->stmts;
219+
std::replace(temp_loop_ast.begin(), temp_loop_ast.end(), temp_loop_ast[latch->ast_index], to<stmt>(std::make_shared<continue_stmt>()));
220+
}
221+
else if (isa<if_stmt>(loop_latch_ast)) {
222+
stmt_block::Ptr if_then_block = to<block::stmt_block>(to<block::if_stmt>(loop_latch_ast)->then_stmt);
223+
stmt_block::Ptr if_else_block = to<block::stmt_block>(to<block::if_stmt>(loop_latch_ast)->else_stmt);
224+
225+
if (if_then_block->stmts.size() && if_then_block->stmts[latch->ast_index] == latch->parent) {
226+
std::replace(if_then_block->stmts.begin(), if_then_block->stmts.end(), if_then_block->stmts[latch->ast_index], to<stmt>(std::make_shared<continue_stmt>()));
227+
}
228+
else if (if_else_block->stmts.size() && if_else_block->stmts[latch->ast_index] == latch->parent) {
229+
std::replace(if_else_block->stmts.begin(), if_else_block->stmts.end(), if_else_block->stmts[latch->ast_index], to<stmt>(std::make_shared<continue_stmt>()));
230+
}
231+
}
232+
}
233+
}
234+
235+
block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) {
236+
for (auto loop_map: postorder_loops_map) {
237+
// std::cerr << "== top level loop tree ==\n";
238+
for (auto postorder: loop_map.second) {
239+
// std::cerr << postorder <<"\n";
240+
block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast);
241+
242+
while_stmt::Ptr while_block = std::make_shared<while_stmt>();
243+
while_block->cond = std::make_shared<int_const>();
244+
to<int_const>(while_block->cond)->value = 1;
245+
while_block->body = std::make_shared<stmt_block>();
246+
247+
if (isa<block::stmt_block>(loop_header_ast)) {
248+
unsigned int ast_index = loops[postorder]->header_block->ast_index;
249+
if (to<block::stmt_block>(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) {
250+
stmt_block::Ptr then_block = to<block::stmt_block>(to<block::if_stmt>(to<block::stmt_block>(loop_header_ast)->stmts[ast_index + 1])->then_stmt);
251+
stmt_block::Ptr else_block = to<block::stmt_block>(to<block::if_stmt>(to<block::stmt_block>(loop_header_ast)->stmts[ast_index + 1])->else_stmt);
252+
253+
// if (isa<goto_stmt>(then_block->stmts.back())) {
254+
// then_block->stmts.pop_back();
255+
// then_block->stmts.push_back(std::make_shared<continue_stmt>());
256+
// }
257+
replace_loop_latches(loops[postorder], ast);
258+
259+
else_block->stmts.push_back(std::make_shared<break_stmt>());
260+
to<stmt_block>(while_block->body)->stmts.push_back(to<block::stmt_block>(loop_header_ast)->stmts[ast_index + 1]);
261+
// while_block->cond = to<block::if_stmt>(to<block::stmt_block>(loop_header_ast)->stmts[ast_index + 1])->cond;
262+
// while_block->dump(std::cerr, 0);
263+
// std::cerr << "found loop header in stmt block\n";
264+
265+
// if block to be replaced with while block
266+
std::vector<stmt::Ptr> &temp_ast = to<block::stmt_block>(loop_header_ast)->stmts;
267+
std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to<stmt>(while_block));
268+
temp_ast.erase(temp_ast.begin() + ast_index);
269+
}
270+
else {
271+
// std::cerr << "not found loop header in stmt block\n";
272+
}
273+
}
274+
else if (isa<block::if_stmt>(loop_header_ast)) {
275+
unsigned int ast_index = loops[postorder]->header_block->ast_index;
276+
stmt_block::Ptr if_then_block = to<block::stmt_block>(to<block::if_stmt>(loop_header_ast)->then_stmt);
277+
stmt_block::Ptr if_else_block = to<block::stmt_block>(to<block::if_stmt>(loop_header_ast)->else_stmt);
278+
279+
if (if_then_block->stmts.size() != 0) {
280+
if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) {
281+
stmt_block::Ptr then_block = to<block::stmt_block>(to<block::if_stmt>(if_then_block->stmts[ast_index + 1])->then_stmt);
282+
stmt_block::Ptr else_block = to<block::stmt_block>(to<block::if_stmt>(if_then_block->stmts[ast_index + 1])->else_stmt);
283+
284+
replace_loop_latches(loops[postorder], ast);
285+
286+
else_block->stmts.push_back(std::make_shared<break_stmt>());
287+
to<stmt_block>(while_block->body)->stmts.push_back(if_then_block->stmts[ast_index + 1]);
288+
// while_block->cond = to<block::if_stmt>(loop_header_ast)->cond;
289+
290+
// while_block->dump(std::cerr, 0);
291+
// std::cerr << "found loop header in if-then stmt\n";
292+
293+
// if block to be replaced with while block
294+
std::vector<stmt::Ptr> &temp_ast = if_then_block->stmts;
295+
std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to<stmt>(while_block));
296+
temp_ast.erase(temp_ast.begin() + ast_index);
297+
}
298+
else {
299+
// loop_header_ast->dump(std::cerr, 0);
300+
// std::cerr << "not found loop header in if-then stmt\n";
301+
}
302+
}
303+
else if (if_else_block->stmts.size() != 0) {
304+
if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) {
305+
stmt_block::Ptr then_block = to<block::stmt_block>(to<block::if_stmt>(if_else_block->stmts[ast_index + 1])->then_stmt);
306+
stmt_block::Ptr else_block = to<block::stmt_block>(to<block::if_stmt>(if_else_block->stmts[ast_index + 1])->else_stmt);
307+
308+
replace_loop_latches(loops[postorder], ast);
309+
310+
else_block->stmts.push_back(std::make_shared<break_stmt>());
311+
to<stmt_block>(while_block->body)->stmts.push_back(if_else_block->stmts[ast_index + 1]);
312+
// while_block->cond = to<block::if_stmt>(loop_header_ast)->cond;
313+
314+
// while_block->dump(std::cerr, 0);
315+
// std::cerr << "found loop header in if-else stmt\n";
316+
317+
// if block to be replaced with while block
318+
std::vector<stmt::Ptr> &temp_ast = if_else_block->stmts;
319+
std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to<stmt>(while_block));
320+
temp_ast.erase(temp_ast.begin() + ast_index);
321+
}
322+
else {
323+
// loop_header_ast->dump(std::cerr, 0);
324+
// std::cerr << "not found loop header in if-else stmt\n";
325+
}
326+
}
327+
}
328+
else {
329+
// std::cerr << "loop header not found\n";
330+
}
331+
// insert into AST - std::replace
332+
// set the ast to loop depth + 1
333+
// loops[loop_tree.first]->header_block->ast_index
334+
}
335+
}
336+
337+
return ast;
338+
}

src/builder/builder_context.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
300300
for (auto pred: bb->predecessor) {
301301
std::cerr << pred->name << ", ";
302302
}
303+
std::cerr << bb->ast_depth;
303304
std::cerr << "\n";
304305
if (bb->branch_expr) {
305306
std::cerr << " ";
@@ -386,14 +387,30 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
386387
for (auto subl: loop->subloops) std::cerr << "(loop header: " << subl->header_block->id << ") ";
387388
std::cerr << "\n";
388389
}
390+
391+
std::cerr << "++++++ top level loops ++++++ \n";
392+
for (auto top_level_loop: LI.top_level_loops) std::cerr << "(loop header: " << top_level_loop->header_block->id << ") ";
393+
std::cerr << "\n";
394+
395+
std::cerr << "++++++ preorder loops tree ++++++ \n";
396+
for (auto loop_tree: LI.postorder_loops_map) {
397+
std::cerr << "loop tree root: (loop header: " << LI.loops[loop_tree.first]->header_block->id << ")\n";
398+
std::cerr << "postorder: ";
399+
for (auto node: loop_tree.second) std::cerr << node << " ";
400+
std::cerr << "\n";
401+
}
389402
std::cerr << "++++++ loop info ++++++ \n";
390403

404+
std::cerr << "++++++ convert to ast ++++++ \n";
405+
LI.convert_to_ast(block::to<block::stmt_block>(ast));
406+
std::cerr << "++++++ convert to ast ++++++ \n";
407+
391408
if (feature_unstructured)
392409
return ast;
393410

394-
block::loop_finder finder;
395-
finder.ast = ast;
396-
ast->accept(&finder);
411+
// block::loop_finder finder;
412+
// finder.ast = ast;
413+
// ast->accept(&finder);
397414

398415
block::for_loop_finder for_finder;
399416
for_finder.ast = ast;

0 commit comments

Comments
 (0)