From d73be04909820a1df4e5952fd41156a0409d1241 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Tue, 16 May 2023 01:15:23 +0530 Subject: [PATCH 01/24] Add support for basic blocks and CFGs Added class for representing basic blocks, and a helper function to generate basic blocks from AST. For testing, disabled the loop_finder code. --- include/blocks/basic_blocks.h | 22 +++++ include/blocks/loop_finder.h | 1 + src/blocks/basic_blocks.cpp | 157 ++++++++++++++++++++++++++++++++++ src/blocks/loop_finder.cpp | 17 ++++ 4 files changed, 197 insertions(+) create mode 100644 include/blocks/basic_blocks.h create mode 100644 src/blocks/basic_blocks.cpp diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h new file mode 100644 index 0000000..c9e92de --- /dev/null +++ b/include/blocks/basic_blocks.h @@ -0,0 +1,22 @@ +#ifndef BASIC_BLOCKS_H +#define BASIC_BLOCKS_H +#include "blocks/block_visitor.h" +#include "blocks/stmt.h" +#include +#include +#include + +class basic_block { + public: + basic_block(std::string label): name(label) {}; + + std::vector> predecessor; + std::vector> successor; + block::expr::Ptr branch_expr; + block::stmt::Ptr parent; + std::string name; +}; + +std::vector> generate_basic_blocks(block::stmt_block::Ptr ast); + +#endif \ No newline at end of file diff --git a/include/blocks/loop_finder.h b/include/blocks/loop_finder.h index 800de65..a1caa66 100644 --- a/include/blocks/loop_finder.h +++ b/include/blocks/loop_finder.h @@ -2,6 +2,7 @@ #define LOOP_FINDER_H #include "blocks/block_visitor.h" #include "blocks/stmt.h" +#include "blocks/basic_blocks.h" namespace block { class loop_finder : public block_visitor { diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp new file mode 100644 index 0000000..2457703 --- /dev/null +++ b/src/blocks/basic_blocks.cpp @@ -0,0 +1,157 @@ +#include "blocks/basic_blocks.h" +#include + +using namespace block; + +std::vector> generate_basic_blocks(block::stmt_block::Ptr ast) { + std::deque> work_list; + std::vector> return_list; + int basic_block_count = 0; + + // step 1: fill the work_list + for (auto st: ast->stmts) { + auto bb = std::make_shared(std::to_string(basic_block_count)); + bb->parent = st; + work_list.push_back(bb); + basic_block_count++; + } + + // step 2: add successors + for (unsigned i = 0; work_list.size() != 0 && i < work_list.size() - 1; i++) { + work_list[i]->successor.push_back(work_list[i+1]); + } + + // step 3: process blocks + while (work_list.size()) { + auto bb = work_list.front(); + + if (isa(bb->parent)) { + stmt_block::Ptr stmt_block_ = to(bb->parent); + bb->name = "stmt" + bb->name; + + if (stmt_block_->stmts.size() > 0) { + std::vector> stmt_block_list; + + for (auto st: stmt_block_->stmts) { + stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); + stmt_block_list.back()->parent = st; + } + + for (unsigned i = 0; stmt_block_list.size() != 0 && i < stmt_block_list.size() - 1; i++) { + stmt_block_list[i]->successor.push_back(stmt_block_list[i+1]); + } + + stmt_block_list.back()->successor.push_back(bb->successor.front()); + bb->successor.clear(); + bb->successor.push_back(stmt_block_list.front()); + + return_list.push_back(bb); + work_list.pop_front(); + work_list.insert(work_list.begin(), stmt_block_list.begin(), stmt_block_list.end()); + } + else { + return_list.push_back(bb); + work_list.pop_front(); + } + } + else if (isa(bb->parent)) { + bb->name = "if" + bb->name; + + if_stmt::Ptr if_stmt_ = to(bb->parent); + // assign the if condition to the basic block + bb->branch_expr = if_stmt_->cond; + + // create a exit block + auto exit_bb = std::make_shared("exit" + std::to_string(basic_block_count)); + // assign it a empty stmt_block as parent + exit_bb->parent = std::make_shared(); + // check if this is the last block, if yes the successor will be empty + if (bb->successor.size()) { + // set the successor to the block that if_stmt pointer to earlier + exit_bb->successor.push_back(bb->successor.front()); + // clear the successor block from the if_stmt + bb->successor.clear(); + } + // remove the if from the work_list + work_list.pop_front(); + // push the exit block to the work_list + work_list.push_front(exit_bb); + + // if there is a then_stmt, create a basic block for it + if (to(if_stmt_->then_stmt)->stmts.size() != 0) { + auto then_bb = std::make_shared(std::to_string(++basic_block_count)); + // set the parent of this block as the then stmts + then_bb->parent = if_stmt_->then_stmt; + // set the successor of this block to be the exit block + then_bb->successor.push_back(exit_bb); + // set the successor of the original if_stmt block to be this then block + bb->successor.push_back(then_bb); + // push the block to the work_list, to expand it further + work_list.push_front(then_bb); + } + // if there is a else_stmt, create a basic block for it + if (to(if_stmt_->else_stmt)->stmts.size() != 0) { + auto else_bb = std::make_shared(std::to_string(++basic_block_count)); + // set the parent of this block as the else stmts + else_bb->parent = if_stmt_->else_stmt; + // set the successor of this block to be the exit block + else_bb->successor.push_back(exit_bb); + // set the successor of the orignal if_stmt block to be this else block + bb->successor.push_back(else_bb); + // push the block to the work_list, to expand it further + work_list.insert(work_list.begin() + 1, else_bb); + } + + // if there is no else block, then have the exit block as successor as well. + if (bb->successor.size() <= 1) bb->successor.push_back(exit_bb); + + return_list.push_back(bb); + } + else if (isa(bb->parent)) { + bb->name = "expr" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "decl" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "label" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "goto" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "return" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + + basic_block_count++; + } + + // step 4: resolve goto calls to successors of labels + for (auto bb: return_list) { + if (isa(bb->parent)) { + auto goto_source = std::find_if(return_list.begin(), return_list.end(), + [bb](std::shared_ptr bb_l) { + if (isa(bb_l->parent)) { + return to(bb_l->parent)->label1 == to(bb->parent)->label1; + } + return false; + }); + if (goto_source != return_list.end()) { + bb->successor.clear(); + bb->successor.push_back(*goto_source); + } + } + } + + return return_list; +} \ No newline at end of file diff --git a/src/blocks/loop_finder.cpp b/src/blocks/loop_finder.cpp index 36ab18f..e43b7e6 100644 --- a/src/blocks/loop_finder.cpp +++ b/src/blocks/loop_finder.cpp @@ -204,6 +204,23 @@ static void merge_condition_with_loop(while_stmt::Ptr new_while) { } } } + std::cout << "++++++ basic blocks ++++++ \n"; + + // while (1) { + // label_stmt::Ptr found_label = nullptr; + // for (auto stmt : a->stmts) { + // if (isa(stmt)) { + // found_label = to(stmt); + // } + // } + // if (found_label == nullptr) + // break; + // visit_label(found_label, a); + // } + // // Once all labels are done, visit the instructions normally + // for (auto stmt : a->stmts) { + // stmt->accept(this); + // } } void loop_finder::visit_label(label_stmt::Ptr a, stmt_block::Ptr parent) { From c624e5bfe2c87f18171c335a27f415bc01343552 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Wed, 17 May 2023 00:28:42 +0530 Subject: [PATCH 02/24] Add code to populate the basic block predecessors --- src/blocks/basic_blocks.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 2457703..9458dc9 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -153,5 +153,12 @@ std::vector> generate_basic_blocks(block::stmt_bloc } } + // step 5: populate the predecessors + for (auto bb: return_list) { + for (auto succ: bb->successor) { + succ->predecessor.push_back(bb); + } + } + return return_list; } \ No newline at end of file From 851917ab62eb1d726236ccb6e4e14776b6cd2ae0 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Tue, 20 Jun 2023 19:33:04 +0530 Subject: [PATCH 03/24] Move the CFG generator driver to builder_context.cpp --- include/blocks/basic_blocks.h | 1 + include/blocks/loop_finder.h | 1 - include/builder/builder_context.h | 1 + src/blocks/basic_blocks.cpp | 17 +++++++++++++---- src/blocks/loop_finder.cpp | 17 ----------------- src/builder/builder_context.cpp | 22 ++++++++++++++++++++++ 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index c9e92de..7239298 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -14,6 +14,7 @@ class basic_block { std::vector> successor; block::expr::Ptr branch_expr; block::stmt::Ptr parent; + unsigned int index; std::string name; }; diff --git a/include/blocks/loop_finder.h b/include/blocks/loop_finder.h index a1caa66..800de65 100644 --- a/include/blocks/loop_finder.h +++ b/include/blocks/loop_finder.h @@ -2,7 +2,6 @@ #define LOOP_FINDER_H #include "blocks/block_visitor.h" #include "blocks/stmt.h" -#include "blocks/basic_blocks.h" namespace block { class loop_finder : public block_visitor { diff --git a/include/builder/builder_context.h b/include/builder/builder_context.h index 840fbca..92470d0 100644 --- a/include/builder/builder_context.h +++ b/include/builder/builder_context.h @@ -1,5 +1,6 @@ #ifndef BUILDER_CONTEXT #define BUILDER_CONTEXT +#include "blocks/basic_blocks.h" #include "blocks/expr.h" #include "blocks/stmt.h" #include "builder/forward_declarations.h" diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 9458dc9..4957fe7 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -12,6 +12,7 @@ std::vector> generate_basic_blocks(block::stmt_bloc for (auto st: ast->stmts) { auto bb = std::make_shared(std::to_string(basic_block_count)); bb->parent = st; + // bb->index = ; work_list.push_back(bb); basic_block_count++; } @@ -21,7 +22,7 @@ std::vector> generate_basic_blocks(block::stmt_bloc work_list[i]->successor.push_back(work_list[i+1]); } - // step 3: process blocks + // step 3: process blocks: every xx_stmt type statement is made out into a basic block while (work_list.size()) { auto bb = work_list.front(); @@ -31,22 +32,30 @@ std::vector> generate_basic_blocks(block::stmt_bloc if (stmt_block_->stmts.size() > 0) { std::vector> stmt_block_list; - + + // convert all statements of this stmt_block into a basic block for (auto st: stmt_block_->stmts) { stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); stmt_block_list.back()->parent = st; } - + + // set the basic block successors for (unsigned i = 0; stmt_block_list.size() != 0 && i < stmt_block_list.size() - 1; i++) { stmt_block_list[i]->successor.push_back(stmt_block_list[i+1]); } + // since we insert these stmts between bb1 ---> bb2 ==> bb1 ---> (bb-a1...bb-an) ---> bb2 + // point the successor of the stmt_block_list to the basic block that bb1's successor + // pointed to. After this, clear the bb1's successor and push the front of stmt_block_list + // to bb1's successor list. stmt_block_list.back()->successor.push_back(bb->successor.front()); bb->successor.clear(); bb->successor.push_back(stmt_block_list.front()); + // push a rather empty-ish basic block, which will branch to the next basic block, or the next statement. return_list.push_back(bb); work_list.pop_front(); + // now insert the pending blocks to be processed at the front of the work_list work_list.insert(work_list.begin(), stmt_block_list.begin(), stmt_block_list.end()); } else { @@ -67,7 +76,7 @@ std::vector> generate_basic_blocks(block::stmt_bloc exit_bb->parent = std::make_shared(); // check if this is the last block, if yes the successor will be empty if (bb->successor.size()) { - // set the successor to the block that if_stmt pointer to earlier + // set the successor to the block that if_stmt successor pointer to earlier exit_bb->successor.push_back(bb->successor.front()); // clear the successor block from the if_stmt bb->successor.clear(); diff --git a/src/blocks/loop_finder.cpp b/src/blocks/loop_finder.cpp index e43b7e6..36ab18f 100644 --- a/src/blocks/loop_finder.cpp +++ b/src/blocks/loop_finder.cpp @@ -204,23 +204,6 @@ static void merge_condition_with_loop(while_stmt::Ptr new_while) { } } } - std::cout << "++++++ basic blocks ++++++ \n"; - - // while (1) { - // label_stmt::Ptr found_label = nullptr; - // for (auto stmt : a->stmts) { - // if (isa(stmt)) { - // found_label = to(stmt); - // } - // } - // if (found_label == nullptr) - // break; - // visit_label(found_label, a); - // } - // // Once all labels are done, visit the instructions normally - // for (auto stmt : a->stmts) { - // stmt->accept(this); - // } } void loop_finder::visit_label(label_stmt::Ptr a, stmt_block::Ptr parent) { diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 0d47559..ac9a6f4 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -303,6 +303,28 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { block::eliminate_redundant_vars(ast); } + std::vector> BBs = generate_basic_blocks(block::to(ast)); + + std::cerr << "++++++ basic blocks ++++++ \n"; + for (auto bb: BBs) { + std::cerr << bb->name << ":" << " ; "; + for (auto pred: bb->predecessor) { + std::cerr << pred->name << ", "; + } + std::cerr << "\n"; + if (bb->branch_expr) { + std::cerr << " "; + bb->branch_expr->dump(std::cerr, 0); + } + std::cerr << " "; + std::cerr << "br "; + for (auto branches: bb->successor) { + std::cerr << branches->name << ", "; + } + std::cerr << "\n"; + } + std::cerr << "++++++ basic blocks ++++++ \n"; + if (feature_unstructured) return ast; From f0c30ad502663044be9a02ef16181c8ee9e50c07 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:56:59 +0530 Subject: [PATCH 04/24] Implement dominator_tree analysis pass Add support to build a dominator tree for a given CFG, and add APIs to use the dominator tree to find idoms and dominance information. --- include/blocks/basic_blocks.h | 1 + include/blocks/dominance.h | 34 +++++++++ include/builder/builder_context.h | 1 + src/blocks/basic_blocks.cpp | 5 ++ src/blocks/dominance.cpp | 116 ++++++++++++++++++++++++++++++ src/builder/builder_context.cpp | 24 ++++++- 6 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 include/blocks/dominance.h create mode 100644 src/blocks/dominance.cpp diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 7239298..3891b79 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -15,6 +15,7 @@ class basic_block { block::expr::Ptr branch_expr; block::stmt::Ptr parent; unsigned int index; + unsigned int id; std::string name; }; diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h new file mode 100644 index 0000000..5aa2f66 --- /dev/null +++ b/include/blocks/dominance.h @@ -0,0 +1,34 @@ +#ifndef DOMINANCE_H +#define DOMINANCE_H +#include "blocks/block_visitor.h" +#include "blocks/basic_blocks.h" +#include "blocks/stmt.h" +#include +#include +#include +#include +#include + +class dominator_tree { + public: + dominator_tree(std::vector> &cfg); + std::vector &get_postorder_bb_map(); + std::vector &get_postorder(); + std::vector &get_idom(); + int get_idom(int bb_id); + bool dominates(int bb1_id, int bb2_id); + bool is_reachable_from_entry(int bb_id); + void analyze(); + + private: + std::vector idom; + std::vector postorder; + std::vector postorder_bb_map; + std::vector> &cfg_; + void postorder_dfs_helper(std::vector &visited_bbs, int id); + void postorder_dfs(); + int intersect(int bb1_id, int bb2_id); +}; + + +#endif \ No newline at end of file diff --git a/include/builder/builder_context.h b/include/builder/builder_context.h index 92470d0..d95f181 100644 --- a/include/builder/builder_context.h +++ b/include/builder/builder_context.h @@ -1,6 +1,7 @@ #ifndef BUILDER_CONTEXT #define BUILDER_CONTEXT #include "blocks/basic_blocks.h" +#include "blocks/dominance.h" #include "blocks/expr.h" #include "blocks/stmt.h" #include "builder/forward_declarations.h" diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 4957fe7..afe43bf 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -169,5 +169,10 @@ std::vector> generate_basic_blocks(block::stmt_bloc } } + // step 6: assign each basic_block an id + for (unsigned int i = 0; i < return_list.size(); i++) { + return_list[i]->id = i; + } + return return_list; } \ No newline at end of file diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp new file mode 100644 index 0000000..1da6648 --- /dev/null +++ b/src/blocks/dominance.cpp @@ -0,0 +1,116 @@ +#include "blocks/dominance.h" + +using namespace block; + +dominator_tree::dominator_tree(std::vector> &cfg) : cfg_(cfg) { + // TODO: Add a check for size, it should be greater than 2. + idom.reserve(cfg_.size()); + idom.assign(cfg_.size(), -1); + postorder.reserve(cfg_.size()); + postorder_bb_map.reserve(cfg_.size()); + postorder_bb_map.assign(cfg_.size(), -1); + + // and call the anaylse function + analyze(); +} + +void dominator_tree::postorder_dfs_helper(std::vector &visited_bbs, int id) { + for (auto child: cfg_[id]->successor) { + if (!visited_bbs[child->id]) { + visited_bbs[child->id] = true; + postorder_dfs_helper(visited_bbs, child->id); + postorder.push_back(child->id); + } + } +} +void dominator_tree::postorder_dfs() { + std::vector visited_bbs(cfg_.size()); + visited_bbs.assign(visited_bbs.size(), false); + visited_bbs[0] = true; + + postorder_dfs_helper(visited_bbs, 0); + postorder.push_back(0); +} + +std::vector &dominator_tree::get_postorder_bb_map() { + return postorder_bb_map; +} + +std::vector &dominator_tree::get_postorder() { + return postorder; +} + +std::vector &dominator_tree::get_idom() { + return idom; +} + +int dominator_tree::get_idom(int bb_id) { + if (bb_id >= 0 && bb_id < idom.size()) { + return -1; + } + + return idom[bb_id]; +} +bool dominator_tree::dominates(int bb1_id, int bb2_id) { + if (bb1_id == 0) { + return true; + } + + int pointer = idom[bb2_id]; + while (pointer != 0) { + if (pointer == bb1_id) { + return true; + } + pointer = idom[pointer]; + } + + return false; +} + +bool dominator_tree::is_reachable_from_entry(int bb_id) { + return dominates(0, bb_id); +} + +int dominator_tree::intersect(int bb1_id, int bb2_id) { + while (bb1_id != bb2_id) { + if (postorder_bb_map[bb1_id] < postorder_bb_map[bb2_id]) { + bb1_id = idom[bb1_id]; + } + else { + bb2_id = idom[bb2_id]; + } + } + + return bb1_id; +} + +void dominator_tree::analyze() { + postorder_dfs(); + for (unsigned int i = 0; i < postorder.size(); i++) { + postorder_bb_map[postorder[i]] = i; + } + + idom[0] = 0; + bool change = false; + + do { + change = 0; + for (int i = postorder.size() - 2; i >= 0; i--) { + int postorder_bb_num = postorder[i]; + std::shared_ptr bb = cfg_[postorder_bb_num]; + int bb_id_idom = bb->predecessor[0]->id; + + for (unsigned int j = 1; j < bb->predecessor.size(); j++) { + int bb_id_idom_next = bb->predecessor[j]->id; + if (idom[bb_id_idom_next] != -1) { + bb_id_idom = intersect(bb_id_idom, bb_id_idom_next); + } + } + + if (idom[postorder_bb_num] != bb_id_idom) { + idom[postorder_bb_num] = bb_id_idom; + change = 1; + } + } + } while(change); +} \ No newline at end of file diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index ac9a6f4..806ce50 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -307,7 +307,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ basic blocks ++++++ \n"; for (auto bb: BBs) { - std::cerr << bb->name << ":" << " ; "; + std::cerr << bb->id << ":" << bb->name << ":" << " ; "; for (auto pred: bb->predecessor) { std::cerr << pred->name << ", "; } @@ -325,6 +325,28 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "++++++ basic blocks ++++++ \n"; + std::cerr << "++++++ dominance ++++++ \n"; + dominator_tree dom(BBs); + + std::cerr << "== postorder map ==\n"; + for (int i: dom.get_postorder_bb_map()) { + std::cerr << i << "\n"; + } + std::cerr << "== postorder map ==\n"; + + std::cerr << "== postorder ==\n"; + for (int i: dom.get_postorder()) { + std::cerr << i << "\n"; + } + std::cerr << "== postorder ==\n"; + + std::cerr << "== idom ==\n"; + for (int i: dom.get_idom()) { + std::cerr << i << "\n"; + } + std::cerr << "== idom ==\n"; + std::cerr << "++++++ dominance ++++++ \n"; + if (feature_unstructured) return ast; From cb06e5890d859a74c51eee378d14435db82a5509 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Wed, 12 Jul 2023 01:48:28 +0530 Subject: [PATCH 05/24] 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. --- include/blocks/basic_blocks.h | 8 ++--- include/blocks/dominance.h | 15 +++++++-- include/blocks/loops.h | 40 ++++++++++++++++++++++ include/builder/builder_context.h | 1 + src/blocks/basic_blocks.cpp | 6 ++-- src/blocks/dominance.cpp | 56 ++++++++++++++++++++++++------- src/blocks/loops.cpp | 9 +++++ src/builder/builder_context.cpp | 27 +++++++++++++-- 8 files changed, 138 insertions(+), 24 deletions(-) create mode 100644 include/blocks/loops.h create mode 100644 src/blocks/loops.cpp diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 3891b79..7ad660e 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -1,6 +1,5 @@ #ifndef BASIC_BLOCKS_H #define BASIC_BLOCKS_H -#include "blocks/block_visitor.h" #include "blocks/stmt.h" #include #include @@ -8,10 +7,11 @@ class basic_block { public: + typedef std::vector> cfg_block; basic_block(std::string label): name(label) {}; - std::vector> predecessor; - std::vector> successor; + cfg_block predecessor; + cfg_block successor; block::expr::Ptr branch_expr; block::stmt::Ptr parent; unsigned int index; @@ -19,6 +19,6 @@ class basic_block { std::string name; }; -std::vector> generate_basic_blocks(block::stmt_block::Ptr ast); +basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast); #endif \ No newline at end of file diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h index 5aa2f66..08eb2ce 100644 --- a/include/blocks/dominance.h +++ b/include/blocks/dominance.h @@ -3,28 +3,37 @@ #include "blocks/block_visitor.h" #include "blocks/basic_blocks.h" #include "blocks/stmt.h" +#include #include #include #include #include #include -class dominator_tree { +class dominator_analysis { public: - dominator_tree(std::vector> &cfg); + // struct dominator_tree_ { + // dominator_tree_(int id): bb_id(id); + // int bb_id; + // std::vector> child_nodes; + // } dominator_tree; + dominator_analysis(basic_block::cfg_block &cfg); std::vector &get_postorder_bb_map(); std::vector &get_postorder(); std::vector &get_idom(); + std::map> &get_idom_map(); int get_idom(int bb_id); + std::vector get_idom_map(int bb_id); bool dominates(int bb1_id, int bb2_id); bool is_reachable_from_entry(int bb_id); void analyze(); private: std::vector idom; + std::map> idom_map; std::vector postorder; std::vector postorder_bb_map; - std::vector> &cfg_; + basic_block::cfg_block &cfg_; void postorder_dfs_helper(std::vector &visited_bbs, int id); void postorder_dfs(); int intersect(int bb1_id, int bb2_id); diff --git a/include/blocks/loops.h b/include/blocks/loops.h new file mode 100644 index 0000000..3767545 --- /dev/null +++ b/include/blocks/loops.h @@ -0,0 +1,40 @@ +#ifndef LOOP_H +#define LOOP_H +#include "blocks/block_visitor.h" +#include "blocks/basic_blocks.h" +#include "blocks/dominance.h" +#include "blocks/stmt.h" + +using namespace block; +class loop { +public: + loop() = default; + +private: + struct loop_bounds_ { + stmt::Ptr ind_var; + // MISS: intial value of ind var + stmt::Ptr steps_ind_var; + // MISS: value of the step + // MISS: final value of the step + stmt::Ptr cond_ind_var; + // MISS: direction of step + stmt::Ptr entry_stmt; + } loop_bounds; + + basic_block::cfg_block exit_bbs; +}; + +class loop_info { +public: + loop_info(basic_block::cfg_block ast, dominator_analysis dt): parent_ast(ast), dta(dt) { + analyze(); + } +private: + basic_block::cfg_block parent_ast; + dominator_analysis dta; + // discover loops during traversal of the abstract syntax tree + void analyze(); +}; + +#endif \ No newline at end of file diff --git a/include/builder/builder_context.h b/include/builder/builder_context.h index d95f181..effaf62 100644 --- a/include/builder/builder_context.h +++ b/include/builder/builder_context.h @@ -2,6 +2,7 @@ #define BUILDER_CONTEXT #include "blocks/basic_blocks.h" #include "blocks/dominance.h" +#include "blocks/loops.h" #include "blocks/expr.h" #include "blocks/stmt.h" #include "builder/forward_declarations.h" diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index afe43bf..c18ec6d 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -3,9 +3,9 @@ using namespace block; -std::vector> generate_basic_blocks(block::stmt_block::Ptr ast) { +basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { std::deque> work_list; - std::vector> return_list; + basic_block::cfg_block return_list; int basic_block_count = 0; // step 1: fill the work_list @@ -31,7 +31,7 @@ std::vector> generate_basic_blocks(block::stmt_bloc bb->name = "stmt" + bb->name; if (stmt_block_->stmts.size() > 0) { - std::vector> stmt_block_list; + basic_block::cfg_block stmt_block_list; // convert all statements of this stmt_block into a basic block for (auto st: stmt_block_->stmts) { diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index 1da6648..fc80072 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -2,7 +2,7 @@ using namespace block; -dominator_tree::dominator_tree(std::vector> &cfg) : cfg_(cfg) { +dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) { // TODO: Add a check for size, it should be greater than 2. idom.reserve(cfg_.size()); idom.assign(cfg_.size(), -1); @@ -14,7 +14,7 @@ dominator_tree::dominator_tree(std::vector> &cfg) : analyze(); } -void dominator_tree::postorder_dfs_helper(std::vector &visited_bbs, int id) { +void dominator_analysis::postorder_dfs_helper(std::vector &visited_bbs, int id) { for (auto child: cfg_[id]->successor) { if (!visited_bbs[child->id]) { visited_bbs[child->id] = true; @@ -23,7 +23,7 @@ void dominator_tree::postorder_dfs_helper(std::vector &visited_bbs, int id } } } -void dominator_tree::postorder_dfs() { +void dominator_analysis::postorder_dfs() { std::vector visited_bbs(cfg_.size()); visited_bbs.assign(visited_bbs.size(), false); visited_bbs[0] = true; @@ -32,26 +32,39 @@ void dominator_tree::postorder_dfs() { postorder.push_back(0); } -std::vector &dominator_tree::get_postorder_bb_map() { +std::vector &dominator_analysis::get_postorder_bb_map() { return postorder_bb_map; } -std::vector &dominator_tree::get_postorder() { +std::vector &dominator_analysis::get_postorder() { return postorder; } -std::vector &dominator_tree::get_idom() { +std::vector &dominator_analysis::get_idom() { return idom; } -int dominator_tree::get_idom(int bb_id) { - if (bb_id >= 0 && bb_id < idom.size()) { +std::map> &dominator_analysis::get_idom_map() { + return idom_map; +} + +int dominator_analysis::get_idom(int bb_id) { + if (bb_id < 0 || bb_id >= (int)idom.size()) { return -1; } return idom[bb_id]; } -bool dominator_tree::dominates(int bb1_id, int bb2_id) { + +std::vector dominator_analysis::get_idom_map(int bb_id) { + if (bb_id < 0 || bb_id >= (int)idom_map.size()) { + return {}; + } + + return idom_map[bb_id]; +} + +bool dominator_analysis::dominates(int bb1_id, int bb2_id) { if (bb1_id == 0) { return true; } @@ -67,11 +80,11 @@ bool dominator_tree::dominates(int bb1_id, int bb2_id) { return false; } -bool dominator_tree::is_reachable_from_entry(int bb_id) { +bool dominator_analysis::is_reachable_from_entry(int bb_id) { return dominates(0, bb_id); } -int dominator_tree::intersect(int bb1_id, int bb2_id) { +int dominator_analysis::intersect(int bb1_id, int bb2_id) { while (bb1_id != bb2_id) { if (postorder_bb_map[bb1_id] < postorder_bb_map[bb2_id]) { bb1_id = idom[bb1_id]; @@ -84,7 +97,7 @@ int dominator_tree::intersect(int bb1_id, int bb2_id) { return bb1_id; } -void dominator_tree::analyze() { +void dominator_analysis::analyze() { postorder_dfs(); for (unsigned int i = 0; i < postorder.size(); i++) { postorder_bb_map[postorder[i]] = i; @@ -113,4 +126,23 @@ void dominator_tree::analyze() { } } } while(change); + + + // build a map of dominators for easy traversal. + for (unsigned int i = 0; i < idom.size(); i++) { + idom_map[idom[i]].push_back(i); + } + + for (unsigned int i = 0; i < idom.size(); i++) { + if (idom_map[i].empty()) + idom_map[i].push_back(-1); + } + + // for (auto key: idom_map) { + // std::cout << key.first << ": "; + // for (int id: key.second) { + // std::cout << id << " "; + // } + // std::cout << "\n"; + // } } \ No newline at end of file diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp new file mode 100644 index 0000000..71f8e1c --- /dev/null +++ b/src/blocks/loops.cpp @@ -0,0 +1,9 @@ +#include "blocks/loops.h" +#include + +void loop_info::analyze() { + std::vector idom = dta.get_idom(); + for (unsigned int i = 0; i < idom.size(); i++) { + std::cout << i << " : " << idom[i] << "\n"; + } +} diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 806ce50..f9054c1 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -303,7 +303,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { block::eliminate_redundant_vars(ast); } - std::vector> BBs = generate_basic_blocks(block::to(ast)); + basic_block::cfg_block BBs = generate_basic_blocks(block::to(ast)); std::cerr << "++++++ basic blocks ++++++ \n"; for (auto bb: BBs) { @@ -326,7 +326,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ basic blocks ++++++ \n"; std::cerr << "++++++ dominance ++++++ \n"; - dominator_tree dom(BBs); + dominator_analysis dom(BBs); std::cerr << "== postorder map ==\n"; for (int i: dom.get_postorder_bb_map()) { @@ -341,12 +341,35 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "== postorder ==\n"; std::cerr << "== idom ==\n"; + std::cerr << "get_idom(int) test: get_idom(0): " << dom.get_idom(0) << "\n"; + std::cerr << "get_idom(int) test: get_idom(-1): " << dom.get_idom(-1) << "\n"; + for (int i: dom.get_idom()) { std::cerr << i << "\n"; } std::cerr << "== idom ==\n"; + + std::cerr << "== idom map ==\n"; + std::cerr << "get_idom_map(int) test: get_idom_map(0): "; + for (int i : dom.get_idom_map(0)) std::cerr << i << " "; + std::cerr << "\n"; + + std::cerr << "get_idom_map(int) test: get_idom_map(-1): "; + for (int i : dom.get_idom_map(-1)) std::cerr << i << " "; + std::cerr << "\n"; + + for (auto children: dom.get_idom_map()) { + std::cerr << children.first << ": "; + for (int child: children.second) { + std::cerr << child << " "; + } + std::cerr << "\n"; + } + std::cerr << "== idom map ==\n"; + std::cerr << "++++++ dominance ++++++ \n"; + loop_info LI(BBs, dom); if (feature_unstructured) return ast; From a772a6032ce7e38cbe72751ce68d58b3bdab34e6 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 23 Jul 2023 01:56:43 +0530 Subject: [PATCH 06/24] Implement loop_info analysis pass This commit adds the analysis pass to find natural loops and subloops. It uses the algorithm from LLVM LoopInfo anaylsis pass for the same, heavily uses the dominance tree to find the backedges and loop headers. --- include/blocks/dominance.h | 6 +- include/blocks/loops.h | 17 +++-- src/blocks/dominance.cpp | 37 +++++++++-- src/blocks/loops.cpp | 111 +++++++++++++++++++++++++++++++- src/builder/builder_context.cpp | 23 +++++++ 5 files changed, 179 insertions(+), 15 deletions(-) diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h index 08eb2ce..a569019 100644 --- a/include/blocks/dominance.h +++ b/include/blocks/dominance.h @@ -18,12 +18,15 @@ class dominator_analysis { // std::vector> child_nodes; // } dominator_tree; dominator_analysis(basic_block::cfg_block &cfg); + basic_block::cfg_block &cfg_; std::vector &get_postorder_bb_map(); std::vector &get_postorder(); std::vector &get_idom(); std::map> &get_idom_map(); + std::vector &get_postorder_idom_map(); int get_idom(int bb_id); std::vector get_idom_map(int bb_id); + int get_postorder_idom_map(int idom_id); bool dominates(int bb1_id, int bb2_id); bool is_reachable_from_entry(int bb_id); void analyze(); @@ -31,9 +34,10 @@ class dominator_analysis { private: std::vector idom; std::map> idom_map; + std::vector postorder_idom; std::vector postorder; std::vector postorder_bb_map; - basic_block::cfg_block &cfg_; + void postorder_idom_helper(std::vector &visited, int id); void postorder_dfs_helper(std::vector &visited_bbs, int id); void postorder_dfs(); int intersect(int bb1_id, int bb2_id); diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 3767545..96f7e9b 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -8,9 +8,9 @@ using namespace block; class loop { public: - loop() = default; + loop(std::shared_ptr header): header_block(header) {} -private: +// private: struct loop_bounds_ { stmt::Ptr ind_var; // MISS: intial value of ind var @@ -22,17 +22,26 @@ class loop { stmt::Ptr entry_stmt; } loop_bounds; - basic_block::cfg_block exit_bbs; + basic_block::cfg_block blocks; + std::shared_ptr parent_loop; + std::shared_ptr header_block; + std::shared_ptr backedge_block; + std::vector> subloops; }; class loop_info { public: - loop_info(basic_block::cfg_block ast, dominator_analysis dt): parent_ast(ast), dta(dt) { + loop_info(basic_block::cfg_block ast, dominator_analysis &dt): parent_ast(ast), dta(dt) { analyze(); } + std::shared_ptr allocate_loop(std::shared_ptr header); + std::vector> loops; + std::vector> top_level_loops; + private: basic_block::cfg_block parent_ast; dominator_analysis dta; + std::map> bb_loop_map; // discover loops during traversal of the abstract syntax tree void analyze(); }; diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index fc80072..ef37cf2 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -14,6 +14,17 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) analyze(); } +void dominator_analysis::postorder_idom_helper(std::vector &visited, int id) { + for (int idom_id: idom_map[id]) { + std::cerr << idom_id << "\n"; + if (idom_id != -1 && !visited[idom_id]) { + visited[idom_id] = true; + postorder_idom_helper(visited, idom_id); + postorder_idom.push_back(idom_id); + } + } +} + void dominator_analysis::postorder_dfs_helper(std::vector &visited_bbs, int id) { for (auto child: cfg_[id]->successor) { if (!visited_bbs[child->id]) { @@ -48,6 +59,10 @@ std::map> &dominator_analysis::get_idom_map() { return idom_map; } +std::vector &dominator_analysis::get_postorder_idom_map() { + return postorder_idom; +} + int dominator_analysis::get_idom(int bb_id) { if (bb_id < 0 || bb_id >= (int)idom.size()) { return -1; @@ -64,6 +79,14 @@ std::vector dominator_analysis::get_idom_map(int bb_id) { return idom_map[bb_id]; } +int dominator_analysis::get_postorder_idom_map(int idom_id) { + if (idom_id < 0 || idom_id >= (int)postorder_idom.size()) { + return -1; + } + + return postorder_idom[idom_id]; +} + bool dominator_analysis::dominates(int bb1_id, int bb2_id) { if (bb1_id == 0) { return true; @@ -138,11 +161,11 @@ void dominator_analysis::analyze() { idom_map[i].push_back(-1); } - // for (auto key: idom_map) { - // std::cout << key.first << ": "; - // for (int id: key.second) { - // std::cout << id << " "; - // } - // std::cout << "\n"; - // } + // build a postorder visit list of idom_tree + std::vector visited_idom_nodes(idom_map.size()); + visited_idom_nodes.assign(visited_idom_nodes.size(), false); + visited_idom_nodes[0] = true; + + postorder_idom_helper(visited_idom_nodes, 0); + postorder_idom.push_back(0); } \ No newline at end of file diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 71f8e1c..dbdba0e 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -1,9 +1,114 @@ #include "blocks/loops.h" #include +std::shared_ptr loop_info::allocate_loop(std::shared_ptr header) { + if (!header) + return nullptr; + + loops.push_back(std::make_shared(header)); + bb_loop_map[header->id] = loops.back(); + return loops.back(); +} + void loop_info::analyze() { std::vector idom = dta.get_idom(); - for (unsigned int i = 0; i < idom.size(); i++) { - std::cout << i << " : " << idom[i] << "\n"; + + for (int idom_id: dta.get_postorder_idom_map()) { + std::vector backedges; + int header = idom_id; + + for (auto backedge: dta.cfg_[header]->predecessor) { + if (dta.dominates(header, backedge->id) && dta.is_reachable_from_entry(backedge->id)) { + backedges.push_back(backedge->id); + } + } + + if (!backedges.empty()) { + std::shared_ptr new_loop = allocate_loop(dta.cfg_[header]); + if (!new_loop) + continue; + + int num_blocks = 0; + int num_subloops = 0; + + auto backedge_iter = backedges.begin(); + // do a reverse CFG traversal to map basic blocks in this loop. + basic_block::cfg_block worklist(backedges.size()); + std::generate(worklist.begin(), worklist.end(), [&backedge_iter, this](){ + return dta.cfg_[*(backedge_iter++)]; + }); + + while (!worklist.empty()) { + unsigned int predecessor_bb_id = worklist.back()->id; + worklist.pop_back(); + + auto subloop_iter = bb_loop_map.find(predecessor_bb_id); + if (subloop_iter == bb_loop_map.end()) { + if (!dta.is_reachable_from_entry(predecessor_bb_id)) + continue; + + bb_loop_map[predecessor_bb_id] = new_loop; + ++num_blocks; + // loop has no blocks between header and backedge + if (predecessor_bb_id == new_loop->header_block->id) + continue; + + worklist.insert(worklist.end(), dta.cfg_[predecessor_bb_id]->predecessor.begin(), dta.cfg_[predecessor_bb_id]->predecessor.end()); + } + else { + // this block has already been discovered, mapped to some other loop + // find the outermost loop + std::shared_ptr subloop = subloop_iter->second; + while (subloop->parent_loop) { + subloop = subloop->parent_loop; + } + + if (subloop == new_loop) + continue; + + // discovered a subloop of this loop + subloop->parent_loop = new_loop; + ++num_subloops; + num_blocks = num_blocks + subloop->blocks.size(); + predecessor_bb_id = subloop->header_block->id; + + for (auto pred: dta.cfg_[predecessor_bb_id]->predecessor) { + auto loop_iter = bb_loop_map.find(pred->id); + // do not check if loop_iter != bb_loop_map.end(), as a results + // basic blocks that are not directly part of the natural loops + // are skipped, like loop latches. + if (loop_iter->second != subloop) + worklist.push_back(pred); + } + } + } + new_loop->subloops.reserve(num_subloops); + new_loop->blocks.reserve(num_blocks); + } } -} + + // populate all subloops and loops with blocks + for (auto bb_id: dta.get_postorder()) { + auto subloop_iter = bb_loop_map.find(bb_id); + std::shared_ptr subloop = nullptr; + if (subloop_iter != bb_loop_map.end() && (subloop = subloop_iter->second) && dta.cfg_[bb_id] == subloop_iter->second->header_block) { + // check if it is the outermost loop + if (subloop->parent_loop != nullptr) { + subloop->parent_loop->subloops.push_back(subloop); + } + else { + top_level_loops.push_back(subloop); + } + + std::reverse(subloop->blocks.begin(), subloop->blocks.end()); + std::reverse(subloop->subloops.begin(), subloop->subloops.end()); + + subloop = subloop->parent_loop; + } + + while (subloop) { + subloop->blocks.push_back(dta.cfg_[bb_id]); + subloop = subloop->parent_loop; + } + } +} \ No newline at end of file diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index f9054c1..b328d75 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -367,9 +367,32 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "== idom map ==\n"; + std::cerr << "== postorder idom ==\n"; + for (auto idom: dom.get_postorder_idom_map()) { + std::cerr << idom << "\n"; + } + std::cerr << "== postorder idom ==\n"; + std::cerr << "++++++ dominance ++++++ \n"; + std::cerr << "++++++ loop info ++++++ \n"; loop_info LI(BBs, dom); + int loop_num = 0; + for (auto loop: LI.loops) { + std::cerr << "++++++ loop " << loop_num++ << " ++++++ \n"; + + std::cerr << "loop headers: " << loop->header_block->id << "\n"; + std::cerr << "blocks: "; + for (auto bb: loop->blocks) std::cerr << bb->id << " "; + std::cerr << "\n"; + // std::cerr << "backedge: " << loop->backedge_block->id << "\n"; + std::cerr << "parent loop: (loop header: " << (loop->parent_loop ? (int)loop->parent_loop->header_block->id : -1) << ")\n"; + std::cerr << "subloops: "; + for (auto subl: loop->subloops) std::cerr << "(loop header: " << subl->header_block->id << ") "; + std::cerr << "\n"; + } + std::cerr << "++++++ loop info ++++++ \n"; + if (feature_unstructured) return ast; From 1cb4f469469677831efd7210c4e9f56131b3ab60 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sat, 29 Jul 2023 12:59:24 +0530 Subject: [PATCH 07/24] Add a index to track the location of the AST block out of which a basic block was carved out. --- include/blocks/basic_blocks.h | 2 +- src/blocks/basic_blocks.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 7ad660e..828f2e7 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -14,7 +14,7 @@ class basic_block { cfg_block successor; block::expr::Ptr branch_expr; block::stmt::Ptr parent; - unsigned int index; + unsigned int ast_index; unsigned int id; std::string name; }; diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index c18ec6d..a9c8aeb 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -9,10 +9,11 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { int basic_block_count = 0; // step 1: fill the work_list + unsigned int ast_index_counter = 0; for (auto st: ast->stmts) { auto bb = std::make_shared(std::to_string(basic_block_count)); bb->parent = st; - // bb->index = ; + bb->ast_index = ast_index_counter++; work_list.push_back(bb); basic_block_count++; } @@ -27,6 +28,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto bb = work_list.front(); if (isa(bb->parent)) { + ast_index_counter = 0; stmt_block::Ptr stmt_block_ = to(bb->parent); bb->name = "stmt" + bb->name; @@ -37,6 +39,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { for (auto st: stmt_block_->stmts) { stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); stmt_block_list.back()->parent = st; + stmt_block_list.back()->ast_index = ast_index_counter++; } // set the basic block successors From e88e82ea07be9e3f624e4bac023592ab7690e881 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sat, 29 Jul 2023 13:24:51 +0530 Subject: [PATCH 08/24] Added code to populate loop latch blocks in a loop --- include/blocks/loops.h | 4 +++- src/blocks/loops.cpp | 15 +++++++++++++++ src/builder/builder_context.cpp | 8 +++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 96f7e9b..c3ec74e 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -4,6 +4,7 @@ #include "blocks/basic_blocks.h" #include "blocks/dominance.h" #include "blocks/stmt.h" +#include using namespace block; class loop { @@ -23,9 +24,10 @@ class loop { } loop_bounds; basic_block::cfg_block blocks; + std::unordered_set blocks_id_map; std::shared_ptr parent_loop; std::shared_ptr header_block; - std::shared_ptr backedge_block; + basic_block::cfg_block loop_latch_blocks; std::vector> subloops; }; diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index dbdba0e..27adcf6 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -84,6 +84,7 @@ void loop_info::analyze() { } new_loop->subloops.reserve(num_subloops); new_loop->blocks.reserve(num_blocks); + new_loop->blocks_id_map.reserve(num_blocks); } } @@ -108,7 +109,21 @@ void loop_info::analyze() { while (subloop) { subloop->blocks.push_back(dta.cfg_[bb_id]); + subloop->blocks_id_map.insert(dta.cfg_[bb_id]->id); subloop = subloop->parent_loop; } } + + // Populate the loop latches + for (auto loop: loops) { + if (!loop->header_block) + continue; + + std::shared_ptr header = loop->header_block; + for (auto children: header->predecessor) { + if (loop->blocks_id_map.count(children->id)) { + loop->loop_latch_blocks.push_back(children); + } + } + } } \ No newline at end of file diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index b328d75..8b23233 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -382,11 +382,17 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ loop " << loop_num++ << " ++++++ \n"; std::cerr << "loop headers: " << loop->header_block->id << "\n"; + std::cerr << "blocks: "; for (auto bb: loop->blocks) std::cerr << bb->id << " "; std::cerr << "\n"; - // std::cerr << "backedge: " << loop->backedge_block->id << "\n"; + + std::cerr << "loop latches: "; + for (auto bb: loop->loop_latch_blocks) std::cerr << bb->id << " "; + std::cerr << "\n"; + std::cerr << "parent loop: (loop header: " << (loop->parent_loop ? (int)loop->parent_loop->header_block->id : -1) << ")\n"; + std::cerr << "subloops: "; for (auto subl: loop->subloops) std::cerr << "(loop header: " << subl->header_block->id << ") "; std::cerr << "\n"; From 25a842530065507a38a86d1a7e1a1e7097b78e3c Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 27 Aug 2023 02:12:56 +0530 Subject: [PATCH 09/24] WIP: Add infra to construct a while loop using the loop_info analysis --- include/blocks/basic_blocks.h | 1 + include/blocks/loops.h | 4 + src/blocks/basic_blocks.cpp | 8 ++ src/blocks/dominance.cpp | 2 +- src/blocks/loops.cpp | 211 +++++++++++++++++++++++++++++++- src/builder/builder_context.cpp | 23 +++- 6 files changed, 244 insertions(+), 5 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 828f2e7..937ccd2 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -15,6 +15,7 @@ class basic_block { block::expr::Ptr branch_expr; block::stmt::Ptr parent; unsigned int ast_index; + unsigned int ast_depth; unsigned int id; std::string name; }; diff --git a/include/blocks/loops.h b/include/blocks/loops.h index c3ec74e..1242e7c 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -23,6 +23,7 @@ class loop { stmt::Ptr entry_stmt; } loop_bounds; + unsigned int loop_id; basic_block::cfg_block blocks; std::unordered_set blocks_id_map; std::shared_ptr parent_loop; @@ -37,6 +38,8 @@ class loop_info { analyze(); } std::shared_ptr allocate_loop(std::shared_ptr header); + block::stmt_block::Ptr convert_to_ast(block::stmt_block::Ptr ast); + std::map> postorder_loops_map; std::vector> loops; std::vector> top_level_loops; @@ -44,6 +47,7 @@ class loop_info { basic_block::cfg_block parent_ast; dominator_analysis dta; std::map> bb_loop_map; + void postorder_dfs_helper(std::vector &postorder_loops_map, std::vector &visited_loops, int id); // discover loops during traversal of the abstract syntax tree void analyze(); }; diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index a9c8aeb..1261179 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -14,6 +14,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto bb = std::make_shared(std::to_string(basic_block_count)); bb->parent = st; bb->ast_index = ast_index_counter++; + bb->ast_depth = 0; work_list.push_back(bb); basic_block_count++; } @@ -40,6 +41,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); stmt_block_list.back()->parent = st; stmt_block_list.back()->ast_index = ast_index_counter++; + stmt_block_list.back()->ast_depth = bb->ast_depth + 1; } // set the basic block successors @@ -77,6 +79,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto exit_bb = std::make_shared("exit" + std::to_string(basic_block_count)); // assign it a empty stmt_block as parent exit_bb->parent = std::make_shared(); + // set the ast depth of the basic block + exit_bb->ast_depth = bb->ast_depth; // check if this is the last block, if yes the successor will be empty if (bb->successor.size()) { // 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) { auto then_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the then stmts then_bb->parent = if_stmt_->then_stmt; + // set the ast depth of the basic block + then_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block then_bb->successor.push_back(exit_bb); // 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) { auto else_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the else stmts else_bb->parent = if_stmt_->else_stmt; + // set the ast depth of the basic block + else_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block else_bb->successor.push_back(exit_bb); // set the successor of the orignal if_stmt block to be this else block diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index ef37cf2..72726ad 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -16,7 +16,7 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) void dominator_analysis::postorder_idom_helper(std::vector &visited, int id) { for (int idom_id: idom_map[id]) { - std::cerr << idom_id << "\n"; + // std::cerr << idom_id << "\n"; if (idom_id != -1 && !visited[idom_id]) { visited[idom_id] = true; postorder_idom_helper(visited, idom_id); diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 27adcf6..28cba63 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -10,6 +10,16 @@ std::shared_ptr loop_info::allocate_loop(std::shared_ptr head return loops.back(); } +void loop_info::postorder_dfs_helper(std::vector &postorder_loops_map, std::vector &visited_loops, int id) { + for (auto subloop: loops[id]->subloops) { + if (!visited_loops[subloop->loop_id]) { + visited_loops[subloop->loop_id] = true; + postorder_dfs_helper(postorder_loops_map, visited_loops, subloop->loop_id); + postorder_loops_map.push_back(subloop->loop_id); + } + } +} + void loop_info::analyze() { std::vector idom = dta.get_idom(); @@ -126,4 +136,203 @@ void loop_info::analyze() { } } } -} \ No newline at end of file + + // Assign id to the loops + for (unsigned int i = 0; i < loops.size(); i++) { + loops[i]->loop_id = i; + } + + // build a loop tree + std::vector visited_loops(loops.size()); + visited_loops.assign(visited_loops.size(), false); + for (auto loop: top_level_loops) { + std::vector postorder_loop_tree; + visited_loops[loop->loop_id] = true; + + postorder_dfs_helper(postorder_loop_tree, visited_loops, loop->loop_id); + postorder_loop_tree.push_back(loop->loop_id); + postorder_loops_map[loop->loop_id] = postorder_loop_tree; + } +} + +static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block::stmt_block::Ptr ast) { + block::stmt::Ptr current_ast = to(ast); + std::vector current_block = to(current_ast)->stmts; + // unsigned int ast_index = loop_header->ast_index; + std::deque worklist; + std::map ast_parent_map; + + for (auto stmt: current_block) { + ast_parent_map[stmt] = current_ast; + } + worklist.insert(worklist.end(), current_block.begin(), current_block.end()); + + while (worklist.size()) { + stmt::Ptr worklist_top = worklist.front(); + worklist.pop_front(); + + if (isa(worklist_top)) { + stmt_block::Ptr wl_stmt_block = to(worklist_top); + for (auto stmt: wl_stmt_block->stmts) { + ast_parent_map[stmt] = worklist_top; + } + worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end()); + } + else if (isa(worklist_top)) { + if_stmt::Ptr wl_if_stmt = to(worklist_top); + + if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { + stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); + for (auto stmt: wl_if_then_stmt->stmts) { + ast_parent_map[stmt] = worklist_top; + } + worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); + } + if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { + stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); + for (auto stmt: wl_if_else_stmt->stmts) { + ast_parent_map[stmt] = worklist_top; + } + worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); + } + } + else if (isa(worklist_top)) { + label_stmt::Ptr wl_label_stmt = to(worklist_top); + if (worklist_top == loop_header->parent) + return ast_parent_map[worklist_top]; + } + else if (isa(worklist_top)) { + goto_stmt::Ptr wl_goto_stmt = to(worklist_top); + if (worklist_top == loop_header->parent) + return ast_parent_map[worklist_top]; + } + } + + return nullptr; +} + +static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast) { + for (auto latch : loop->loop_latch_blocks) { + stmt::Ptr loop_latch_ast = get_loop_block(latch, ast); + if (isa(loop_latch_ast)) { + std::vector &temp_loop_ast = to(loop_latch_ast)->stmts; + std::replace(temp_loop_ast.begin(), temp_loop_ast.end(), temp_loop_ast[latch->ast_index], to(std::make_shared())); + } + else if (isa(loop_latch_ast)) { + stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); + stmt_block::Ptr if_else_block = to(to(loop_latch_ast)->else_stmt); + + if (if_then_block->stmts.size() && if_then_block->stmts[latch->ast_index] == latch->parent) { + std::replace(if_then_block->stmts.begin(), if_then_block->stmts.end(), if_then_block->stmts[latch->ast_index], to(std::make_shared())); + } + else if (if_else_block->stmts.size() && if_else_block->stmts[latch->ast_index] == latch->parent) { + std::replace(if_else_block->stmts.begin(), if_else_block->stmts.end(), if_else_block->stmts[latch->ast_index], to(std::make_shared())); + } + } + } +} + +block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { + for (auto loop_map: postorder_loops_map) { + // std::cerr << "== top level loop tree ==\n"; + for (auto postorder: loop_map.second) { + // std::cerr << postorder <<"\n"; + block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); + + while_stmt::Ptr while_block = std::make_shared(); + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + while_block->body = std::make_shared(); + + if (isa(loop_header_ast)) { + unsigned int ast_index = loops[postorder]->header_block->ast_index; + if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { + stmt_block::Ptr then_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->then_stmt); + stmt_block::Ptr else_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->else_stmt); + + // if (isa(then_block->stmts.back())) { + // then_block->stmts.pop_back(); + // then_block->stmts.push_back(std::make_shared()); + // } + replace_loop_latches(loops[postorder], ast); + + else_block->stmts.push_back(std::make_shared()); + to(while_block->body)->stmts.push_back(to(loop_header_ast)->stmts[ast_index + 1]); + // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; + // while_block->dump(std::cerr, 0); + // std::cerr << "found loop header in stmt block\n"; + + // if block to be replaced with while block + std::vector &temp_ast = to(loop_header_ast)->stmts; + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); + temp_ast.erase(temp_ast.begin() + ast_index); + } + else { + // std::cerr << "not found loop header in stmt block\n"; + } + } + else if (isa(loop_header_ast)) { + unsigned int ast_index = loops[postorder]->header_block->ast_index; + stmt_block::Ptr if_then_block = to(to(loop_header_ast)->then_stmt); + stmt_block::Ptr if_else_block = to(to(loop_header_ast)->else_stmt); + + if (if_then_block->stmts.size() != 0) { + if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + stmt_block::Ptr then_block = to(to(if_then_block->stmts[ast_index + 1])->then_stmt); + stmt_block::Ptr else_block = to(to(if_then_block->stmts[ast_index + 1])->else_stmt); + + replace_loop_latches(loops[postorder], ast); + + else_block->stmts.push_back(std::make_shared()); + to(while_block->body)->stmts.push_back(if_then_block->stmts[ast_index + 1]); + // while_block->cond = to(loop_header_ast)->cond; + + // while_block->dump(std::cerr, 0); + // std::cerr << "found loop header in if-then stmt\n"; + + // if block to be replaced with while block + std::vector &temp_ast = if_then_block->stmts; + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); + temp_ast.erase(temp_ast.begin() + ast_index); + } + else { + // loop_header_ast->dump(std::cerr, 0); + // std::cerr << "not found loop header in if-then stmt\n"; + } + } + else if (if_else_block->stmts.size() != 0) { + if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + stmt_block::Ptr then_block = to(to(if_else_block->stmts[ast_index + 1])->then_stmt); + stmt_block::Ptr else_block = to(to(if_else_block->stmts[ast_index + 1])->else_stmt); + + replace_loop_latches(loops[postorder], ast); + + else_block->stmts.push_back(std::make_shared()); + to(while_block->body)->stmts.push_back(if_else_block->stmts[ast_index + 1]); + // while_block->cond = to(loop_header_ast)->cond; + + // while_block->dump(std::cerr, 0); + // std::cerr << "found loop header in if-else stmt\n"; + + // if block to be replaced with while block + std::vector &temp_ast = if_else_block->stmts; + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); + temp_ast.erase(temp_ast.begin() + ast_index); + } + else { + // loop_header_ast->dump(std::cerr, 0); + // std::cerr << "not found loop header in if-else stmt\n"; + } + } + } + else { + // std::cerr << "loop header not found\n"; + } + // insert into AST - std::replace + // set the ast to loop depth + 1 + // loops[loop_tree.first]->header_block->ast_index + } + } + + return ast; +} diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 8b23233..5d47bc5 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -311,6 +311,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { for (auto pred: bb->predecessor) { std::cerr << pred->name << ", "; } + std::cerr << bb->ast_depth; std::cerr << "\n"; if (bb->branch_expr) { std::cerr << " "; @@ -397,14 +398,30 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { for (auto subl: loop->subloops) std::cerr << "(loop header: " << subl->header_block->id << ") "; std::cerr << "\n"; } + + std::cerr << "++++++ top level loops ++++++ \n"; + for (auto top_level_loop: LI.top_level_loops) std::cerr << "(loop header: " << top_level_loop->header_block->id << ") "; + std::cerr << "\n"; + + std::cerr << "++++++ preorder loops tree ++++++ \n"; + for (auto loop_tree: LI.postorder_loops_map) { + std::cerr << "loop tree root: (loop header: " << LI.loops[loop_tree.first]->header_block->id << ")\n"; + std::cerr << "postorder: "; + for (auto node: loop_tree.second) std::cerr << node << " "; + std::cerr << "\n"; + } std::cerr << "++++++ loop info ++++++ \n"; + std::cerr << "++++++ convert to ast ++++++ \n"; + LI.convert_to_ast(block::to(ast)); + std::cerr << "++++++ convert to ast ++++++ \n"; + if (feature_unstructured) return ast; - block::loop_finder finder; - finder.ast = ast; - ast->accept(&finder); + // block::loop_finder finder; + // finder.ast = ast; + // ast->accept(&finder); block::for_loop_finder for_finder; for_finder.ast = ast; From 79fd09e92b87de3cfc8e7199b5fc93a998fd8738 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 3 Sep 2023 22:02:59 +0530 Subject: [PATCH 10/24] WIP v2: Add infra to construct a while loop using the loop_info analysis (36/43 tests pass) --- include/blocks/basic_blocks.h | 2 + include/blocks/loops.h | 2 + src/blocks/basic_blocks.cpp | 8 + src/blocks/loops.cpp | 298 +++++++++++++++++++++++++------- src/builder/builder_context.cpp | 23 ++- 5 files changed, 267 insertions(+), 66 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 937ccd2..afe7055 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -4,6 +4,7 @@ #include #include #include +#include class basic_block { public: @@ -18,6 +19,7 @@ class basic_block { unsigned int ast_depth; unsigned int id; std::string name; + // static std::map> ast_to_basic_block_map; }; basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast); diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 1242e7c..f909d3c 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -40,6 +40,7 @@ class loop_info { std::shared_ptr allocate_loop(std::shared_ptr header); block::stmt_block::Ptr convert_to_ast(block::stmt_block::Ptr ast); std::map> postorder_loops_map; + std::map> preorder_loops_map; std::vector> loops; std::vector> top_level_loops; @@ -48,6 +49,7 @@ class loop_info { dominator_analysis dta; std::map> bb_loop_map; void postorder_dfs_helper(std::vector &postorder_loops_map, std::vector &visited_loops, int id); + void preorder_dfs_helper(std::vector &preorder_loops_map, std::vector &visited_loops, int id); // discover loops during traversal of the abstract syntax tree void analyze(); }; diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 1261179..76656a3 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -13,6 +13,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { for (auto st: ast->stmts) { auto bb = std::make_shared(std::to_string(basic_block_count)); bb->parent = st; + // bb->ast_to_basic_block_map[bb->parent] = bb; bb->ast_index = ast_index_counter++; bb->ast_depth = 0; work_list.push_back(bb); @@ -40,6 +41,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { for (auto st: stmt_block_->stmts) { stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); stmt_block_list.back()->parent = st; + // stmt_block_list.back()->ast_to_basic_block_map[bb->parent] = stmt_block_list.back(); stmt_block_list.back()->ast_index = ast_index_counter++; stmt_block_list.back()->ast_depth = bb->ast_depth + 1; } @@ -79,6 +81,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto exit_bb = std::make_shared("exit" + std::to_string(basic_block_count)); // assign it a empty stmt_block as parent exit_bb->parent = std::make_shared(); + // add mapping in ast to bb map + // exit_bb->ast_to_basic_block_map[exit_bb->parent] = exit_bb; // set the ast depth of the basic block exit_bb->ast_depth = bb->ast_depth; // check if this is the last block, if yes the successor will be empty @@ -98,6 +102,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto then_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the then stmts then_bb->parent = if_stmt_->then_stmt; + // add mapping in ast to bb map + // then_bb->ast_to_basic_block_map[then_bb->parent] = then_bb; // set the ast depth of the basic block then_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block @@ -112,6 +118,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto else_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the else stmts else_bb->parent = if_stmt_->else_stmt; + // add mapping in ast to bb map + // else_bb->ast_to_basic_block_map[else_bb->parent] = else_bb; // set the ast depth of the basic block else_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 28cba63..b77d824 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -1,5 +1,8 @@ #include "blocks/loops.h" #include +#include + +static std::vector>, stmt::Ptr>> worklist; std::shared_ptr loop_info::allocate_loop(std::shared_ptr header) { if (!header) @@ -20,6 +23,16 @@ void loop_info::postorder_dfs_helper(std::vector &postorder_loops_map, std: } } +void loop_info::preorder_dfs_helper(std::vector &preorder_loops_map, std::vector &visited_loops, int id) { + for (auto subloop: loops[id]->subloops) { + if (!visited_loops[subloop->loop_id]) { + visited_loops[subloop->loop_id] = true; + preorder_loops_map.push_back(subloop->loop_id); + preorder_dfs_helper(preorder_loops_map, visited_loops, subloop->loop_id); + } + } +} + void loop_info::analyze() { std::vector idom = dta.get_idom(); @@ -142,7 +155,7 @@ void loop_info::analyze() { loops[i]->loop_id = i; } - // build a loop tree + // build a postorder loop tree std::vector visited_loops(loops.size()); visited_loops.assign(visited_loops.size(), false); for (auto loop: top_level_loops) { @@ -153,14 +166,26 @@ void loop_info::analyze() { postorder_loop_tree.push_back(loop->loop_id); postorder_loops_map[loop->loop_id] = postorder_loop_tree; } + + // build a preorder loop tree + visited_loops.clear(); + visited_loops.assign(visited_loops.size(), false); + for (auto loop: top_level_loops) { + std::vector preorder_loop_tree; + visited_loops[loop->loop_id] = true; + + preorder_loop_tree.push_back(loop->loop_id); + preorder_dfs_helper(preorder_loop_tree, visited_loops, loop->loop_id); + preorder_loops_map[loop->loop_id] = preorder_loop_tree; + } } static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block::stmt_block::Ptr ast) { block::stmt::Ptr current_ast = to(ast); std::vector current_block = to(current_ast)->stmts; - // unsigned int ast_index = loop_header->ast_index; std::deque worklist; std::map ast_parent_map; + std::cerr << loop_header->name << "\n"; for (auto stmt: current_block) { ast_parent_map[stmt] = current_ast; @@ -180,8 +205,9 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: } else if (isa(worklist_top)) { if_stmt::Ptr wl_if_stmt = to(worklist_top); - + std::cerr << "found if: "; if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { + std::cerr << "then\n"; stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); for (auto stmt: wl_if_then_stmt->stmts) { ast_parent_map[stmt] = worklist_top; @@ -189,6 +215,7 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); } if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { + std::cerr << "else\n"; stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); for (auto stmt: wl_if_else_stmt->stmts) { ast_parent_map[stmt] = worklist_top; @@ -196,76 +223,151 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); } } + else if (isa(worklist_top)) { + stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); + for (auto stmt: wl_while_body_block->stmts) { + ast_parent_map[stmt] = worklist_top; + } + worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); + } else if (isa(worklist_top)) { + std::cerr << "found label\n"; + worklist_top->dump(std::cerr, 0); label_stmt::Ptr wl_label_stmt = to(worklist_top); if (worklist_top == loop_header->parent) return ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { + std::cerr << "found goto\n"; goto_stmt::Ptr wl_goto_stmt = to(worklist_top); if (worklist_top == loop_header->parent) return ast_parent_map[worklist_top]; } } + std::cerr << "Returned nullptr !\n"; return nullptr; } +// remove continue if last basic block static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast) { - for (auto latch : loop->loop_latch_blocks) { - stmt::Ptr loop_latch_ast = get_loop_block(latch, ast); + for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { + std::cerr << (*latch_iter)->ast_index << "\n"; + std::cerr << (*latch_iter)->parent.get() << "\n"; + stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); + // loop_latch_ast->dump(std::cerr, 0); + if (isa(loop_latch_ast)) { - std::vector &temp_loop_ast = to(loop_latch_ast)->stmts; - std::replace(temp_loop_ast.begin(), temp_loop_ast.end(), temp_loop_ast[latch->ast_index], to(std::make_shared())); + std::cerr << "stmt parent\n"; + std::vector &temp_ast = to(loop_latch_ast)->stmts; + if (latch_iter == loop->loop_latch_blocks.end() - 1) + temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); + else + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], to(std::make_shared())); } else if (isa(loop_latch_ast)) { stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); stmt_block::Ptr if_else_block = to(to(loop_latch_ast)->else_stmt); - - if (if_then_block->stmts.size() && if_then_block->stmts[latch->ast_index] == latch->parent) { - std::replace(if_then_block->stmts.begin(), if_then_block->stmts.end(), if_then_block->stmts[latch->ast_index], to(std::make_shared())); + + std::cerr << "if parent: "; + std::cerr << if_then_block->stmts.size() << " " << if_else_block->stmts.size() << " " << (*latch_iter)->ast_index << " "; + if (if_then_block->stmts.size() && if_then_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { + std::cerr << "then\n"; + std::vector &temp_ast = if_then_block->stmts; + if (latch_iter == loop->loop_latch_blocks.end() - 1) + temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); + else + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); } - else if (if_else_block->stmts.size() && if_else_block->stmts[latch->ast_index] == latch->parent) { - std::replace(if_else_block->stmts.begin(), if_else_block->stmts.end(), if_else_block->stmts[latch->ast_index], to(std::make_shared())); + + if (if_else_block->stmts.size() && if_else_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { + std::cerr << "else\n"; + std::vector &temp_ast = if_else_block->stmts; + if (latch_iter == loop->loop_latch_blocks.end() - 1) + temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); + else + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); } } + + // loop_latch_ast->dump(std::cerr, 0); } } block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { + // std::cerr << "before ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "before ast\n"; + + for (auto loop_map: preorder_loops_map) { + for (auto preorder: loop_map.second) { + replace_loop_latches(loops[preorder], ast); + } + } + + // std::cerr << "after ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "after ast\n"; + for (auto loop_map: postorder_loops_map) { - // std::cerr << "== top level loop tree ==\n"; for (auto postorder: loop_map.second) { - // std::cerr << postorder <<"\n"; + std::cerr << "before ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "before ast\n"; block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); - + std::cerr << loops[postorder]->header_block->ast_index << "\n"; + loop_header_ast->dump(std::cerr, 0); while_stmt::Ptr while_block = std::make_shared(); - while_block->cond = std::make_shared(); - to(while_block->cond)->value = 1; while_block->body = std::make_shared(); + if (isa(loop_header_ast)) { + loop_header_ast = to(loop_header_ast)->body; + } + if (isa(loop_header_ast)) { unsigned int ast_index = loops[postorder]->header_block->ast_index; - if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { + // handle unconditional loops + if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(to(loop_header_ast)->stmts[ast_index + 1])) { + for (auto bb: loops[postorder]->blocks) { + to(while_block->body)->stmts.push_back(bb->parent); + } + // pop loop backedge + to(while_block->body)->stmts.pop_back(); + + // set always true condition + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + + // unconditional loops can have only one backedge !? + assert(loops[postorder]->loop_latch_blocks.size() == 1); + for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + std::cerr << i << "\n"; + worklist.push_back(std::make_tuple(i, std::ref(to(loop_header_ast)->stmts), nullptr)); + } + + worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); + } + else if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { stmt_block::Ptr then_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->then_stmt); stmt_block::Ptr else_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->else_stmt); + std::cerr << "stmt block\n"; + + while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; + if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + } - // if (isa(then_block->stmts.back())) { - // then_block->stmts.pop_back(); - // then_block->stmts.push_back(std::make_shared()); - // } - replace_loop_latches(loops[postorder], ast); - - else_block->stmts.push_back(std::make_shared()); - to(while_block->body)->stmts.push_back(to(loop_header_ast)->stmts[ast_index + 1]); - // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; - // while_block->dump(std::cerr, 0); - // std::cerr << "found loop header in stmt block\n"; - + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } // if block to be replaced with while block - std::vector &temp_ast = to(loop_header_ast)->stmts; - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); - temp_ast.erase(temp_ast.begin() + ast_index); + worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); } else { // std::cerr << "not found loop header in stmt block\n"; @@ -277,50 +379,97 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { stmt_block::Ptr if_else_block = to(to(loop_header_ast)->else_stmt); if (if_then_block->stmts.size() != 0) { - if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + std::cerr << "if then block\n"; + // handle unconditional loops + if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_then_block->stmts[ast_index + 1])) { + for (auto bb: loops[postorder]->blocks) { + to(while_block->body)->stmts.push_back(bb->parent); + } + // pop loop backedge + to(while_block->body)->stmts.pop_back(); + + // set always true condition + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + + // unconditional loops can have only one backedge !? + assert(loops[postorder]->loop_latch_blocks.size() == 1); + for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + worklist.push_back(std::make_tuple(i, std::ref(if_then_block->stmts), nullptr)); + } + + worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); + } + else if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { stmt_block::Ptr then_block = to(to(if_then_block->stmts[ast_index + 1])->then_stmt); stmt_block::Ptr else_block = to(to(if_then_block->stmts[ast_index + 1])->else_stmt); - replace_loop_latches(loops[postorder], ast); - - else_block->stmts.push_back(std::make_shared()); - to(while_block->body)->stmts.push_back(if_then_block->stmts[ast_index + 1]); - // while_block->cond = to(loop_header_ast)->cond; - - // while_block->dump(std::cerr, 0); - // std::cerr << "found loop header in if-then stmt\n"; - + while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; + if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + } + + + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } // if block to be replaced with while block - std::vector &temp_ast = if_then_block->stmts; - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); - temp_ast.erase(temp_ast.begin() + ast_index); + worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); } else { - // loop_header_ast->dump(std::cerr, 0); // std::cerr << "not found loop header in if-then stmt\n"; } } else if (if_else_block->stmts.size() != 0) { - if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + std::cerr << "if else block\n"; + // handle unconditional loops + if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_else_block->stmts[ast_index + 1])) { + for (auto bb: loops[postorder]->blocks) { + to(while_block->body)->stmts.push_back(bb->parent); + } + // pop loop backedge + to(while_block->body)->stmts.pop_back(); + + // set always true condition + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + + // unconditional loops can have only one backedge !? + assert(loops[postorder]->loop_latch_blocks.size() == 1); + for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + worklist.push_back(std::make_tuple(i, std::ref(if_else_block->stmts), nullptr)); + } + + worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); + } + else if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { stmt_block::Ptr then_block = to(to(if_else_block->stmts[ast_index + 1])->then_stmt); stmt_block::Ptr else_block = to(to(if_else_block->stmts[ast_index + 1])->else_stmt); - replace_loop_latches(loops[postorder], ast); - - else_block->stmts.push_back(std::make_shared()); - to(while_block->body)->stmts.push_back(if_else_block->stmts[ast_index + 1]); - // while_block->cond = to(loop_header_ast)->cond; - - // while_block->dump(std::cerr, 0); - // std::cerr << "found loop header in if-else stmt\n"; - + while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; + if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + } + + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } // if block to be replaced with while block - std::vector &temp_ast = if_else_block->stmts; - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[ast_index + 1], to(while_block)); - temp_ast.erase(temp_ast.begin() + ast_index); + worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); } else { - // loop_header_ast->dump(std::cerr, 0); // std::cerr << "not found loop header in if-else stmt\n"; } } @@ -328,9 +477,30 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { else { // std::cerr << "loop header not found\n"; } - // insert into AST - std::replace - // set the ast to loop depth + 1 - // loops[loop_tree.first]->header_block->ast_index + + // process worklist + std::sort(worklist.begin(), worklist.end(), [](std::tuple>, stmt::Ptr> a, std::tuple>, stmt::Ptr> b) { + return std::get<0>(a) > std::get<0>(b); + }); + for (auto item : worklist) { + std::vector &temp_ast = std::get<1>(item); + if (std::get<2>(item)) { + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[std::get<0>(item) + 1], std::get<2>(item)); + temp_ast.erase(temp_ast.begin() + std::get<0>(item)); + } + } + + for (auto item : worklist) { + std::vector &temp_ast = std::get<1>(item); + if (!std::get<2>(item)) { + temp_ast.erase(temp_ast.begin() + std::get<0>(item)); + } + } + worklist.clear(); + + std::cerr << "after ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "after ast\n"; } } diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 5d47bc5..600f713 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -404,12 +404,21 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "\n"; std::cerr << "++++++ preorder loops tree ++++++ \n"; + for (auto loop_tree: LI.preorder_loops_map) { + std::cerr << "loop tree root: (loop header: " << LI.loops[loop_tree.first]->header_block->id << ")\n"; + std::cerr << "preorder: "; + for (auto node: loop_tree.second) std::cerr << node << " "; + std::cerr << "\n"; + } + + std::cerr << "++++++ postorder loops tree ++++++ \n"; for (auto loop_tree: LI.postorder_loops_map) { std::cerr << "loop tree root: (loop header: " << LI.loops[loop_tree.first]->header_block->id << ")\n"; std::cerr << "postorder: "; for (auto node: loop_tree.second) std::cerr << node << " "; std::cerr << "\n"; } + std::cerr << "++++++ loop info ++++++ \n"; std::cerr << "++++++ convert to ast ++++++ \n"; @@ -518,7 +527,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_internal(std::vector ret_ast = ast; } catch (LoopBackException &e) { current_builder_context = nullptr; - + std::cerr << "goto in\n"; block::goto_stmt::Ptr goto_stmt = std::make_shared(); goto_stmt->static_offset.clear(); goto_stmt->temporary_label_number = e.static_offset; @@ -528,13 +537,23 @@ block::stmt::Ptr builder_context::extract_ast_from_function_internal(std::vector } catch (MemoizationException &e) { if (feature_unstructured) { // Instead of copying statements to the current block, we will just insert a goto + std::cerr << "goto memo\n"; block::goto_stmt::Ptr goto_stmt = std::make_shared(); goto_stmt->static_offset.clear(); goto_stmt->temporary_label_number = e.static_offset; add_stmt_to_current_block(goto_stmt, false); } else { + std::cerr << "goto memo\n"; for (unsigned int i = e.child_id; i < e.parent->stmts.size(); i++) { - add_stmt_to_current_block(e.parent->stmts[i], false); + if (isa(e.parent->stmts[i])) { + block::goto_stmt::Ptr goto_stmt = std::make_shared(); + goto_stmt->static_offset.clear(); + goto_stmt->temporary_label_number = to(e.parent->stmts[i])->temporary_label_number; + add_stmt_to_current_block(goto_stmt, false); + } + else { + add_stmt_to_current_block(e.parent->stmts[i], false); + } } } ret_ast = ast; From 02cb778d56ff143d9a66505d33eb8de6e02da920 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:23:07 +0530 Subject: [PATCH 11/24] V3: Added postdom, and other stuff --- include/blocks/basic_blocks.h | 13 +++ include/blocks/dominance.h | 6 +- include/blocks/loops.h | 5 +- src/blocks/basic_blocks.cpp | 10 +- src/blocks/dominance.cpp | 75 +++++++++++---- src/blocks/loops.cpp | 156 ++++++++++++++++++++++---------- src/builder/builder_context.cpp | 58 +++++++++++- 7 files changed, 252 insertions(+), 71 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index afe7055..37af06d 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -10,10 +10,23 @@ class basic_block { public: typedef std::vector> cfg_block; basic_block(std::string label): name(label) {}; + // only does a shallow copy (leaves out predecessors and successors) + // basic_block(basic_block &bb) { + // bb.branch_expr = branch_expr; + // bb.then_branch = then_branch; + // bb.else_branch = else_branch; + // bb.parent = parent; + // bb.ast_index = ast_index; + // bb.ast_depth = ast_depth; + // bb.id = id; + // bb.name = name; + // } cfg_block predecessor; cfg_block successor; block::expr::Ptr branch_expr; + std::shared_ptr then_branch; + std::shared_ptr else_branch; block::stmt::Ptr parent; unsigned int ast_index; unsigned int ast_depth; diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h index a569019..1850a25 100644 --- a/include/blocks/dominance.h +++ b/include/blocks/dominance.h @@ -17,8 +17,9 @@ class dominator_analysis { // int bb_id; // std::vector> child_nodes; // } dominator_tree; - dominator_analysis(basic_block::cfg_block &cfg); - basic_block::cfg_block &cfg_; + dominator_analysis(basic_block::cfg_block cfg, bool is_postdom = false); + basic_block::cfg_block cfg_; + bool is_postdom_; std::vector &get_postorder_bb_map(); std::vector &get_postorder(); std::vector &get_idom(); @@ -37,6 +38,7 @@ class dominator_analysis { std::vector postorder_idom; std::vector postorder; std::vector postorder_bb_map; + void reverse_cfg(); void postorder_idom_helper(std::vector &visited, int id); void postorder_dfs_helper(std::vector &visited_bbs, int id); void postorder_dfs(); diff --git a/include/blocks/loops.h b/include/blocks/loops.h index f909d3c..54f4ddf 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -28,13 +28,15 @@ class loop { std::unordered_set blocks_id_map; std::shared_ptr parent_loop; std::shared_ptr header_block; + std::shared_ptr unique_exit_block; basic_block::cfg_block loop_latch_blocks; + basic_block::cfg_block loop_exit_blocks; std::vector> subloops; }; class loop_info { public: - loop_info(basic_block::cfg_block ast, dominator_analysis &dt): parent_ast(ast), dta(dt) { + loop_info(basic_block::cfg_block ast, dominator_analysis &dt, dominator_analysis &post_dt): parent_ast(ast), dta(dt), post_dta(post_dt) { analyze(); } std::shared_ptr allocate_loop(std::shared_ptr header); @@ -47,6 +49,7 @@ class loop_info { private: basic_block::cfg_block parent_ast; dominator_analysis dta; + dominator_analysis post_dta; std::map> bb_loop_map; void postorder_dfs_helper(std::vector &postorder_loops_map, std::vector &visited_loops, int id); void preorder_dfs_helper(std::vector &preorder_loops_map, std::vector &visited_loops, int id); diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 76656a3..54880d2 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -110,6 +110,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { then_bb->successor.push_back(exit_bb); // set the successor of the original if_stmt block to be this then block bb->successor.push_back(then_bb); + // set the then branch ptr + bb->then_branch = then_bb; // push the block to the work_list, to expand it further work_list.push_front(then_bb); } @@ -126,13 +128,19 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { else_bb->successor.push_back(exit_bb); // set the successor of the orignal if_stmt block to be this else block bb->successor.push_back(else_bb); + // set the else branch ptr + bb->else_branch = else_bb; // push the block to the work_list, to expand it further work_list.insert(work_list.begin() + 1, else_bb); } - // if there is no else block, then have the exit block as successor as well. + // if there is no then/else block, then have the exit block as successor as well. if (bb->successor.size() <= 1) bb->successor.push_back(exit_bb); + // set the missing block as the exit block + if (!bb->then_branch) bb->then_branch = exit_bb; + else if (!bb->else_branch) bb->else_branch = exit_bb; + return_list.push_back(bb); } else if (isa(bb->parent)) { diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index 72726ad..4d73d2b 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -2,7 +2,38 @@ using namespace block; -dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) { +void dominator_analysis::reverse_cfg() { + // TODO: Add a check for size, it should be greater than 2. + if (cfg_.size() == 0) + assert(0); + + std::shared_ptr virtual_exit_bb = std::make_shared("virtualexit0"); + virtual_exit_bb->id = cfg_.size(); + cfg_.push_back(virtual_exit_bb); + + for (auto bb: cfg_) { + if (bb->successor.size() == 0) { + bb->successor.push_back(virtual_exit_bb); + virtual_exit_bb->predecessor.push_back(bb); + } + } + + for (auto bb: cfg_) { + basic_block::cfg_block temp_pred = bb->predecessor; + bb->predecessor.clear(); + bb->predecessor.insert(bb->predecessor.begin(), bb->successor.begin(), bb->successor.end()); + std::reverse(bb->predecessor.begin(), bb->predecessor.end()); + bb->successor.clear(); + bb->successor.insert(bb->successor.begin(), temp_pred.begin(), temp_pred.end()); + std::reverse(bb->successor.begin(), bb->successor.end()); + } +} + +dominator_analysis::dominator_analysis(basic_block::cfg_block cfg, bool is_postdom) : cfg_(cfg), is_postdom_(is_postdom) { + if (is_postdom) { + reverse_cfg(); + } + // TODO: Add a check for size, it should be greater than 2. idom.reserve(cfg_.size()); idom.assign(cfg_.size(), -1); @@ -16,7 +47,6 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block &cfg) : cfg_(cfg) void dominator_analysis::postorder_idom_helper(std::vector &visited, int id) { for (int idom_id: idom_map[id]) { - // std::cerr << idom_id << "\n"; if (idom_id != -1 && !visited[idom_id]) { visited[idom_id] = true; postorder_idom_helper(visited, idom_id); @@ -26,21 +56,31 @@ void dominator_analysis::postorder_idom_helper(std::vector &visited, int i } void dominator_analysis::postorder_dfs_helper(std::vector &visited_bbs, int id) { - for (auto child: cfg_[id]->successor) { - if (!visited_bbs[child->id]) { - visited_bbs[child->id] = true; - postorder_dfs_helper(visited_bbs, child->id); - postorder.push_back(child->id); + for (auto child: cfg_[id]->successor) { + if (!visited_bbs[child->id]) { + visited_bbs[child->id] = true; + postorder_dfs_helper(visited_bbs, child->id); + postorder.push_back(child->id); + } } - } } + void dominator_analysis::postorder_dfs() { std::vector visited_bbs(cfg_.size()); visited_bbs.assign(visited_bbs.size(), false); - visited_bbs[0] = true; - - postorder_dfs_helper(visited_bbs, 0); - postorder.push_back(0); + if (is_postdom_) + visited_bbs[cfg_.size() - 1] = true; + else + visited_bbs[0] = true; + + if (is_postdom_) { + postorder_dfs_helper(visited_bbs, cfg_.size() - 1); + postorder.push_back(cfg_.size() - 1); + } + else { + postorder_dfs_helper(visited_bbs, 0); + postorder.push_back(0); + } } std::vector &dominator_analysis::get_postorder_bb_map() { @@ -121,12 +161,16 @@ int dominator_analysis::intersect(int bb1_id, int bb2_id) { } void dominator_analysis::analyze() { - postorder_dfs(); + postorder_dfs(); for (unsigned int i = 0; i < postorder.size(); i++) { postorder_bb_map[postorder[i]] = i; } - idom[0] = 0; + if (is_postdom_) + idom[cfg_.size() - 1] = cfg_.size() - 1; + else + idom[0] = 0; + bool change = false; do { @@ -135,7 +179,7 @@ void dominator_analysis::analyze() { int postorder_bb_num = postorder[i]; std::shared_ptr bb = cfg_[postorder_bb_num]; int bb_id_idom = bb->predecessor[0]->id; - + for (unsigned int j = 1; j < bb->predecessor.size(); j++) { int bb_id_idom_next = bb->predecessor[j]->id; if (idom[bb_id_idom_next] != -1) { @@ -150,7 +194,6 @@ void dominator_analysis::analyze() { } } while(change); - // build a map of dominators for easy traversal. for (unsigned int i = 0; i < idom.size(); i++) { idom_map[idom[i]].push_back(i); diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index b77d824..d7d2252 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -150,6 +150,38 @@ void loop_info::analyze() { } } + // Populate the loop exits + for (auto loop: loops) { + if (!loop->header_block) + continue; + + for (auto bb: loop->blocks) { + for (auto children: bb->successor) { + if (!loop->blocks_id_map.count(children->id) && children->id != loop->header_block->id) { + loop->loop_exit_blocks.push_back(bb); + break; + } + } + } + } + + // Update unique loop exit using post dominators + for (auto loop: loops) { + if (loop->loop_exit_blocks.size() == 0) + continue; + + int unique_postdom = post_dta.get_idom(loop->loop_exit_blocks[0]->id); + bool unique_postdom_flag = true; + for (auto exit_bb: loop->loop_exit_blocks) { + if (post_dta.get_idom(exit_bb->id) != unique_postdom) { + unique_postdom_flag = false; + } + } + + if (unique_postdom_flag) + loop->unique_exit_block = dta.cfg_[unique_postdom]; + } + // Assign id to the loops for (unsigned int i = 0; i < loops.size(); i++) { loops[i]->loop_id = i; @@ -180,12 +212,12 @@ void loop_info::analyze() { } } -static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block::stmt_block::Ptr ast) { +static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast) { block::stmt::Ptr current_ast = to(ast); std::vector current_block = to(current_ast)->stmts; std::deque worklist; std::map ast_parent_map; - std::cerr << loop_header->name << "\n"; + // std::cerr << bb->name << "\n"; for (auto stmt: current_block) { ast_parent_map[stmt] = current_ast; @@ -198,30 +230,36 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: if (isa(worklist_top)) { stmt_block::Ptr wl_stmt_block = to(worklist_top); - for (auto stmt: wl_stmt_block->stmts) { - ast_parent_map[stmt] = worklist_top; + for (auto stmt_: wl_stmt_block->stmts) { + ast_parent_map[stmt_] = worklist_top; } worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end()); + + if (worklist_top == bb->parent) + return ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { if_stmt::Ptr wl_if_stmt = to(worklist_top); - std::cerr << "found if: "; + // std::cerr << "found if: "; if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { - std::cerr << "then\n"; + // std::cerr << "then\n"; stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); - for (auto stmt: wl_if_then_stmt->stmts) { - ast_parent_map[stmt] = worklist_top; + for (auto stmt_: wl_if_then_stmt->stmts) { + ast_parent_map[stmt_] = worklist_top; } worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); } if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { - std::cerr << "else\n"; + // std::cerr << "else\n"; stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); - for (auto stmt: wl_if_else_stmt->stmts) { - ast_parent_map[stmt] = worklist_top; + for (auto stmt_: wl_if_else_stmt->stmts) { + ast_parent_map[stmt_] = worklist_top; } worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); } + + if (worklist_top == bb->parent) + return ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); @@ -229,18 +267,18 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: ast_parent_map[stmt] = worklist_top; } worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); + + if (worklist_top == bb->parent) + return ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { - std::cerr << "found label\n"; - worklist_top->dump(std::cerr, 0); - label_stmt::Ptr wl_label_stmt = to(worklist_top); - if (worklist_top == loop_header->parent) + // std::cerr << "found label\n"; + if (worklist_top == bb->parent) return ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { - std::cerr << "found goto\n"; - goto_stmt::Ptr wl_goto_stmt = to(worklist_top); - if (worklist_top == loop_header->parent) + // std::cerr << "found goto\n"; + if (worklist_top == bb->parent) return ast_parent_map[worklist_top]; } } @@ -249,13 +287,39 @@ static stmt::Ptr get_loop_block(std::shared_ptr loop_header, block: return nullptr; } -// remove continue if last basic block +static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast) { + for (auto exit_bb: loop->loop_exit_blocks) { + if (!loop->unique_exit_block) + return; + + // exit_bb->parent->dump(std::cerr, 0); + int target_branch = -1; + + if (!isa(exit_bb->parent)) + assert(0); + + if (exit_bb->then_branch && !loop->blocks_id_map.count(exit_bb->then_branch->id)) + target_branch = 0; + else if (exit_bb->else_branch && !loop->blocks_id_map.count(exit_bb->else_branch->id)) + target_branch = 1; + + if (target_branch == -1) + assert(0); + + if (target_branch == 0) { + std::vector &temp_ast = to(to(exit_bb->parent)->then_stmt)->stmts; + temp_ast.push_back(std::make_shared()); + } + else if (target_branch == 1) { + std::vector &temp_ast = to(to(exit_bb->parent)->else_stmt)->stmts; + temp_ast.push_back(std::make_shared()); + } + } +} + static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast) { for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { - std::cerr << (*latch_iter)->ast_index << "\n"; - std::cerr << (*latch_iter)->parent.get() << "\n"; stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); - // loop_latch_ast->dump(std::cerr, 0); if (isa(loop_latch_ast)) { std::cerr << "stmt parent\n"; @@ -289,31 +353,30 @@ static void replace_loop_latches(std::shared_ptr loop, block::stmt_block:: std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); } } - - // loop_latch_ast->dump(std::cerr, 0); } } block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { - // std::cerr << "before ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "before ast\n"; + std::cerr << "before ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "before ast\n"; for (auto loop_map: preorder_loops_map) { for (auto preorder: loop_map.second) { + replace_loop_exits(loops[preorder], ast); replace_loop_latches(loops[preorder], ast); } } - - // std::cerr << "after ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "after ast\n"; + + std::cerr << "after ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "after ast\n"; for (auto loop_map: postorder_loops_map) { for (auto postorder: loop_map.second) { - std::cerr << "before ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "before ast\n"; + // std::cerr << "before ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "before ast\n"; block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); std::cerr << loops[postorder]->header_block->ast_index << "\n"; loop_header_ast->dump(std::cerr, 0); @@ -363,9 +426,9 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); } - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); } @@ -412,13 +475,12 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { while_block->cond = new_cond; } - for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); } - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); } @@ -463,9 +525,9 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); } - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); } @@ -498,9 +560,9 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } worklist.clear(); - std::cerr << "after ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "after ast\n"; + // std::cerr << "after ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "after ast\n"; } } diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 600f713..ddcc141 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -303,7 +303,11 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { block::eliminate_redundant_vars(ast); } + if (feature_unstructured) + return ast; + basic_block::cfg_block BBs = generate_basic_blocks(block::to(ast)); + basic_block::cfg_block post_BBs = generate_basic_blocks(block::to(ast)); std::cerr << "++++++ basic blocks ++++++ \n"; for (auto bb: BBs) { @@ -328,6 +332,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ dominance ++++++ \n"; dominator_analysis dom(BBs); + dominator_analysis post_dom(post_BBs, true); std::cerr << "== postorder map ==\n"; for (int i: dom.get_postorder_bb_map()) { @@ -374,10 +379,54 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "== postorder idom ==\n"; + std::cerr << "== (postdom) postorder map ==\n"; + for (int i: post_dom.get_postorder_bb_map()) { + std::cerr << i << "\n"; + } + std::cerr << "== (postdom) postorder map ==\n"; + + std::cerr << "== (postdom) postorder ==\n"; + for (int i: post_dom.get_postorder()) { + std::cerr << i << "\n"; + } + std::cerr << "== (postdom) postorder ==\n"; + + std::cerr << "== (postdom) idom ==\n"; + std::cerr << "get_idom(int) test: get_idom(0): " << post_dom.get_idom(0) << "\n"; + std::cerr << "get_idom(int) test: get_idom(-1): " << post_dom.get_idom(-1) << "\n"; + + for (int i: post_dom.get_idom()) { + std::cerr << i << "\n"; + } + std::cerr << "== (postdom) idom ==\n"; + + std::cerr << "== (postdom) idom map ==\n"; + std::cerr << "get_idom_map(int) test: get_idom_map(0): "; + for (int i : post_dom.get_idom_map(0)) std::cerr << i << " "; + std::cerr << "\n"; + + std::cerr << "get_idom_map(int) test: get_idom_map(-1): "; + for (int i : post_dom.get_idom_map(-1)) std::cerr << i << " "; + std::cerr << "\n"; + + for (auto children: post_dom.get_idom_map()) { + std::cerr << children.first << ": "; + for (int child: children.second) { + std::cerr << child << " "; + } + std::cerr << "\n"; + } + std::cerr << "== (postdom) idom map ==\n"; + + std::cerr << "== (postdom) postorder idom ==\n"; + for (auto idom: post_dom.get_postorder_idom_map()) { + std::cerr << idom << "\n"; + } + std::cerr << "== (postdom) postorder idom ==\n"; std::cerr << "++++++ dominance ++++++ \n"; std::cerr << "++++++ loop info ++++++ \n"; - loop_info LI(BBs, dom); + loop_info LI(BBs, dom, post_dom); int loop_num = 0; for (auto loop: LI.loops) { std::cerr << "++++++ loop " << loop_num++ << " ++++++ \n"; @@ -392,6 +441,10 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { for (auto bb: loop->loop_latch_blocks) std::cerr << bb->id << " "; std::cerr << "\n"; + std::cerr << "loop exits: "; + for (auto bb: loop->loop_exit_blocks) std::cerr << bb->id << " "; + std::cerr << "\n"; + std::cerr << "parent loop: (loop header: " << (loop->parent_loop ? (int)loop->parent_loop->header_block->id : -1) << ")\n"; std::cerr << "subloops: "; @@ -425,9 +478,6 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; - if (feature_unstructured) - return ast; - // block::loop_finder finder; // finder.ast = ast; // ast->accept(&finder); From 3a97de642889b14a8e16835636254e95b8b29f65 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Tue, 12 Sep 2023 23:57:18 +0530 Subject: [PATCH 12/24] WIP v3: got majority test cases working --- include/blocks/basic_blocks.h | 12 +- include/blocks/dominance.h | 6 + src/blocks/basic_blocks.cpp | 2 + src/blocks/dominance.cpp | 46 +++++- src/blocks/loops.cpp | 281 ++++++++++++++++++++++++++++---- src/builder/builder_context.cpp | 25 +++ 6 files changed, 326 insertions(+), 46 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 37af06d..5cc629e 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -10,23 +10,13 @@ class basic_block { public: typedef std::vector> cfg_block; basic_block(std::string label): name(label) {}; - // only does a shallow copy (leaves out predecessors and successors) - // basic_block(basic_block &bb) { - // bb.branch_expr = branch_expr; - // bb.then_branch = then_branch; - // bb.else_branch = else_branch; - // bb.parent = parent; - // bb.ast_index = ast_index; - // bb.ast_depth = ast_depth; - // bb.id = id; - // bb.name = name; - // } cfg_block predecessor; cfg_block successor; block::expr::Ptr branch_expr; std::shared_ptr then_branch; std::shared_ptr else_branch; + bool is_exit_block; block::stmt::Ptr parent; unsigned int ast_index; unsigned int ast_depth; diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h index 1850a25..9dfa598 100644 --- a/include/blocks/dominance.h +++ b/include/blocks/dominance.h @@ -22,6 +22,8 @@ class dominator_analysis { bool is_postdom_; std::vector &get_postorder_bb_map(); std::vector &get_postorder(); + std::vector &get_preorder_bb_map(); + std::vector &get_preorder(); std::vector &get_idom(); std::map> &get_idom_map(); std::vector &get_postorder_idom_map(); @@ -38,10 +40,14 @@ class dominator_analysis { std::vector postorder_idom; std::vector postorder; std::vector postorder_bb_map; + std::vector preorder; + std::vector preorder_bb_map; void reverse_cfg(); void postorder_idom_helper(std::vector &visited, int id); void postorder_dfs_helper(std::vector &visited_bbs, int id); void postorder_dfs(); + void preorder_dfs_helper(std::vector &visited_bbs, int id); + void preorder_dfs(); int intersect(int bb1_id, int bb2_id); }; diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 54880d2..b9755c9 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -81,6 +81,8 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto exit_bb = std::make_shared("exit" + std::to_string(basic_block_count)); // assign it a empty stmt_block as parent exit_bb->parent = std::make_shared(); + // mark the basic block as exit block + exit_bb->is_exit_block = true; // add mapping in ast to bb map // exit_bb->ast_to_basic_block_map[exit_bb->parent] = exit_bb; // set the ast depth of the basic block diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index 4d73d2b..234767c 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -40,6 +40,9 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block cfg, bool is_postd postorder.reserve(cfg_.size()); postorder_bb_map.reserve(cfg_.size()); postorder_bb_map.assign(cfg_.size(), -1); + preorder.reserve(cfg_.size()); + preorder_bb_map.reserve(cfg_.size()); + preorder_bb_map.assign(cfg_.size(), -1); // and call the anaylse function analyze(); @@ -83,6 +86,34 @@ void dominator_analysis::postorder_dfs() { } } +void dominator_analysis::preorder_dfs_helper(std::vector &visited_bbs, int id) { + for (auto child: cfg_[id]->successor) { + if (!visited_bbs[child->id]) { + visited_bbs[child->id] = true; + preorder.push_back(child->id); + preorder_dfs_helper(visited_bbs, child->id); + } + } +} + +void dominator_analysis::preorder_dfs() { + std::vector visited_bbs(cfg_.size()); + visited_bbs.assign(visited_bbs.size(), false); + if (is_postdom_) + visited_bbs[cfg_.size() - 1] = true; + else + visited_bbs[0] = true; + + if (is_postdom_) { + preorder.push_back(cfg_.size() - 1); + preorder_dfs_helper(visited_bbs, cfg_.size() - 1); + } + else { + preorder.push_back(0); + preorder_dfs_helper(visited_bbs, 0); + } +} + std::vector &dominator_analysis::get_postorder_bb_map() { return postorder_bb_map; } @@ -91,6 +122,14 @@ std::vector &dominator_analysis::get_postorder() { return postorder; } +std::vector &dominator_analysis::get_preorder_bb_map() { + return preorder_bb_map; +} + +std::vector &dominator_analysis::get_preorder() { + return preorder; +} + std::vector &dominator_analysis::get_idom() { return idom; } @@ -161,11 +200,14 @@ int dominator_analysis::intersect(int bb1_id, int bb2_id) { } void dominator_analysis::analyze() { - postorder_dfs(); + preorder_dfs(); + postorder_dfs(); + for (unsigned int i = 0; i < preorder.size(); i++) { + preorder_bb_map[preorder[i]] = i; + } for (unsigned int i = 0; i < postorder.size(); i++) { postorder_bb_map[postorder[i]] = i; } - if (is_postdom_) idom[cfg_.size() - 1] = cfg_.size() - 1; else diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index d7d2252..7e5a0b4 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -212,7 +212,7 @@ void loop_info::analyze() { } } -static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast) { +static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast, bool one_level_up = false) { block::stmt::Ptr current_ast = to(ast); std::vector current_block = to(current_ast)->stmts; std::deque worklist; @@ -259,7 +259,7 @@ static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_blo } if (worklist_top == bb->parent) - return ast_parent_map[worklist_top]; + return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); @@ -269,17 +269,21 @@ static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_blo worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); if (worklist_top == bb->parent) - return ast_parent_map[worklist_top]; + return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { // std::cerr << "found label\n"; if (worklist_top == bb->parent) - return ast_parent_map[worklist_top]; + return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; } else if (isa(worklist_top)) { // std::cerr << "found goto\n"; if (worklist_top == bb->parent) - return ast_parent_map[worklist_top]; + return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + } + else if (isa(worklist_top)) { + if (worklist_top == bb->parent) + return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; } } @@ -287,12 +291,11 @@ static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_blo return nullptr; } -static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast) { +static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { for (auto exit_bb: loop->loop_exit_blocks) { if (!loop->unique_exit_block) return; - // exit_bb->parent->dump(std::cerr, 0); int target_branch = -1; if (!isa(exit_bb->parent)) @@ -308,26 +311,125 @@ static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Pt if (target_branch == 0) { std::vector &temp_ast = to(to(exit_bb->parent)->then_stmt)->stmts; - temp_ast.push_back(std::make_shared()); + + if (exit_bb->then_branch == loop->unique_exit_block) { + temp_ast.push_back(std::make_shared()); + } + else { + std::shared_ptr exiting_bb = exit_bb->then_branch; + std::cerr << exiting_bb->id << "\n"; + // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) + // exiting_bb = exit_bb->then_branch->successor[0]; + unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; + while(exiting_bb->is_exit_block) { + std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; + if (temp_exiting_bb->id == loop->unique_exit_block->id) + break; + exiting_bb = temp_exiting_bb; + } + std::cerr << exiting_bb->id << "\n"; + + stmt::Ptr loop_exit_ast; + if (exiting_bb->is_exit_block) + loop_exit_ast = exit_bb->parent; + else + loop_exit_ast = get_loop_block(exiting_bb, ast); + + if (isa(loop_exit_ast)) { + to(loop_exit_ast)->stmts.push_back(std::make_shared()); + } + else if (isa(loop_exit_ast)) { + stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); + // stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); + + // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) + if_then_block->stmts.push_back(std::make_shared()); + // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) + // if_else_block->stmts.push_back(std::make_shared()); + } + } } else if (target_branch == 1) { std::vector &temp_ast = to(to(exit_bb->parent)->else_stmt)->stmts; - temp_ast.push_back(std::make_shared()); + + if (exit_bb->else_branch == loop->unique_exit_block) { + temp_ast.push_back(std::make_shared()); + } + else { + std::shared_ptr exiting_bb = exit_bb->else_branch; + std::cerr << exiting_bb->id << "\n"; + // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) + // exiting_bb = exit_bb->else_branch->successor[0]; + unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; + while(exiting_bb->is_exit_block) { + std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; + if (temp_exiting_bb->id == loop->unique_exit_block->id) + break; + exiting_bb = temp_exiting_bb; + } + std::cerr << exiting_bb->id << "\n"; + + stmt::Ptr loop_exit_ast; + if (exiting_bb->is_exit_block) + loop_exit_ast = exit_bb->parent; + else + loop_exit_ast = get_loop_block(exiting_bb, ast); + + if (isa(loop_exit_ast)) { + to(loop_exit_ast)->stmts.push_back(std::make_shared()); + } + else if (isa(loop_exit_ast)) { + // stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); + stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); + + // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) + // if_then_block->stmts.push_back(std::make_shared()); + // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) + if_else_block->stmts.push_back(std::make_shared()); + } + } } } } -static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast) { +static std::vector backedge_blocks; + +static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); + // stmt::Ptr loop_latch_ast_level_up = get_loop_block(*latch_iter, ast, true); + bool is_last_block = false; + if (dta_.get_preorder_bb_map()[(*latch_iter)->id] == (int)dta_.get_preorder().size() - 1) { + is_last_block = true; + } + else { + unsigned int next_preorder = dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1]; + unsigned int next_next_preorder = dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1]; + + std::cerr << next_preorder << " : " << next_next_preorder << "\n"; + if (loop->blocks_id_map.count(next_preorder)) + is_last_block = false; + else { + if (loop->unique_exit_block && (next_preorder == loop->unique_exit_block->id)) + is_last_block = true; + else if (loop->unique_exit_block && (next_next_preorder == loop->unique_exit_block->id)) + is_last_block = true; + else + is_last_block = false; + } + } + + std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << "\n"; if (isa(loop_latch_ast)) { std::cerr << "stmt parent\n"; std::vector &temp_ast = to(loop_latch_ast)->stmts; - if (latch_iter == loop->loop_latch_blocks.end() - 1) + if (is_last_block) temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); - else + else { + backedge_blocks.push_back(to(loop_latch_ast)); std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], to(std::make_shared())); + } } else if (isa(loop_latch_ast)) { stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); @@ -338,19 +440,23 @@ static void replace_loop_latches(std::shared_ptr loop, block::stmt_block:: if (if_then_block->stmts.size() && if_then_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { std::cerr << "then\n"; std::vector &temp_ast = if_then_block->stmts; - if (latch_iter == loop->loop_latch_blocks.end() - 1) + if (is_last_block) temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); - else + else { + backedge_blocks.push_back(if_then_block); std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); + } } if (if_else_block->stmts.size() && if_else_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { std::cerr << "else\n"; std::vector &temp_ast = if_else_block->stmts; - if (latch_iter == loop->loop_latch_blocks.end() - 1) + if (is_last_block) temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); - else + else { + backedge_blocks.push_back(if_else_block); std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); + } } } } @@ -363,25 +469,26 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto loop_map: preorder_loops_map) { for (auto preorder: loop_map.second) { - replace_loop_exits(loops[preorder], ast); - replace_loop_latches(loops[preorder], ast); + replace_loop_exits(loops[preorder], ast, dta); + replace_loop_latches(loops[preorder], ast, dta); } } - + std::cerr << "after ast\n"; ast->dump(std::cerr, 0); std::cerr << "after ast\n"; for (auto loop_map: postorder_loops_map) { for (auto postorder: loop_map.second) { - // std::cerr << "before ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "before ast\n"; + std::cerr << "before ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "before ast\n"; block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); std::cerr << loops[postorder]->header_block->ast_index << "\n"; loop_header_ast->dump(std::cerr, 0); while_stmt::Ptr while_block = std::make_shared(); while_block->body = std::make_shared(); + // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); if (isa(loop_header_ast)) { loop_header_ast = to(loop_header_ast)->body; @@ -421,10 +528,46 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; while_block->cond = new_cond; + + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + } + else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } + else { + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } // for (auto body_stmt: else_block->stmts) { // to(while_block->body)->stmts.push_back(body_stmt); @@ -473,10 +616,46 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; while_block->cond = new_cond; - } - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + } + else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + } + else { + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } // for (auto body_stmt: else_block->stmts) { // to(while_block->body)->stmts.push_back(body_stmt); @@ -520,10 +699,46 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; while_block->cond = new_cond; - } - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + } + else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + not_expr::Ptr new_cond = std::make_shared(); + new_cond->static_offset = while_block->cond->static_offset; + new_cond->expr1 = while_block->cond; + while_block->cond = new_cond; + + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + } + else { + for (auto body_stmt: then_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + if (backedge_iter != backedge_blocks.end()) { + std::cerr << "replaced BE\n"; + std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + } + while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } // for (auto body_stmt: else_block->stmts) { // to(while_block->body)->stmts.push_back(body_stmt); @@ -560,9 +775,9 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } worklist.clear(); - // std::cerr << "after ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "after ast\n"; + std::cerr << "after ast\n"; + ast->dump(std::cerr, 0); + std::cerr << "after ast\n"; } } diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index ddcc141..bd66e76 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -346,6 +346,18 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "== postorder ==\n"; + std::cerr << "== preorder map ==\n"; + for (int i: dom.get_preorder_bb_map()) { + std::cerr << i << "\n"; + } + std::cerr << "== preorder map ==\n"; + + std::cerr << "== preorder ==\n"; + for (int i: dom.get_preorder()) { + std::cerr << i << "\n"; + } + std::cerr << "== preorder ==\n"; + std::cerr << "== idom ==\n"; std::cerr << "get_idom(int) test: get_idom(0): " << dom.get_idom(0) << "\n"; std::cerr << "get_idom(int) test: get_idom(-1): " << dom.get_idom(-1) << "\n"; @@ -391,6 +403,18 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "== (postdom) postorder ==\n"; + std::cerr << "== (postdom) preorder map ==\n"; + for (int i: dom.get_preorder_bb_map()) { + std::cerr << i << "\n"; + } + std::cerr << "== (postdom) preorder map ==\n"; + + std::cerr << "== (postdom) preorder ==\n"; + for (int i: dom.get_preorder()) { + std::cerr << i << "\n"; + } + std::cerr << "== (postdom) preorder ==\n"; + std::cerr << "== (postdom) idom ==\n"; std::cerr << "get_idom(int) test: get_idom(0): " << post_dom.get_idom(0) << "\n"; std::cerr << "get_idom(int) test: get_idom(-1): " << post_dom.get_idom(-1) << "\n"; @@ -444,6 +468,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "loop exits: "; for (auto bb: loop->loop_exit_blocks) std::cerr << bb->id << " "; std::cerr << "\n"; + if (loop->unique_exit_block) std::cerr << "loop unique exit block: " << loop->unique_exit_block->id << "\n"; std::cerr << "parent loop: (loop header: " << (loop->parent_loop ? (int)loop->parent_loop->header_block->id : -1) << ")\n"; From ecd353a74560fbbf9e0a87f837cfb8a045314c8d Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Wed, 13 Sep 2023 20:31:03 +0530 Subject: [PATCH 13/24] WIP v4: got the insert loop latches/exits correctly and added while loop simplifications --- include/blocks/basic_blocks.h | 2 +- src/blocks/basic_blocks.cpp | 15 +++-- src/blocks/loops.cpp | 106 +++++++++++++++++++++++++--------- 3 files changed, 86 insertions(+), 37 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 5cc629e..a3983c8 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -22,7 +22,7 @@ class basic_block { unsigned int ast_depth; unsigned int id; std::string name; - // static std::map> ast_to_basic_block_map; + static std::map> ast_to_basic_block_map; }; basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast); diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index b9755c9..b9a058c 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -3,6 +3,8 @@ using namespace block; +std::map> basic_block::ast_to_basic_block_map = {}; + basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { std::deque> work_list; basic_block::cfg_block return_list; @@ -13,7 +15,6 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { for (auto st: ast->stmts) { auto bb = std::make_shared(std::to_string(basic_block_count)); bb->parent = st; - // bb->ast_to_basic_block_map[bb->parent] = bb; bb->ast_index = ast_index_counter++; bb->ast_depth = 0; work_list.push_back(bb); @@ -41,7 +42,6 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { for (auto st: stmt_block_->stmts) { stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); stmt_block_list.back()->parent = st; - // stmt_block_list.back()->ast_to_basic_block_map[bb->parent] = stmt_block_list.back(); stmt_block_list.back()->ast_index = ast_index_counter++; stmt_block_list.back()->ast_depth = bb->ast_depth + 1; } @@ -83,8 +83,6 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { exit_bb->parent = std::make_shared(); // mark the basic block as exit block exit_bb->is_exit_block = true; - // add mapping in ast to bb map - // exit_bb->ast_to_basic_block_map[exit_bb->parent] = exit_bb; // set the ast depth of the basic block exit_bb->ast_depth = bb->ast_depth; // check if this is the last block, if yes the successor will be empty @@ -104,8 +102,6 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto then_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the then stmts then_bb->parent = if_stmt_->then_stmt; - // add mapping in ast to bb map - // then_bb->ast_to_basic_block_map[then_bb->parent] = then_bb; // set the ast depth of the basic block then_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block @@ -122,8 +118,6 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { auto else_bb = std::make_shared(std::to_string(++basic_block_count)); // set the parent of this block as the else stmts else_bb->parent = if_stmt_->else_stmt; - // add mapping in ast to bb map - // else_bb->ast_to_basic_block_map[else_bb->parent] = else_bb; // set the ast depth of the basic block else_bb->ast_depth = bb->ast_depth; // set the successor of this block to be the exit block @@ -203,5 +197,10 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { return_list[i]->id = i; } + // step 7: populate the ast -> bb map + for (auto bb: return_list) { + bb->ast_to_basic_block_map[bb->parent] = bb; + } + return return_list; } \ No newline at end of file diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 7e5a0b4..7b2cde3 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -395,32 +395,49 @@ static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Pt static std::vector backedge_blocks; static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { + std::cerr << "loop id: " << loop->loop_id << " : "; for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { + std::cerr << "loop latch id: " << (*latch_iter)->id << "\n"; stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); // stmt::Ptr loop_latch_ast_level_up = get_loop_block(*latch_iter, ast, true); bool is_last_block = false; + bool is_latch_in_other_loop = false; if (dta_.get_preorder_bb_map()[(*latch_iter)->id] == (int)dta_.get_preorder().size() - 1) { is_last_block = true; } else { - unsigned int next_preorder = dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1]; - unsigned int next_next_preorder = dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1]; + int next_preorder = dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1] : -1; + int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; std::cerr << next_preorder << " : " << next_next_preorder << "\n"; if (loop->blocks_id_map.count(next_preorder)) is_last_block = false; else { - if (loop->unique_exit_block && (next_preorder == loop->unique_exit_block->id)) + if (loop->unique_exit_block && (next_preorder == (int)loop->unique_exit_block->id)) is_last_block = true; - else if (loop->unique_exit_block && (next_next_preorder == loop->unique_exit_block->id)) + else if (loop->unique_exit_block && (next_next_preorder == (int)loop->unique_exit_block->id)) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) is_last_block = true; else is_last_block = false; } } + std::cerr << "==== ast ====\n"; + loop_latch_ast->dump(std::cerr, 0); + if ((*latch_iter)->ast_to_basic_block_map.count(loop_latch_ast)) { + std::cerr << "break in latch: " << (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; + auto bb = (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast); + for (auto subloop: loop->subloops) { + if (subloop->blocks_id_map.count(bb->id)) + is_latch_in_other_loop = true; + } + } - std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << "\n"; + std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << ": " << is_latch_in_other_loop << "\n"; if (isa(loop_latch_ast)) { std::cerr << "stmt parent\n"; std::vector &temp_ast = to(loop_latch_ast)->stmts; @@ -428,7 +445,7 @@ static void replace_loop_latches(std::shared_ptr loop, block::stmt_block:: temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); else { backedge_blocks.push_back(to(loop_latch_ast)); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], to(std::make_shared())); + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); } } else if (isa(loop_latch_ast)) { @@ -444,7 +461,7 @@ static void replace_loop_latches(std::shared_ptr loop, block::stmt_block:: temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); else { backedge_blocks.push_back(if_then_block); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); } } @@ -455,7 +472,7 @@ static void replace_loop_latches(std::shared_ptr loop, block::stmt_block:: temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); else { backedge_blocks.push_back(if_else_block); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], to(std::make_shared())); + std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); } } } @@ -478,6 +495,7 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { ast->dump(std::cerr, 0); std::cerr << "after ast\n"; + // return ast; for (auto loop_map: postorder_loops_map) { for (auto postorder: loop_map.second) { std::cerr << "before ast\n"; @@ -488,7 +506,6 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { loop_header_ast->dump(std::cerr, 0); while_stmt::Ptr while_block = std::make_shared(); while_block->body = std::make_shared(); - // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); if (isa(loop_header_ast)) { loop_header_ast = to(loop_header_ast)->body; @@ -540,15 +557,21 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } - else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { not_expr::Ptr new_cond = std::make_shared(); new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; while_block->cond = new_cond; - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } + // if (else_block->stmts.size() != 0) + for (auto body_stmt: else_block->stmts) { + to(while_block->body)->stmts.push_back(body_stmt); + } + // else { + then_block->stmts.pop_back(); + for (auto stmt: then_block->stmts) + to(loop_header_ast)->stmts.push_back(stmt); + // } auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); if (backedge_iter != backedge_blocks.end()) { @@ -557,6 +580,16 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } + // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // then_block->stmts.pop_back(); + // for (auto stmt: then_block->stmts) + // to(loop_header_ast)->stmts.push_back(stmt); + // } else { for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); @@ -575,9 +608,6 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); } - else { - // std::cerr << "not found loop header in stmt block\n"; - } } else if (isa(loop_header_ast)) { unsigned int ast_index = loops[postorder]->header_block->ast_index; @@ -628,7 +658,7 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } - else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { not_expr::Ptr new_cond = std::make_shared(); new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; @@ -638,6 +668,10 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { to(while_block->body)->stmts.push_back(body_stmt); } + then_block->stmts.pop_back(); + for (auto stmt: then_block->stmts) + if_then_block->stmts.push_back(stmt); + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); if (backedge_iter != backedge_blocks.end()) { std::cerr << "replaced BE\n"; @@ -645,6 +679,16 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } + // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // then_block->stmts.pop_back(); + // for (auto stmt: then_block->stmts) + // if_then_block->stmts.push_back(stmt); + // } else { for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); @@ -663,11 +707,9 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); } - else { - // std::cerr << "not found loop header in if-then stmt\n"; - } } - else if (if_else_block->stmts.size() != 0) { + + if (if_else_block->stmts.size() != 0) { std::cerr << "if else block\n"; // handle unconditional loops if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_else_block->stmts[ast_index + 1])) { @@ -711,7 +753,7 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } - else if (then_block->stmts.size() == 1 && else_block->stmts.size() != 0 && isa(then_block->stmts[0])) { + else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { not_expr::Ptr new_cond = std::make_shared(); new_cond->static_offset = while_block->cond->static_offset; new_cond->expr1 = while_block->cond; @@ -721,6 +763,10 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { to(while_block->body)->stmts.push_back(body_stmt); } + then_block->stmts.pop_back(); + for (auto stmt: then_block->stmts) + if_else_block->stmts.push_back(stmt); + auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); if (backedge_iter != backedge_blocks.end()) { std::cerr << "replaced BE\n"; @@ -728,6 +774,16 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); } + // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // then_block->stmts.pop_back(); + // for (auto stmt: then_block->stmts) + // if_else_block->stmts.push_back(stmt); + // } else { for (auto body_stmt: then_block->stmts) { to(while_block->body)->stmts.push_back(body_stmt); @@ -746,14 +802,8 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { // if block to be replaced with while block worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); } - else { - // std::cerr << "not found loop header in if-else stmt\n"; - } } } - else { - // std::cerr << "loop header not found\n"; - } // process worklist std::sort(worklist.begin(), worklist.end(), [](std::tuple>, stmt::Ptr> a, std::tuple>, stmt::Ptr> b) { From 4a1613b9cb0f3f3d9fd8cd7e8df1513d6bc0433a Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 24 Sep 2023 02:37:09 +0530 Subject: [PATCH 14/24] WIP v1: Implement a recursive convert_to_ast implementation (works better with lesser LOC) --- include/blocks/basic_blocks.h | 1 + include/blocks/loops.h | 3 +- src/blocks/basic_blocks.cpp | 3 + src/blocks/loops.cpp | 1388 ++++++++++++++++++------------- src/builder/builder_context.cpp | 6 +- 5 files changed, 824 insertions(+), 577 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index a3983c8..1eb25ee 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -16,6 +16,7 @@ class basic_block { block::expr::Ptr branch_expr; std::shared_ptr then_branch; std::shared_ptr else_branch; + std::shared_ptr exit_block; bool is_exit_block; block::stmt::Ptr parent; unsigned int ast_index; diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 54f4ddf..c65ad51 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -10,8 +10,8 @@ using namespace block; class loop { public: loop(std::shared_ptr header): header_block(header) {} + stmt::Ptr convert_to_ast_impl(dominator_analysis &dta_); -// private: struct loop_bounds_ { stmt::Ptr ind_var; // MISS: intial value of ind var @@ -28,6 +28,7 @@ class loop { std::unordered_set blocks_id_map; std::shared_ptr parent_loop; std::shared_ptr header_block; + std::shared_ptr condition_block; std::shared_ptr unique_exit_block; basic_block::cfg_block loop_latch_blocks; basic_block::cfg_block loop_exit_blocks; diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index b9a058c..66f863f 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -137,6 +137,9 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { if (!bb->then_branch) bb->then_branch = exit_bb; else if (!bb->else_branch) bb->else_branch = exit_bb; + // set the exit block of this if stmt + bb->exit_block = exit_bb; + return_list.push_back(bb); } else if (isa(bb->parent)) { diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 7b2cde3..c28664e 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -1,6 +1,7 @@ #include "blocks/loops.h" #include #include +#include static std::vector>, stmt::Ptr>> worklist; @@ -150,6 +151,17 @@ void loop_info::analyze() { } } + // Populate loop condition block + for(auto loop: loops) { + if (!loop->header_block) + continue; + + std::shared_ptr header = loop->header_block; + assert(header->successor.size() == 1 && "loop header cannot have more than one successor"); + if (isa(header->successor[0]->parent)) + loop->condition_block = header->successor[0]; + } + // Populate the loop exits for (auto loop: loops) { if (!loop->header_block) @@ -212,624 +224,856 @@ void loop_info::analyze() { } } -static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast, bool one_level_up = false) { - block::stmt::Ptr current_ast = to(ast); - std::vector current_block = to(current_ast)->stmts; - std::deque worklist; - std::map ast_parent_map; - // std::cerr << bb->name << "\n"; - - for (auto stmt: current_block) { - ast_parent_map[stmt] = current_ast; - } - worklist.insert(worklist.end(), current_block.begin(), current_block.end()); - - while (worklist.size()) { - stmt::Ptr worklist_top = worklist.front(); - worklist.pop_front(); +// static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast, bool one_level_up = false) { +// block::stmt::Ptr current_ast = to(ast); +// std::vector current_block = to(current_ast)->stmts; +// std::deque worklist; +// std::map ast_parent_map; +// // std::cerr << bb->name << "\n"; + +// for (auto stmt: current_block) { +// ast_parent_map[stmt] = current_ast; +// } +// worklist.insert(worklist.end(), current_block.begin(), current_block.end()); + +// while (worklist.size()) { +// stmt::Ptr worklist_top = worklist.front(); +// worklist.pop_front(); + +// if (isa(worklist_top)) { +// stmt_block::Ptr wl_stmt_block = to(worklist_top); +// for (auto stmt_: wl_stmt_block->stmts) { +// ast_parent_map[stmt_] = worklist_top; +// } +// worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end()); + +// if (worklist_top == bb->parent) +// return ast_parent_map[worklist_top]; +// } +// else if (isa(worklist_top)) { +// if_stmt::Ptr wl_if_stmt = to(worklist_top); +// // std::cerr << "found if: "; +// if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { +// // std::cerr << "then\n"; +// stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); +// for (auto stmt_: wl_if_then_stmt->stmts) { +// ast_parent_map[stmt_] = worklist_top; +// } +// worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); +// } +// if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { +// // std::cerr << "else\n"; +// stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); +// for (auto stmt_: wl_if_else_stmt->stmts) { +// ast_parent_map[stmt_] = worklist_top; +// } +// worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); +// } + +// if (worklist_top == bb->parent) +// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; +// } +// else if (isa(worklist_top)) { +// stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); +// for (auto stmt: wl_while_body_block->stmts) { +// ast_parent_map[stmt] = worklist_top; +// } +// worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); + +// if (worklist_top == bb->parent) +// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; +// } +// else if (isa(worklist_top)) { +// // std::cerr << "found label\n"; +// if (worklist_top == bb->parent) +// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; +// } +// else if (isa(worklist_top)) { +// // std::cerr << "found goto\n"; +// if (worklist_top == bb->parent) +// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; +// } +// else if (isa(worklist_top)) { +// if (worklist_top == bb->parent) +// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; +// } +// } + +// std::cerr << "Returned nullptr !\n"; +// return nullptr; +// } + +// static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { +// for (auto exit_bb: loop->loop_exit_blocks) { +// if (!loop->unique_exit_block) +// return; + +// int target_branch = -1; + +// if (!isa(exit_bb->parent)) +// assert(0); + +// if (exit_bb->then_branch && !loop->blocks_id_map.count(exit_bb->then_branch->id)) +// target_branch = 0; +// else if (exit_bb->else_branch && !loop->blocks_id_map.count(exit_bb->else_branch->id)) +// target_branch = 1; + +// if (target_branch == -1) +// assert(0); + +// if (target_branch == 0) { +// std::vector &temp_ast = to(to(exit_bb->parent)->then_stmt)->stmts; + +// if (exit_bb->then_branch == loop->unique_exit_block) { +// temp_ast.push_back(std::make_shared()); +// } +// else { +// std::shared_ptr exiting_bb = exit_bb->then_branch; +// std::cerr << exiting_bb->id << "\n"; +// // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) +// // exiting_bb = exit_bb->then_branch->successor[0]; +// unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; +// while(exiting_bb->is_exit_block) { +// std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; +// if (temp_exiting_bb->id == loop->unique_exit_block->id) +// break; +// exiting_bb = temp_exiting_bb; +// } +// std::cerr << exiting_bb->id << "\n"; + +// stmt::Ptr loop_exit_ast; +// if (exiting_bb->is_exit_block) +// loop_exit_ast = exit_bb->parent; +// else +// loop_exit_ast = get_loop_block(exiting_bb, ast); + +// if (isa(loop_exit_ast)) { +// to(loop_exit_ast)->stmts.push_back(std::make_shared()); +// } +// else if (isa(loop_exit_ast)) { +// stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); +// // stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); + +// // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) +// if_then_block->stmts.push_back(std::make_shared()); +// // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) +// // if_else_block->stmts.push_back(std::make_shared()); +// } +// } +// } +// else if (target_branch == 1) { +// std::vector &temp_ast = to(to(exit_bb->parent)->else_stmt)->stmts; + +// if (exit_bb->else_branch == loop->unique_exit_block) { +// temp_ast.push_back(std::make_shared()); +// } +// else { +// std::shared_ptr exiting_bb = exit_bb->else_branch; +// std::cerr << exiting_bb->id << "\n"; +// // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) +// // exiting_bb = exit_bb->else_branch->successor[0]; +// unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; +// while(exiting_bb->is_exit_block) { +// std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; +// if (temp_exiting_bb->id == loop->unique_exit_block->id) +// break; +// exiting_bb = temp_exiting_bb; +// } +// std::cerr << exiting_bb->id << "\n"; + +// stmt::Ptr loop_exit_ast; +// if (exiting_bb->is_exit_block) +// loop_exit_ast = exit_bb->parent; +// else +// loop_exit_ast = get_loop_block(exiting_bb, ast); + +// if (isa(loop_exit_ast)) { +// to(loop_exit_ast)->stmts.push_back(std::make_shared()); +// } +// else if (isa(loop_exit_ast)) { +// // stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); +// stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); + +// // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) +// // if_then_block->stmts.push_back(std::make_shared()); +// // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) +// if_else_block->stmts.push_back(std::make_shared()); +// } +// } +// } +// } +// } + +// static std::vector backedge_blocks; + +// static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { +// std::cerr << "loop id: " << loop->loop_id << " : "; +// for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { +// std::cerr << "loop latch id: " << (*latch_iter)->id << "\n"; +// stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); +// // stmt::Ptr loop_latch_ast_level_up = get_loop_block(*latch_iter, ast, true); +// bool is_last_block = false; +// bool is_latch_in_other_loop = false; + +// if (dta_.get_preorder_bb_map()[(*latch_iter)->id] == (int)dta_.get_preorder().size() - 1) { +// is_last_block = true; +// } +// else { +// int next_preorder = dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1] : -1; +// int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; + +// std::cerr << next_preorder << " : " << next_next_preorder << "\n"; +// if (loop->blocks_id_map.count(next_preorder)) +// is_last_block = false; +// else { +// if (loop->unique_exit_block && (next_preorder == (int)loop->unique_exit_block->id)) +// is_last_block = true; +// else if (loop->unique_exit_block && (next_next_preorder == (int)loop->unique_exit_block->id)) +// is_last_block = true; +// else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) +// is_last_block = true; +// else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) +// is_last_block = true; +// else +// is_last_block = false; +// } +// } +// std::cerr << "==== ast ====\n"; +// loop_latch_ast->dump(std::cerr, 0); +// if ((*latch_iter)->ast_to_basic_block_map.count(loop_latch_ast)) { +// std::cerr << "break in latch: " << (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; +// auto bb = (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast); +// for (auto subloop: loop->subloops) { +// if (subloop->blocks_id_map.count(bb->id)) +// is_latch_in_other_loop = true; +// } +// } + +// std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << ": " << is_latch_in_other_loop << "\n"; +// if (isa(loop_latch_ast)) { +// std::cerr << "stmt parent\n"; +// std::vector &temp_ast = to(loop_latch_ast)->stmts; +// if (is_last_block) +// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); +// else { +// backedge_blocks.push_back(to(loop_latch_ast)); +// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); +// } +// } +// else if (isa(loop_latch_ast)) { +// stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); +// stmt_block::Ptr if_else_block = to(to(loop_latch_ast)->else_stmt); + +// std::cerr << "if parent: "; +// std::cerr << if_then_block->stmts.size() << " " << if_else_block->stmts.size() << " " << (*latch_iter)->ast_index << " "; +// if (if_then_block->stmts.size() && if_then_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { +// std::cerr << "then\n"; +// std::vector &temp_ast = if_then_block->stmts; +// if (is_last_block) +// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); +// else { +// backedge_blocks.push_back(if_then_block); +// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); +// } +// } + +// if (if_else_block->stmts.size() && if_else_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { +// std::cerr << "else\n"; +// std::vector &temp_ast = if_else_block->stmts; +// if (is_last_block) +// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); +// else { +// backedge_blocks.push_back(if_else_block); +// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); +// } +// } +// } +// } +// } +std::set visited_blocks; +std::map> ast_parent_map; +stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_) { + while_stmt::Ptr while_block = std::make_shared(); + while_block->body = std::make_shared(); + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + + std::cerr << "loop: " << loop_id << " " << header_block->id << "\n"; + if_stmt::Ptr if_stmt_; + for (auto bb: blocks) { + std::cerr << "block: " << bb->id << "\n"; + + if (visited_blocks.count(bb->parent)) + continue; - if (isa(worklist_top)) { - stmt_block::Ptr wl_stmt_block = to(worklist_top); - for (auto stmt_: wl_stmt_block->stmts) { - ast_parent_map[stmt_] = worklist_top; + if (isa(bb->parent)) { + for (auto subloop: subloops) { + if (subloop->header_block->parent == bb->parent) { + to(while_block->body)->stmts.push_back(subloop->convert_to_ast_impl(dta_)); + unsigned int index = to(while_block->body)->stmts.size() - 1; + std::cerr << "loop label\n"; + visited_blocks.insert(bb->parent); + ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); + break; + } } - worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end()); - - if (worklist_top == bb->parent) - return ast_parent_map[worklist_top]; } - else if (isa(worklist_top)) { - if_stmt::Ptr wl_if_stmt = to(worklist_top); - // std::cerr << "found if: "; - if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { - // std::cerr << "then\n"; - stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); - for (auto stmt_: wl_if_then_stmt->stmts) { - ast_parent_map[stmt_] = worklist_top; + else if (isa(bb->parent)) { + if_stmt::Ptr if_stmt_copy = std::make_shared(); + if_stmt_copy->then_stmt = to(std::make_shared()); + if_stmt_copy->else_stmt = to(std::make_shared()); + if_stmt_copy->cond = to(bb->parent)->cond; + std::cerr << bb->id << " if\n"; + + if (condition_block == bb) { + if (to(to(bb->parent)->then_stmt)->stmts.size() == 0 && to(to(bb->parent)->else_stmt)->stmts.size() != 0) { + not_expr::Ptr neg_cond = std::make_shared(); + neg_cond->static_offset = if_stmt_copy->cond->static_offset; + neg_cond->expr1 = if_stmt_copy->cond; + while_block->cond = neg_cond; + std::cerr << "neg if\n"; } - worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); - } - if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { - // std::cerr << "else\n"; - stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); - for (auto stmt_: wl_if_else_stmt->stmts) { - ast_parent_map[stmt_] = worklist_top; + else { + while_block->cond = if_stmt_copy->cond; } - worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); } + else { + if_stmt_copy->then_stmt = to(bb->parent)->then_stmt; + if_stmt_copy->else_stmt = to(bb->parent)->else_stmt; + + for (auto stmt: to(if_stmt_copy->then_stmt)->stmts) { + visited_blocks.insert(stmt); + ast_parent_map.insert({stmt, {to(if_stmt_copy->then_stmt), -1}}); + } + + for (auto stmt: to(if_stmt_copy->else_stmt)->stmts) { + visited_blocks.insert(stmt); + ast_parent_map.insert({stmt, {to(if_stmt_copy->else_stmt), -1}}); + } - if (worklist_top == bb->parent) - return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + visited_blocks.insert(if_stmt_copy); + to(while_block->body)->stmts.push_back(if_stmt_copy); + } + + unsigned int index = to(while_block->body)->stmts.size() - 1; + ast_parent_map.insert({to(if_stmt_copy), {to(while_block->body), index}}); + ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); } - else if (isa(worklist_top)) { - stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); - for (auto stmt: wl_while_body_block->stmts) { - ast_parent_map[stmt] = worklist_top; + else if (subloops.size() != 0) { + bool skip_block = false; + for (auto subloop: subloops) { + if (subloop->blocks_id_map.count(bb->id)) { + skip_block = true; + std::cerr << "skipped\n"; + break; + } } - worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); - - if (worklist_top == bb->parent) - return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + + if (skip_block) + continue; } - else if (isa(worklist_top)) { - // std::cerr << "found label\n"; - if (worklist_top == bb->parent) - return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + else if (isa(bb->parent)) { + to(while_block->body)->stmts.push_back(bb->parent); + unsigned int index = to(while_block->body)->stmts.size() - 1; + visited_blocks.insert(bb->parent); + ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); } - else if (isa(worklist_top)) { - // std::cerr << "found goto\n"; - if (worklist_top == bb->parent) - return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + else if (isa(bb->parent)) { + to(while_block->body)->stmts.push_back(bb->parent); + unsigned int index = to(while_block->body)->stmts.size() - 1; + visited_blocks.insert(bb->parent); + ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); } - else if (isa(worklist_top)) { - if (worklist_top == bb->parent) - return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; + else if (isa(bb->parent)) { + to(while_block->body)->stmts.push_back(bb->parent); + unsigned int index = to(while_block->body)->stmts.size() - 1; + visited_blocks.insert(bb->parent); + ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); } } - std::cerr << "Returned nullptr !\n"; - return nullptr; -} - -static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { - for (auto exit_bb: loop->loop_exit_blocks) { - if (!loop->unique_exit_block) - return; + // manage loop exits + for (auto exit_bb: loop_exit_blocks) { + if (!unique_exit_block) + continue; int target_branch = -1; if (!isa(exit_bb->parent)) - assert(0); + assert(0 && "loop exit block must be an if_stmt"); - if (exit_bb->then_branch && !loop->blocks_id_map.count(exit_bb->then_branch->id)) + if (exit_bb->then_branch && !blocks_id_map.count(exit_bb->then_branch->id)) target_branch = 0; - else if (exit_bb->else_branch && !loop->blocks_id_map.count(exit_bb->else_branch->id)) + else if (exit_bb->else_branch && !blocks_id_map.count(exit_bb->else_branch->id)) target_branch = 1; if (target_branch == -1) - assert(0); - - if (target_branch == 0) { - std::vector &temp_ast = to(to(exit_bb->parent)->then_stmt)->stmts; - - if (exit_bb->then_branch == loop->unique_exit_block) { - temp_ast.push_back(std::make_shared()); - } - else { - std::shared_ptr exiting_bb = exit_bb->then_branch; - std::cerr << exiting_bb->id << "\n"; - // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) - // exiting_bb = exit_bb->then_branch->successor[0]; - unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; - while(exiting_bb->is_exit_block) { - std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; - if (temp_exiting_bb->id == loop->unique_exit_block->id) - break; - exiting_bb = temp_exiting_bb; - } - std::cerr << exiting_bb->id << "\n"; - - stmt::Ptr loop_exit_ast; - if (exiting_bb->is_exit_block) - loop_exit_ast = exit_bb->parent; - else - loop_exit_ast = get_loop_block(exiting_bb, ast); - - if (isa(loop_exit_ast)) { - to(loop_exit_ast)->stmts.push_back(std::make_shared()); - } - else if (isa(loop_exit_ast)) { - stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); - // stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); - - // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) - if_then_block->stmts.push_back(std::make_shared()); - // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) - // if_else_block->stmts.push_back(std::make_shared()); + assert(0 && "one of the branches of if should have the exiting block"); + + if (ast_parent_map.count(exit_bb->parent)) { + std::cerr << "inside parent map\n"; + auto temp = ast_parent_map[exit_bb->parent]; + std::cerr << temp.second << "\n"; + std::cerr << temp.first->stmts.size() << "\n"; + std::vector &temp_ast = to(temp.second == -1 ? temp.first : to(temp.first->stmts[temp.second])->then_stmt)->stmts; + std::cerr << "ast size: " << temp_ast.size() << "\n"; + + std::shared_ptr exiting_bb = target_branch ? exit_bb->else_branch : exit_bb->then_branch; + std::cerr << exiting_bb->id << "\n"; + unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id] + 1; + unsigned int unique_exit_index = dta_.get_preorder_bb_map()[unique_exit_block->id]; + std::cerr << preorder_index << " " << unique_exit_index << "\n"; + + for (;preorder_index < unique_exit_index; preorder_index++) { + std::shared_ptr exiting_bb = dta_.cfg_[dta_.get_preorder()[preorder_index]]; + if (!exiting_bb->is_exit_block) { + visited_blocks.insert(exiting_bb->parent); + temp_ast.push_back(exiting_bb->parent); } } - } - else if (target_branch == 1) { - std::vector &temp_ast = to(to(exit_bb->parent)->else_stmt)->stmts; - - if (exit_bb->else_branch == loop->unique_exit_block) { - temp_ast.push_back(std::make_shared()); - } - else { - std::shared_ptr exiting_bb = exit_bb->else_branch; - std::cerr << exiting_bb->id << "\n"; - // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) - // exiting_bb = exit_bb->else_branch->successor[0]; - unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; - while(exiting_bb->is_exit_block) { - std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; - if (temp_exiting_bb->id == loop->unique_exit_block->id) - break; - exiting_bb = temp_exiting_bb; - } - std::cerr << exiting_bb->id << "\n"; + std::cerr << preorder_index << " " << unique_exit_index << "\n"; + if (preorder_index == unique_exit_index) + temp_ast.push_back(std::make_shared()); - stmt::Ptr loop_exit_ast; - if (exiting_bb->is_exit_block) - loop_exit_ast = exit_bb->parent; - else - loop_exit_ast = get_loop_block(exiting_bb, ast); - - if (isa(loop_exit_ast)) { - to(loop_exit_ast)->stmts.push_back(std::make_shared()); - } - else if (isa(loop_exit_ast)) { - // stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); - stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); - - // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) - // if_then_block->stmts.push_back(std::make_shared()); - // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) - if_else_block->stmts.push_back(std::make_shared()); - } - } - } - } -} - -static std::vector backedge_blocks; - -static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { - std::cerr << "loop id: " << loop->loop_id << " : "; - for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { - std::cerr << "loop latch id: " << (*latch_iter)->id << "\n"; - stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); - // stmt::Ptr loop_latch_ast_level_up = get_loop_block(*latch_iter, ast, true); - bool is_last_block = false; - bool is_latch_in_other_loop = false; - - if (dta_.get_preorder_bb_map()[(*latch_iter)->id] == (int)dta_.get_preorder().size() - 1) { - is_last_block = true; + // if (preorder_index == unique_exit_index + 1) + // temp_ast.push_back(std::make_shared()); } else { - int next_preorder = dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1] : -1; - int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - - std::cerr << next_preorder << " : " << next_next_preorder << "\n"; - if (loop->blocks_id_map.count(next_preorder)) - is_last_block = false; - else { - if (loop->unique_exit_block && (next_preorder == (int)loop->unique_exit_block->id)) - is_last_block = true; - else if (loop->unique_exit_block && (next_next_preorder == (int)loop->unique_exit_block->id)) - is_last_block = true; - else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) - is_last_block = true; - else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) - is_last_block = true; - else - is_last_block = false; - } - } - std::cerr << "==== ast ====\n"; - loop_latch_ast->dump(std::cerr, 0); - if ((*latch_iter)->ast_to_basic_block_map.count(loop_latch_ast)) { - std::cerr << "break in latch: " << (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; - auto bb = (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast); - for (auto subloop: loop->subloops) { - if (subloop->blocks_id_map.count(bb->id)) - is_latch_in_other_loop = true; - } + std::cerr << "not inside parent map\n"; } + } - std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << ": " << is_latch_in_other_loop << "\n"; - if (isa(loop_latch_ast)) { - std::cerr << "stmt parent\n"; - std::vector &temp_ast = to(loop_latch_ast)->stmts; - if (is_last_block) - temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); - else { - backedge_blocks.push_back(to(loop_latch_ast)); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); + // manage loop latches + for (auto latch: loop_latch_blocks) { + if (ast_parent_map.count(latch->parent)) { + visited_blocks.insert(latch->parent); + std::cerr << "inside latch map\n"; + auto temp = ast_parent_map[latch->parent]; + std::cerr << temp.second << "\n"; + std::cerr << temp.first->stmts.size() << "\n"; + std::vector &temp_ast = temp.first->stmts; + std::cerr << "ast size: " << temp_ast.size() << "\n"; + + bool is_last_block = false; + // bool is_latch_in_other_loop = false; + + if (dta_.get_preorder_bb_map()[latch->id] == (int)dta_.get_preorder().size() - 1) { + is_last_block = true; } - } - else if (isa(loop_latch_ast)) { - stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); - stmt_block::Ptr if_else_block = to(to(loop_latch_ast)->else_stmt); - - std::cerr << "if parent: "; - std::cerr << if_then_block->stmts.size() << " " << if_else_block->stmts.size() << " " << (*latch_iter)->ast_index << " "; - if (if_then_block->stmts.size() && if_then_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { - std::cerr << "then\n"; - std::vector &temp_ast = if_then_block->stmts; - if (is_last_block) - temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); + else { + int next_preorder = dta_.get_preorder_bb_map()[latch->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[latch->id] + 1] : -1; + int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; + + if (blocks_id_map.count(next_preorder)) + is_last_block = false; else { - backedge_blocks.push_back(if_then_block); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); + if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) + is_last_block = true; + else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) + is_last_block = true; + else + is_last_block = false; } } - - if (if_else_block->stmts.size() && if_else_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { - std::cerr << "else\n"; - std::vector &temp_ast = if_else_block->stmts; - if (is_last_block) - temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); - else { - backedge_blocks.push_back(if_else_block); - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); - } + + // if (latch->ast_to_basic_block_map.count(loop_latch_ast)) { + // std::cerr << "break in latch: " << latch->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; + // auto bb = latch->ast_to_basic_block_map.at(loop_latch_ast); + // for (auto subloop: loop->subloops) { + // if (subloop->blocks_id_map.count(bb->id)) + // is_latch_in_other_loop = true; + // } + // } + + temp_ast.pop_back(); + if (!is_last_block) { + while_block->continue_blocks.push_back(temp.first); + temp_ast.push_back(std::make_shared()); } } } + + return to(while_block); } block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { - std::cerr << "before ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "before ast\n"; - - for (auto loop_map: preorder_loops_map) { - for (auto preorder: loop_map.second) { - replace_loop_exits(loops[preorder], ast, dta); - replace_loop_latches(loops[preorder], ast, dta); + + block::stmt_block::Ptr return_ast = std::make_shared(); + + for (auto bb: dta.cfg_) { + if (isa(bb->parent)) { + for (auto loop: top_level_loops) { + if (loop->header_block->parent == bb->parent) + return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + } + } + else if (!bb_loop_map.count(bb->id) && !visited_blocks.count(bb->parent) && !bb->is_exit_block) { + return_ast->stmts.push_back(bb->parent); } } - - std::cerr << "after ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "after ast\n"; + // for (auto loop: top_level_loops) { + // return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + // } + + return return_ast; + +// std::cerr << "before ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "before ast\n"; + + // for (auto loop_map: preorder_loops_map) { + // for (auto preorder: loop_map.second) { + // replace_loop_exits(loops[preorder], ast, dta); + // replace_loop_latches(loops[preorder], ast, dta); + // } + // } + + // std::cerr << "after ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "after ast\n"; // return ast; - for (auto loop_map: postorder_loops_map) { - for (auto postorder: loop_map.second) { - std::cerr << "before ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "before ast\n"; - block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); - std::cerr << loops[postorder]->header_block->ast_index << "\n"; - loop_header_ast->dump(std::cerr, 0); - while_stmt::Ptr while_block = std::make_shared(); - while_block->body = std::make_shared(); - - if (isa(loop_header_ast)) { - loop_header_ast = to(loop_header_ast)->body; - } - if (isa(loop_header_ast)) { - unsigned int ast_index = loops[postorder]->header_block->ast_index; - // handle unconditional loops - if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(to(loop_header_ast)->stmts[ast_index + 1])) { - for (auto bb: loops[postorder]->blocks) { - to(while_block->body)->stmts.push_back(bb->parent); - } - // pop loop backedge - to(while_block->body)->stmts.pop_back(); - - // set always true condition - while_block->cond = std::make_shared(); - to(while_block->cond)->value = 1; - - // unconditional loops can have only one backedge !? - assert(loops[postorder]->loop_latch_blocks.size() == 1); - for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - std::cerr << i << "\n"; - worklist.push_back(std::make_tuple(i, std::ref(to(loop_header_ast)->stmts), nullptr)); - } - worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); - } - else if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { - stmt_block::Ptr then_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->then_stmt); - stmt_block::Ptr else_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->else_stmt); - std::cerr << "stmt block\n"; - - while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; - if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - // if (else_block->stmts.size() != 0) - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - // else { - then_block->stmts.pop_back(); - for (auto stmt: then_block->stmts) - to(loop_header_ast)->stmts.push_back(stmt); - // } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // then_block->stmts.pop_back(); - // for (auto stmt: then_block->stmts) - // to(loop_header_ast)->stmts.push_back(stmt); - // } - else { - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - // if block to be replaced with while block - worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); - } - } - else if (isa(loop_header_ast)) { - unsigned int ast_index = loops[postorder]->header_block->ast_index; - stmt_block::Ptr if_then_block = to(to(loop_header_ast)->then_stmt); - stmt_block::Ptr if_else_block = to(to(loop_header_ast)->else_stmt); - - if (if_then_block->stmts.size() != 0) { - std::cerr << "if then block\n"; - // handle unconditional loops - if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_then_block->stmts[ast_index + 1])) { - for (auto bb: loops[postorder]->blocks) { - to(while_block->body)->stmts.push_back(bb->parent); - } - // pop loop backedge - to(while_block->body)->stmts.pop_back(); - - // set always true condition - while_block->cond = std::make_shared(); - to(while_block->cond)->value = 1; - - // unconditional loops can have only one backedge !? - assert(loops[postorder]->loop_latch_blocks.size() == 1); - for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - worklist.push_back(std::make_tuple(i, std::ref(if_then_block->stmts), nullptr)); - } - - worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); - } - else if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { - stmt_block::Ptr then_block = to(to(if_then_block->stmts[ast_index + 1])->then_stmt); - stmt_block::Ptr else_block = to(to(if_then_block->stmts[ast_index + 1])->else_stmt); - - while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; - if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - then_block->stmts.pop_back(); - for (auto stmt: then_block->stmts) - if_then_block->stmts.push_back(stmt); - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // then_block->stmts.pop_back(); - // for (auto stmt: then_block->stmts) - // if_then_block->stmts.push_back(stmt); - // } - else { - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - // if block to be replaced with while block - worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); - } - } + // std::cerr << "before ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "before ast\n"; + // block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); + // std::cerr << loops[postorder]->header_block->ast_index << "\n"; + // loop_header_ast->dump(std::cerr, 0); + // while_stmt::Ptr while_block = std::make_shared(); + // while_block->body = std::make_shared(); + // while_block->cond = std::make_shared(); + // to(while_block->cond)->value = 1; + // if (isa(loop_header_ast)) { + // loop_header_ast = to(loop_header_ast)->body; + // } + + // if (isa(loop_header_ast)) { + // unsigned int ast_index = loops[postorder]->header_block->ast_index; + // // handle unconditional loops + // if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(to(loop_header_ast)->stmts[ast_index + 1])) { + // for (auto bb: loops[postorder]->blocks) { + // to(while_block->body)->stmts.push_back(bb->parent); + // } + // // pop loop backedge + // to(while_block->body)->stmts.pop_back(); + + // // set always true condition + // while_block->cond = std::make_shared(); + // to(while_block->cond)->value = 1; + + // // unconditional loops can have only one backedge !? + // assert(loops[postorder]->loop_latch_blocks.size() == 1); + // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + // std::cerr << i << "\n"; + // worklist.push_back(std::make_tuple(i, std::ref(to(loop_header_ast)->stmts), nullptr)); + // } + + // worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); + // } + // else if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { + // stmt_block::Ptr then_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->then_stmt); + // stmt_block::Ptr else_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->else_stmt); + // std::cerr << "stmt block\n"; + + // // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; + // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } + + // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // if (backedge_iter != backedge_blocks.end()) { + // std::cerr << "replaced BE\n"; + // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // } + // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // // if (else_block->stmts.size() != 0) + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + // // // else { + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // to(loop_header_ast)->stmts.push_back(stmt); + // // // } + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // to(loop_header_ast)->stmts.push_back(stmt); + // // } + // // else { + // // for (auto body_stmt: then_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + // // if block to be replaced with while block + // worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); + // } + // } + // else if (isa(loop_header_ast)) { + // unsigned int ast_index = loops[postorder]->header_block->ast_index; + // stmt_block::Ptr if_then_block = to(to(loop_header_ast)->then_stmt); + // stmt_block::Ptr if_else_block = to(to(loop_header_ast)->else_stmt); + + // if (if_then_block->stmts.size() != 0) { + // std::cerr << "if then block\n"; + // // handle unconditional loops + // if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_then_block->stmts[ast_index + 1])) { + // for (auto bb: loops[postorder]->blocks) { + // to(while_block->body)->stmts.push_back(bb->parent); + // } + // // pop loop backedge + // to(while_block->body)->stmts.pop_back(); + + // // set always true condition + // while_block->cond = std::make_shared(); + // to(while_block->cond)->value = 1; + + // // unconditional loops can have only one backedge !? + // assert(loops[postorder]->loop_latch_blocks.size() == 1); + // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + // worklist.push_back(std::make_tuple(i, std::ref(if_then_block->stmts), nullptr)); + // } + + // worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); + // } + // else if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + // stmt_block::Ptr then_block = to(to(if_then_block->stmts[ast_index + 1])->then_stmt); + // stmt_block::Ptr else_block = to(to(if_then_block->stmts[ast_index + 1])->else_stmt); + + // // while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; + // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + // while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } + + // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // if (backedge_iter != backedge_blocks.end()) { + // std::cerr << "replaced BE\n"; + // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // } + // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // if_then_block->stmts.push_back(stmt); + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // if_then_block->stmts.push_back(stmt); + // // } + // // else { + // // for (auto body_stmt: then_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + // // if block to be replaced with while block + // worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); + // } + // } - if (if_else_block->stmts.size() != 0) { - std::cerr << "if else block\n"; - // handle unconditional loops - if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_else_block->stmts[ast_index + 1])) { - for (auto bb: loops[postorder]->blocks) { - to(while_block->body)->stmts.push_back(bb->parent); - } - // pop loop backedge - to(while_block->body)->stmts.pop_back(); - - // set always true condition - while_block->cond = std::make_shared(); - to(while_block->cond)->value = 1; - - // unconditional loops can have only one backedge !? - assert(loops[postorder]->loop_latch_blocks.size() == 1); - for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - worklist.push_back(std::make_tuple(i, std::ref(if_else_block->stmts), nullptr)); - } - - worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); - } - else if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { - stmt_block::Ptr then_block = to(to(if_else_block->stmts[ast_index + 1])->then_stmt); - stmt_block::Ptr else_block = to(to(if_else_block->stmts[ast_index + 1])->else_stmt); - - while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; - if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - not_expr::Ptr new_cond = std::make_shared(); - new_cond->static_offset = while_block->cond->static_offset; - new_cond->expr1 = while_block->cond; - while_block->cond = new_cond; - - for (auto body_stmt: else_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - then_block->stmts.pop_back(); - for (auto stmt: then_block->stmts) - if_else_block->stmts.push_back(stmt); - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // else if (then_block->stmts.size() <= 2 && isa(then_block->stmts.back())) { - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // then_block->stmts.pop_back(); - // for (auto stmt: then_block->stmts) - // if_else_block->stmts.push_back(stmt); - // } - else { - for (auto body_stmt: then_block->stmts) { - to(while_block->body)->stmts.push_back(body_stmt); - } - - auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - if (backedge_iter != backedge_blocks.end()) { - std::cerr << "replaced BE\n"; - std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - } - while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - } - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - // if block to be replaced with while block - worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); - } - } - } - - // process worklist - std::sort(worklist.begin(), worklist.end(), [](std::tuple>, stmt::Ptr> a, std::tuple>, stmt::Ptr> b) { - return std::get<0>(a) > std::get<0>(b); - }); - for (auto item : worklist) { - std::vector &temp_ast = std::get<1>(item); - if (std::get<2>(item)) { - std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[std::get<0>(item) + 1], std::get<2>(item)); - temp_ast.erase(temp_ast.begin() + std::get<0>(item)); - } - } - - for (auto item : worklist) { - std::vector &temp_ast = std::get<1>(item); - if (!std::get<2>(item)) { - temp_ast.erase(temp_ast.begin() + std::get<0>(item)); - } - } - worklist.clear(); - - std::cerr << "after ast\n"; - ast->dump(std::cerr, 0); - std::cerr << "after ast\n"; - } - } - - return ast; + // if (if_else_block->stmts.size() != 0) { + // std::cerr << "if else block\n"; + // // handle unconditional loops + // if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_else_block->stmts[ast_index + 1])) { + // for (auto bb: loops[postorder]->blocks) { + // to(while_block->body)->stmts.push_back(bb->parent); + // } + // // pop loop backedge + // to(while_block->body)->stmts.pop_back(); + + // // set always true condition + // while_block->cond = std::make_shared(); + // to(while_block->cond)->value = 1; + + // // unconditional loops can have only one backedge !? + // assert(loops[postorder]->loop_latch_blocks.size() == 1); + // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { + // worklist.push_back(std::make_tuple(i, std::ref(if_else_block->stmts), nullptr)); + // } + + // worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); + // } + // else if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { + // stmt_block::Ptr then_block = to(to(if_else_block->stmts[ast_index + 1])->then_stmt); + // stmt_block::Ptr else_block = to(to(if_else_block->stmts[ast_index + 1])->else_stmt); + + // // while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; + // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { + // while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; + // not_expr::Ptr new_cond = std::make_shared(); + // new_cond->static_offset = while_block->cond->static_offset; + // new_cond->expr1 = while_block->cond; + // while_block->cond = new_cond; + + // for (auto body_stmt: else_block->stmts) { + // to(while_block->body)->stmts.push_back(body_stmt); + // } + + // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // if (backedge_iter != backedge_blocks.end()) { + // std::cerr << "replaced BE\n"; + // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // } + // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // if_else_block->stmts.push_back(stmt); + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { + // // not_expr::Ptr new_cond = std::make_shared(); + // // new_cond->static_offset = while_block->cond->static_offset; + // // new_cond->expr1 = while_block->cond; + // // while_block->cond = new_cond; + + // // then_block->stmts.pop_back(); + // // for (auto stmt: then_block->stmts) + // // if_else_block->stmts.push_back(stmt); + // // } + // // else { + // // for (auto body_stmt: then_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + + // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); + // // if (backedge_iter != backedge_blocks.end()) { + // // std::cerr << "replaced BE\n"; + // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); + // // } + // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); + // // } + + // // for (auto body_stmt: else_block->stmts) { + // // to(while_block->body)->stmts.push_back(body_stmt); + // // } + // // if block to be replaced with while block + // worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); + // } + // } + // } + + // // process worklist + // std::sort(worklist.begin(), worklist.end(), [](std::tuple>, stmt::Ptr> a, std::tuple>, stmt::Ptr> b) { + // return std::get<0>(a) > std::get<0>(b); + // }); + // for (auto item : worklist) { + // std::vector &temp_ast = std::get<1>(item); + // if (std::get<2>(item)) { + // std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[std::get<0>(item) + 1], std::get<2>(item)); + // temp_ast.erase(temp_ast.begin() + std::get<0>(item)); + // } + // } + + // for (auto item : worklist) { + // std::vector &temp_ast = std::get<1>(item); + // if (!std::get<2>(item)) { + // temp_ast.erase(temp_ast.begin() + std::get<0>(item)); + // } + // } + // worklist.clear(); + + // std::cerr << "after ast\n"; + // ast->dump(std::cerr, 0); + // std::cerr << "after ast\n"; } diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index bd66e76..77f2b0f 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -498,9 +498,10 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "++++++ loop info ++++++ \n"; + // return ast; std::cerr << "++++++ convert to ast ++++++ \n"; - LI.convert_to_ast(block::to(ast)); + ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; // block::loop_finder finder; @@ -602,7 +603,6 @@ block::stmt::Ptr builder_context::extract_ast_from_function_internal(std::vector ret_ast = ast; } catch (LoopBackException &e) { current_builder_context = nullptr; - std::cerr << "goto in\n"; block::goto_stmt::Ptr goto_stmt = std::make_shared(); goto_stmt->static_offset.clear(); goto_stmt->temporary_label_number = e.static_offset; @@ -612,13 +612,11 @@ block::stmt::Ptr builder_context::extract_ast_from_function_internal(std::vector } catch (MemoizationException &e) { if (feature_unstructured) { // Instead of copying statements to the current block, we will just insert a goto - std::cerr << "goto memo\n"; block::goto_stmt::Ptr goto_stmt = std::make_shared(); goto_stmt->static_offset.clear(); goto_stmt->temporary_label_number = e.static_offset; add_stmt_to_current_block(goto_stmt, false); } else { - std::cerr << "goto memo\n"; for (unsigned int i = e.child_id; i < e.parent->stmts.size(); i++) { if (isa(e.parent->stmts[i])) { block::goto_stmt::Ptr goto_stmt = std::make_shared(); From 7818fef2256d8ceee98074f2407408472b6e503e Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Tue, 26 Sep 2023 03:30:59 +0530 Subject: [PATCH 15/24] WIP v2: Handle the non-loop blocks using a iterative algorithm --- include/blocks/basic_blocks.h | 2 +- src/blocks/loops.cpp | 216 ++++++++++++++++++++++++++++++++-- 2 files changed, 207 insertions(+), 11 deletions(-) diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h index 1eb25ee..ee4f6a9 100644 --- a/include/blocks/basic_blocks.h +++ b/include/blocks/basic_blocks.h @@ -17,7 +17,7 @@ class basic_block { std::shared_ptr then_branch; std::shared_ptr else_branch; std::shared_ptr exit_block; - bool is_exit_block; + bool is_exit_block = false; block::stmt::Ptr parent; unsigned int ast_index; unsigned int ast_depth; diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index c28664e..0a39545 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -1,4 +1,5 @@ #include "blocks/loops.h" +#include #include #include #include @@ -700,23 +701,218 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_) { return to(while_block); } +std::map ast_parent_map_global; block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { - block::stmt_block::Ptr return_ast = std::make_shared(); - - for (auto bb: dta.cfg_) { + + std::deque, stmt_block::Ptr>> worklist; + std::unordered_set> visited; + worklist.push_back({dta.cfg_[0], return_ast}); + visited.insert(dta.cfg_[0]); + + while (worklist.size()) { + auto bb_ast_pair = worklist.front(); + auto bb = bb_ast_pair.first; + auto ast = bb_ast_pair.second; + worklist.pop_front(); + if (isa(bb->parent)) { - for (auto loop: top_level_loops) { - if (loop->header_block->parent == bb->parent) - return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + for (auto loop : top_level_loops) { + if (loop->header_block->parent == bb->parent) { + ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + std::cerr << "found loop\n"; + break; + } } } - else if (!bb_loop_map.count(bb->id) && !visited_blocks.count(bb->parent) && !bb->is_exit_block) { - return_ast->stmts.push_back(bb->parent); + else if (isa(bb->parent)) { + + if (bb_loop_map.count(bb->id)) + continue; + + if (visited_blocks.count(bb->parent)) + continue; + + if_stmt::Ptr if_stmt_copy = std::make_shared(); + if_stmt_copy->then_stmt = to(std::make_shared()); + if_stmt_copy->else_stmt = to(std::make_shared()); + if_stmt_copy->cond = to(bb->parent)->cond; + + // push the then branch onto worklist. (worklist should be a pair ) ? + if (bb->then_branch) { + ast_parent_map_global[to(if_stmt_copy->then_stmt)] = ast; + worklist.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); + visited.insert(bb->then_branch); + } + + if (bb->else_branch) { + ast_parent_map_global[to(if_stmt_copy->else_stmt)] = ast; + worklist.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); + visited.insert(bb->else_branch); + } + + ast->stmts.push_back(to(if_stmt_copy)); + } + else { + assert(bb->successor.size() <= 1); + + if (bb_loop_map.count(bb->id)) + continue; + + if (visited_blocks.count(bb->parent)) + continue; + + // what is happening is that when we see a if stmt exit block we should + // reduce the level of the tree, it is not being done now. + if (!bb->is_exit_block && !isa(bb->parent)) + ast->stmts.push_back(to(bb->parent)); + + if (bb->successor.size()) { + if (visited.count(bb->successor[0])) + continue; + else + visited.insert(bb->successor[0]); + + if (bb->is_exit_block) + worklist.push_back({bb->successor[0], ast_parent_map_global[ast]}); + else + worklist.push_back({bb->successor[0], ast}); + } } } - // for (auto loop: top_level_loops) { - // return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + // // iterate using preorder bb + // // use stack for current parent block + // std::stack parent_stack; + // parent_stack.push(to(return_ast)); + + // for (unsigned int i = 0; i < dta.get_preorder().size(); i++) { + // auto bb = dta.cfg_[dta.get_preorder()[i]]; + + // std::cerr << "bb: " << bb->id << "\n"; + // if (isa(bb->parent)) { + // std::cerr << "inside label block\n"; + + // for (auto loop: top_level_loops) { + // if (loop->header_block->parent == bb->parent) { + // to(parent_stack.top())->stmts.push_back(loop->convert_to_ast_impl(dta)); + // break; + // } + // } + // } + // else if (isa(bb->parent)) { + // std::cerr << "inside if block\n"; + + // if (bb_loop_map.count(bb->id)) + // continue; + // std::cerr << "inside if block (exit 1)\n"; + + // if (visited_blocks.count(bb->parent)) + // continue; + // std::cerr << "inside if block (exit 2)\n"; + + // if (dta.get_preorder().size() <= i + 1) + // continue; + // std::cerr << "inside if block (exit 3)\n"; + + // if_stmt::Ptr if_stmt_copy = std::make_shared(); + // if_stmt_copy->then_stmt = to(std::make_shared()); + // if_stmt_copy->else_stmt = to(std::make_shared()); + // if_stmt_copy->cond = to(bb->parent)->cond; + + // int next_block = -1; + // if (dta.get_preorder()[i + 1] == (int)bb->then_branch->id) + // next_block = 0; + // else if (dta.get_preorder()[i + 1] == (int)bb->else_branch->id) + // next_block = 1; + + // assert(next_block != -1); + + // to(parent_stack.top())->stmts.push_back(if_stmt_copy); + // if (next_block == 0) { + // parent_stack.push(to(if_stmt_copy->then_stmt)); + // } + // else if (next_block == 1) { + // parent_stack.push(to(if_stmt_copy->else_stmt)); + // } + + // } + // else if (bb->is_exit_block) { + // std::cerr << "inside exit block\n"; + + // if (bb_loop_map.count(bb->id)) + // continue; + // std::cerr << "inside exit block (exit 1)\n"; + + // if (visited_blocks.count(bb->parent)) + // continue; + + // parent_stack.pop(); + // } + // else { + // std::cerr << "inside default block\n"; + + // if (bb_loop_map.count(bb->id)) + // continue; + // std::cerr << "inside default block (exit 1)\n"; + + // if (visited_blocks.count(bb->parent)) + // continue; + // std::cerr << "inside default block (exit 2)\n"; + + // to(parent_stack.top())->stmts.push_back(bb->parent); + // } + // } + + // for (auto bb: dta.cfg_) { + // std::cerr << bb->id << " " << bb_loop_map.count(bb->id) << " " << visited_blocks.count(bb->parent) << " " << bb->is_exit_block << "\n"; + // if (isa(bb->parent)) { + // std::cerr << "inside label block\n"; + // for (auto loop: top_level_loops) { + // if (loop->header_block->parent == bb->parent) { + // if (ast_parent_map_global.count(bb->parent)) { + // ast_parent_map_global[bb->parent]->stmts.push_back(loop->convert_to_ast_impl(dta)); + // } + // else { + // return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); + // } + // } + // } + // } + // else if (!bb_loop_map.count(bb->id) && !visited_blocks.count(bb->parent) && !bb->is_exit_block) { + // std::cerr << "inside if block\n"; + // stmt::Ptr push_block = bb->parent; + + // if (isa(bb->parent)) { + // if_stmt::Ptr if_stmt_copy = std::make_shared(); + // if_stmt_copy->then_stmt = to(std::make_shared()); + // if_stmt_copy->else_stmt = to(std::make_shared()); + // if_stmt_copy->cond = to(bb->parent)->cond; + // push_block = to(if_stmt_copy); + + // for (auto stmt: to(to(bb->parent)->then_stmt)->stmts) { + // if (!isa(stmt)) { + // std::cerr << "ifstmt\n"; + // visited_blocks.insert(stmt); + // to(if_stmt_copy->then_stmt)->stmts.push_back(stmt); + // } + // ast_parent_map_global.insert({stmt, to(if_stmt_copy->then_stmt)}); + // } + // for (auto stmt: to(to(bb->parent)->else_stmt)->stmts) { + // if (!isa(stmt)) { + // std::cerr << "elsestmt\n"; + // visited_blocks.insert(stmt); + // to(if_stmt_copy->else_stmt)->stmts.push_back(stmt); + // } + // ast_parent_map_global.insert({stmt, to(if_stmt_copy->else_stmt)}); + // } + // } + // else if (isa(bb->parent)) { + // continue; + // } + + // visited_blocks.insert(bb->parent); + // return_ast->stmts.push_back(push_block); + // } // } return return_ast; From 9bb93bc46e8c2c97b66ae1970ec8b1a910039f00 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Wed, 27 Sep 2023 02:23:45 +0530 Subject: [PATCH 16/24] WIP v3: Handle the non-loop blocks using a iterative algorithm --- include/blocks/loops.h | 2 +- src/blocks/loops.cpp | 689 ++++++++++++-------------------- src/builder/builder_context.cpp | 4 +- 3 files changed, 254 insertions(+), 441 deletions(-) diff --git a/include/blocks/loops.h b/include/blocks/loops.h index c65ad51..0751167 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -10,7 +10,7 @@ using namespace block; class loop { public: loop(std::shared_ptr header): header_block(header) {} - stmt::Ptr convert_to_ast_impl(dominator_analysis &dta_); + stmt::Ptr convert_to_ast_impl(dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks); struct loop_bounds_ { stmt::Ptr ind_var; diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 0a39545..0222787 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -225,479 +225,290 @@ void loop_info::analyze() { } } -// static stmt::Ptr get_loop_block(std::shared_ptr bb, block::stmt_block::Ptr ast, bool one_level_up = false) { -// block::stmt::Ptr current_ast = to(ast); -// std::vector current_block = to(current_ast)->stmts; -// std::deque worklist; -// std::map ast_parent_map; -// // std::cerr << bb->name << "\n"; - -// for (auto stmt: current_block) { -// ast_parent_map[stmt] = current_ast; -// } -// worklist.insert(worklist.end(), current_block.begin(), current_block.end()); - -// while (worklist.size()) { -// stmt::Ptr worklist_top = worklist.front(); -// worklist.pop_front(); - -// if (isa(worklist_top)) { -// stmt_block::Ptr wl_stmt_block = to(worklist_top); -// for (auto stmt_: wl_stmt_block->stmts) { -// ast_parent_map[stmt_] = worklist_top; -// } -// worklist.insert(worklist.end(), wl_stmt_block->stmts.begin(), wl_stmt_block->stmts.end()); - -// if (worklist_top == bb->parent) -// return ast_parent_map[worklist_top]; -// } -// else if (isa(worklist_top)) { -// if_stmt::Ptr wl_if_stmt = to(worklist_top); -// // std::cerr << "found if: "; -// if (to(wl_if_stmt->then_stmt)->stmts.size() != 0) { -// // std::cerr << "then\n"; -// stmt_block::Ptr wl_if_then_stmt = to(wl_if_stmt->then_stmt); -// for (auto stmt_: wl_if_then_stmt->stmts) { -// ast_parent_map[stmt_] = worklist_top; -// } -// worklist.insert(worklist.end(), wl_if_then_stmt->stmts.begin(), wl_if_then_stmt->stmts.end()); -// } -// if (to(wl_if_stmt->else_stmt)->stmts.size() != 0) { -// // std::cerr << "else\n"; -// stmt_block::Ptr wl_if_else_stmt = to(wl_if_stmt->else_stmt); -// for (auto stmt_: wl_if_else_stmt->stmts) { -// ast_parent_map[stmt_] = worklist_top; -// } -// worklist.insert(worklist.end(), wl_if_else_stmt->stmts.begin(), wl_if_else_stmt->stmts.end()); -// } - -// if (worklist_top == bb->parent) -// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; -// } -// else if (isa(worklist_top)) { -// stmt_block::Ptr wl_while_body_block = to(to(worklist_top)->body); -// for (auto stmt: wl_while_body_block->stmts) { -// ast_parent_map[stmt] = worklist_top; -// } -// worklist.insert(worklist.end(), wl_while_body_block->stmts.begin(), wl_while_body_block->stmts.end()); - -// if (worklist_top == bb->parent) -// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; -// } -// else if (isa(worklist_top)) { -// // std::cerr << "found label\n"; -// if (worklist_top == bb->parent) -// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; -// } -// else if (isa(worklist_top)) { -// // std::cerr << "found goto\n"; -// if (worklist_top == bb->parent) -// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; -// } -// else if (isa(worklist_top)) { -// if (worklist_top == bb->parent) -// return one_level_up ? ast_parent_map[ast_parent_map[worklist_top]] : ast_parent_map[worklist_top]; -// } -// } - -// std::cerr << "Returned nullptr !\n"; -// return nullptr; -// } - -// static void replace_loop_exits(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { -// for (auto exit_bb: loop->loop_exit_blocks) { -// if (!loop->unique_exit_block) -// return; - -// int target_branch = -1; - -// if (!isa(exit_bb->parent)) -// assert(0); - -// if (exit_bb->then_branch && !loop->blocks_id_map.count(exit_bb->then_branch->id)) -// target_branch = 0; -// else if (exit_bb->else_branch && !loop->blocks_id_map.count(exit_bb->else_branch->id)) -// target_branch = 1; - -// if (target_branch == -1) -// assert(0); - -// if (target_branch == 0) { -// std::vector &temp_ast = to(to(exit_bb->parent)->then_stmt)->stmts; - -// if (exit_bb->then_branch == loop->unique_exit_block) { -// temp_ast.push_back(std::make_shared()); -// } -// else { -// std::shared_ptr exiting_bb = exit_bb->then_branch; -// std::cerr << exiting_bb->id << "\n"; -// // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) -// // exiting_bb = exit_bb->then_branch->successor[0]; -// unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; -// while(exiting_bb->is_exit_block) { -// std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; -// if (temp_exiting_bb->id == loop->unique_exit_block->id) -// break; -// exiting_bb = temp_exiting_bb; -// } -// std::cerr << exiting_bb->id << "\n"; - -// stmt::Ptr loop_exit_ast; -// if (exiting_bb->is_exit_block) -// loop_exit_ast = exit_bb->parent; -// else -// loop_exit_ast = get_loop_block(exiting_bb, ast); - -// if (isa(loop_exit_ast)) { -// to(loop_exit_ast)->stmts.push_back(std::make_shared()); -// } -// else if (isa(loop_exit_ast)) { -// stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); -// // stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); - -// // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) -// if_then_block->stmts.push_back(std::make_shared()); -// // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) -// // if_else_block->stmts.push_back(std::make_shared()); -// } -// } -// } -// else if (target_branch == 1) { -// std::vector &temp_ast = to(to(exit_bb->parent)->else_stmt)->stmts; - -// if (exit_bb->else_branch == loop->unique_exit_block) { -// temp_ast.push_back(std::make_shared()); -// } -// else { -// std::shared_ptr exiting_bb = exit_bb->else_branch; -// std::cerr << exiting_bb->id << "\n"; -// // if (!isa(exiting_bb->parent) || to(exiting_bb->parent)->stmts.size() == 0) -// // exiting_bb = exit_bb->else_branch->successor[0]; -// unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id]; -// while(exiting_bb->is_exit_block) { -// std::shared_ptr temp_exiting_bb = dta_.cfg_[dta_.get_preorder()[++preorder_index]]; -// if (temp_exiting_bb->id == loop->unique_exit_block->id) -// break; -// exiting_bb = temp_exiting_bb; -// } -// std::cerr << exiting_bb->id << "\n"; - -// stmt::Ptr loop_exit_ast; -// if (exiting_bb->is_exit_block) -// loop_exit_ast = exit_bb->parent; -// else -// loop_exit_ast = get_loop_block(exiting_bb, ast); - -// if (isa(loop_exit_ast)) { -// to(loop_exit_ast)->stmts.push_back(std::make_shared()); -// } -// else if (isa(loop_exit_ast)) { -// // stmt_block::Ptr if_then_block = to(to(loop_exit_ast)->then_stmt); -// stmt_block::Ptr if_else_block = to(to(loop_exit_ast)->else_stmt); - -// // if (exiting_bb->ast_index < if_then_block->stmts.size() && if_then_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) -// // if_then_block->stmts.push_back(std::make_shared()); -// // else if (exiting_bb->ast_index < if_else_block->stmts.size() && if_else_block->stmts[exiting_bb->ast_index] == exiting_bb->parent) -// if_else_block->stmts.push_back(std::make_shared()); -// } -// } -// } -// } -// } - -// static std::vector backedge_blocks; - -// static void replace_loop_latches(std::shared_ptr loop, block::stmt_block::Ptr ast, dominator_analysis &dta_) { -// std::cerr << "loop id: " << loop->loop_id << " : "; -// for (auto latch_iter = loop->loop_latch_blocks.begin(); latch_iter != loop->loop_latch_blocks.end(); latch_iter++) { -// std::cerr << "loop latch id: " << (*latch_iter)->id << "\n"; -// stmt::Ptr loop_latch_ast = get_loop_block(*latch_iter, ast); -// // stmt::Ptr loop_latch_ast_level_up = get_loop_block(*latch_iter, ast, true); -// bool is_last_block = false; -// bool is_latch_in_other_loop = false; - -// if (dta_.get_preorder_bb_map()[(*latch_iter)->id] == (int)dta_.get_preorder().size() - 1) { -// is_last_block = true; -// } -// else { -// int next_preorder = dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[(*latch_iter)->id] + 1] : -1; -// int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - -// std::cerr << next_preorder << " : " << next_next_preorder << "\n"; -// if (loop->blocks_id_map.count(next_preorder)) -// is_last_block = false; -// else { -// if (loop->unique_exit_block && (next_preorder == (int)loop->unique_exit_block->id)) -// is_last_block = true; -// else if (loop->unique_exit_block && (next_next_preorder == (int)loop->unique_exit_block->id)) -// is_last_block = true; -// else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) -// is_last_block = true; -// else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) -// is_last_block = true; -// else -// is_last_block = false; -// } -// } -// std::cerr << "==== ast ====\n"; -// loop_latch_ast->dump(std::cerr, 0); -// if ((*latch_iter)->ast_to_basic_block_map.count(loop_latch_ast)) { -// std::cerr << "break in latch: " << (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; -// auto bb = (*latch_iter)->ast_to_basic_block_map.at(loop_latch_ast); -// for (auto subloop: loop->subloops) { -// if (subloop->blocks_id_map.count(bb->id)) -// is_latch_in_other_loop = true; -// } -// } - -// std::cerr << "LL: " << (*latch_iter)->id << ": " << is_last_block << ": " << is_latch_in_other_loop << "\n"; -// if (isa(loop_latch_ast)) { -// std::cerr << "stmt parent\n"; -// std::vector &temp_ast = to(loop_latch_ast)->stmts; -// if (is_last_block) -// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); -// else { -// backedge_blocks.push_back(to(loop_latch_ast)); -// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index + 1], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); -// } -// } -// else if (isa(loop_latch_ast)) { -// stmt_block::Ptr if_then_block = to(to(loop_latch_ast)->then_stmt); -// stmt_block::Ptr if_else_block = to(to(loop_latch_ast)->else_stmt); - -// std::cerr << "if parent: "; -// std::cerr << if_then_block->stmts.size() << " " << if_else_block->stmts.size() << " " << (*latch_iter)->ast_index << " "; -// if (if_then_block->stmts.size() && if_then_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { -// std::cerr << "then\n"; -// std::vector &temp_ast = if_then_block->stmts; -// if (is_last_block) -// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); -// else { -// backedge_blocks.push_back(if_then_block); -// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); -// } -// } - -// if (if_else_block->stmts.size() && if_else_block->stmts[(*latch_iter)->ast_index] == (*latch_iter)->parent) { -// std::cerr << "else\n"; -// std::vector &temp_ast = if_else_block->stmts; -// if (is_last_block) -// temp_ast.erase(temp_ast.begin() + (*latch_iter)->ast_index); -// else { -// backedge_blocks.push_back(if_else_block); -// std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[(*latch_iter)->ast_index], is_latch_in_other_loop ? to(std::make_shared()) : to(std::make_shared())); -// } -// } -// } -// } -// } std::set visited_blocks; -std::map> ast_parent_map; -stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_) { +std::map ast_parent_map_loop; +stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks) { while_stmt::Ptr while_block = std::make_shared(); while_block->body = std::make_shared(); - while_block->cond = std::make_shared(); - to(while_block->cond)->value = 1; + if (!condition_block) { + while_block->cond = std::make_shared(); + to(while_block->cond)->value = 1; + } + std::deque, stmt_block::Ptr>> worklist; + std::unordered_set> visited; + worklist.push_back({header_block->successor[0], to(while_block->body)}); + visited.insert(header_block->successor[0]); + std::cerr << "loop: " << loop_id << " " << header_block->id << "\n"; - if_stmt::Ptr if_stmt_; - for (auto bb: blocks) { - std::cerr << "block: " << bb->id << "\n"; - - if (visited_blocks.count(bb->parent)) - continue; - + while (worklist.size()) { + auto bb_ast_pair = worklist.front(); + auto bb = bb_ast_pair.first; + auto ast = bb_ast_pair.second; + worklist.pop_front(); + if (isa(bb->parent)) { for (auto subloop: subloops) { if (subloop->header_block->parent == bb->parent) { - to(while_block->body)->stmts.push_back(subloop->convert_to_ast_impl(dta_)); - unsigned int index = to(while_block->body)->stmts.size() - 1; - std::cerr << "loop label\n"; - visited_blocks.insert(bb->parent); - ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); + std::cerr << "found subloop\n"; + std::vector, stmt_block::Ptr>> loop_out_blocks; + ast->stmts.push_back(subloop->convert_to_ast_impl(dta_, loop_out_blocks)); + + for (auto block: loop_out_blocks) { + worklist.push_back({block.first, block.second ? block.second : ast}); + } break; } } } else if (isa(bb->parent)) { + if (!blocks_id_map.count(bb->id)) + continue; + if_stmt::Ptr if_stmt_copy = std::make_shared(); if_stmt_copy->then_stmt = to(std::make_shared()); if_stmt_copy->else_stmt = to(std::make_shared()); - if_stmt_copy->cond = to(bb->parent)->cond; - std::cerr << bb->id << " if\n"; - if (condition_block == bb) { - if (to(to(bb->parent)->then_stmt)->stmts.size() == 0 && to(to(bb->parent)->else_stmt)->stmts.size() != 0) { - not_expr::Ptr neg_cond = std::make_shared(); - neg_cond->static_offset = if_stmt_copy->cond->static_offset; - neg_cond->expr1 = if_stmt_copy->cond; - while_block->cond = neg_cond; - std::cerr << "neg if\n"; + while_block->cond = to(bb->parent)->cond; + + if (to(to(bb->parent)->then_stmt)->stmts.size() == 0) { + not_expr::Ptr negated_cond = std::make_shared(); + negated_cond->static_offset = while_block->cond->static_offset; + negated_cond->expr1 = while_block->cond; + + if (bb->else_branch) { + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->else_branch, to(while_block->body)}); + visited.insert(bb->else_branch); + } + + if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { + std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); + } } else { - while_block->cond = if_stmt_copy->cond; + if (bb->then_branch) { + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->then_branch, to(while_block->body)}); + visited.insert(bb->then_branch); + } + + if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { + std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); + } } } else { - if_stmt_copy->then_stmt = to(bb->parent)->then_stmt; - if_stmt_copy->else_stmt = to(bb->parent)->else_stmt; - - for (auto stmt: to(if_stmt_copy->then_stmt)->stmts) { - visited_blocks.insert(stmt); - ast_parent_map.insert({stmt, {to(if_stmt_copy->then_stmt), -1}}); - } + if_stmt_copy->cond = to(bb->parent)->cond; - for (auto stmt: to(if_stmt_copy->else_stmt)->stmts) { - visited_blocks.insert(stmt); - ast_parent_map.insert({stmt, {to(if_stmt_copy->else_stmt), -1}}); + if (bb->then_branch) { + std::cerr << "non-cond if then\n"; + ast_parent_map_loop[to(if_stmt_copy->then_stmt)] = ast; + worklist.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); + visited.insert(bb->then_branch); } - visited_blocks.insert(if_stmt_copy); - to(while_block->body)->stmts.push_back(if_stmt_copy); - } - - unsigned int index = to(while_block->body)->stmts.size() - 1; - ast_parent_map.insert({to(if_stmt_copy), {to(while_block->body), index}}); - ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); - } - else if (subloops.size() != 0) { - bool skip_block = false; - for (auto subloop: subloops) { - if (subloop->blocks_id_map.count(bb->id)) { - skip_block = true; - std::cerr << "skipped\n"; - break; + if (bb->else_branch) { + std::cerr << "non-cond if else\n"; + ast_parent_map_loop[to(if_stmt_copy->else_stmt)] = ast; + worklist.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); + visited.insert(bb->else_branch); } + ast->stmts.push_back(to(if_stmt_copy)); } - - if (skip_block) - continue; - } - else if (isa(bb->parent)) { - to(while_block->body)->stmts.push_back(bb->parent); - unsigned int index = to(while_block->body)->stmts.size() - 1; - visited_blocks.insert(bb->parent); - ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); - } - else if (isa(bb->parent)) { - to(while_block->body)->stmts.push_back(bb->parent); - unsigned int index = to(while_block->body)->stmts.size() - 1; - visited_blocks.insert(bb->parent); - ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); } else if (isa(bb->parent)) { - to(while_block->body)->stmts.push_back(bb->parent); - unsigned int index = to(while_block->body)->stmts.size() - 1; - visited_blocks.insert(bb->parent); - ast_parent_map.insert({bb->parent, {to(while_block->body), index}}); - } - } - - // manage loop exits - for (auto exit_bb: loop_exit_blocks) { - if (!unique_exit_block) - continue; + if (to(bb->parent)->label1 == to(header_block->parent)->label1) { + bool is_last_block = false; + + if (dta_.get_preorder_bb_map()[bb->id] == (int)dta_.get_preorder().size() - 1) { + is_last_block = true; + } + else { + // TODO: this can be cleaned up or reduced. + int next_preorder = dta_.get_preorder_bb_map()[bb->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[bb->id] + 1] : -1; + int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - int target_branch = -1; + if (blocks_id_map.count(next_preorder)) + is_last_block = false; + else { + if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) + is_last_block = true; + else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) + is_last_block = true; + else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) + is_last_block = true; + else + is_last_block = false; + } + } - if (!isa(exit_bb->parent)) - assert(0 && "loop exit block must be an if_stmt"); - - if (exit_bb->then_branch && !blocks_id_map.count(exit_bb->then_branch->id)) - target_branch = 0; - else if (exit_bb->else_branch && !blocks_id_map.count(exit_bb->else_branch->id)) - target_branch = 1; - - if (target_branch == -1) - assert(0 && "one of the branches of if should have the exiting block"); - - if (ast_parent_map.count(exit_bb->parent)) { - std::cerr << "inside parent map\n"; - auto temp = ast_parent_map[exit_bb->parent]; - std::cerr << temp.second << "\n"; - std::cerr << temp.first->stmts.size() << "\n"; - std::vector &temp_ast = to(temp.second == -1 ? temp.first : to(temp.first->stmts[temp.second])->then_stmt)->stmts; - std::cerr << "ast size: " << temp_ast.size() << "\n"; - - std::shared_ptr exiting_bb = target_branch ? exit_bb->else_branch : exit_bb->then_branch; - std::cerr << exiting_bb->id << "\n"; - unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id] + 1; - unsigned int unique_exit_index = dta_.get_preorder_bb_map()[unique_exit_block->id]; - std::cerr << preorder_index << " " << unique_exit_index << "\n"; - - for (;preorder_index < unique_exit_index; preorder_index++) { - std::shared_ptr exiting_bb = dta_.cfg_[dta_.get_preorder()[preorder_index]]; - if (!exiting_bb->is_exit_block) { - visited_blocks.insert(exiting_bb->parent); - temp_ast.push_back(exiting_bb->parent); + if (!is_last_block) { + ast->stmts.push_back(to(std::make_shared())); + // TODO: also insert in continue stmt vector in while_stmt } + visited.insert(bb); + } + else { + ast->stmts.push_back(to(std::make_shared())); + visited.insert(bb); } - std::cerr << preorder_index << " " << unique_exit_index << "\n"; - if (preorder_index == unique_exit_index) - temp_ast.push_back(std::make_shared()); - - // if (preorder_index == unique_exit_index + 1) - // temp_ast.push_back(std::make_shared()); } else { - std::cerr << "not inside parent map\n"; - } - } + assert(bb->successor.size() <= 1); + bool exit_bb_succ = false; + if (bb->is_exit_block) { + for (auto exit: loop_exit_blocks) { + for (auto pred: bb->predecessor) { + if (pred->id == exit->id && bb->successor.size()) { + return_blocks.push_back({bb->successor[0], ast}); + std::cerr << "found return block " << bb->successor[0]->id << "\n"; + exit_bb_succ = true; + break; + } + } - // manage loop latches - for (auto latch: loop_latch_blocks) { - if (ast_parent_map.count(latch->parent)) { - visited_blocks.insert(latch->parent); - std::cerr << "inside latch map\n"; - auto temp = ast_parent_map[latch->parent]; - std::cerr << temp.second << "\n"; - std::cerr << temp.first->stmts.size() << "\n"; - std::vector &temp_ast = temp.first->stmts; - std::cerr << "ast size: " << temp_ast.size() << "\n"; - - bool is_last_block = false; - // bool is_latch_in_other_loop = false; - - if (dta_.get_preorder_bb_map()[latch->id] == (int)dta_.get_preorder().size() - 1) { - is_last_block = true; + if (exit_bb_succ) + break; + } + + if (exit_bb_succ) + continue; } - else { - int next_preorder = dta_.get_preorder_bb_map()[latch->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[latch->id] + 1] : -1; - int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - if (blocks_id_map.count(next_preorder)) - is_last_block = false; + if (!bb->is_exit_block && !isa(bb->parent)) { + std::cerr << "bb: " << bb->id << "\n"; + ast->dump(std::cerr, 0); + ast->stmts.push_back(to(bb->parent)); + } + + if (bb->successor.size()) { + if (visited.count(bb->successor[0])) + continue; + else + visited.insert(bb->successor[0]); + + if (bb->is_exit_block) { + worklist.push_back({bb->successor[0], ast_parent_map_loop[ast]}); + } else { - if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) - is_last_block = true; - else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) - is_last_block = true; - else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) - is_last_block = true; - else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) - is_last_block = true; - else - is_last_block = false; + worklist.push_back({bb->successor[0], ast}); } } - - // if (latch->ast_to_basic_block_map.count(loop_latch_ast)) { - // std::cerr << "break in latch: " << latch->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; - // auto bb = latch->ast_to_basic_block_map.at(loop_latch_ast); - // for (auto subloop: loop->subloops) { - // if (subloop->blocks_id_map.count(bb->id)) - // is_latch_in_other_loop = true; - // } - // } - - temp_ast.pop_back(); - if (!is_last_block) { - while_block->continue_blocks.push_back(temp.first); - temp_ast.push_back(std::make_shared()); - } } } + // manage loop exits + // for (auto exit_bb: loop_exit_blocks) { + // if (!unique_exit_block) + // continue; + + // int target_branch = -1; + + // if (!isa(exit_bb->parent)) + // assert(0 && "loop exit block must be an if_stmt"); + + // if (exit_bb->then_branch && !blocks_id_map.count(exit_bb->then_branch->id)) + // target_branch = 0; + // else if (exit_bb->else_branch && !blocks_id_map.count(exit_bb->else_branch->id)) + // target_branch = 1; + + // if (target_branch == -1) + // assert(0 && "one of the branches of if should have the exiting block"); + + // if (ast_parent_map.count(exit_bb->parent)) { + // std::cerr << "inside parent map\n"; + // auto temp = ast_parent_map[exit_bb->parent]; + // std::cerr << temp.second << "\n"; + // std::cerr << temp.first->stmts.size() << "\n"; + // std::vector &temp_ast = to(temp.second == -1 ? temp.first : to(temp.first->stmts[temp.second])->then_stmt)->stmts; + // std::cerr << "ast size: " << temp_ast.size() << "\n"; + + // std::shared_ptr exiting_bb = target_branch ? exit_bb->else_branch : exit_bb->then_branch; + // std::cerr << exiting_bb->id << "\n"; + // unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id] + 1; + // unsigned int unique_exit_index = dta_.get_preorder_bb_map()[unique_exit_block->id]; + // std::cerr << preorder_index << " " << unique_exit_index << "\n"; + + // for (;preorder_index < unique_exit_index; preorder_index++) { + // std::shared_ptr exiting_bb = dta_.cfg_[dta_.get_preorder()[preorder_index]]; + // if (!exiting_bb->is_exit_block) { + // visited_blocks.insert(exiting_bb->parent); + // temp_ast.push_back(exiting_bb->parent); + // } + // } + // std::cerr << preorder_index << " " << unique_exit_index << "\n"; + // if (preorder_index == unique_exit_index) + // temp_ast.push_back(std::make_shared()); + + // // if (preorder_index == unique_exit_index + 1) + // // temp_ast.push_back(std::make_shared()); + // } + // else { + // std::cerr << "not inside parent map\n"; + // } + // } + + // manage loop latches + // for (auto latch: loop_latch_blocks) { + // if (ast_parent_map.count(latch->parent)) { + // visited_blocks.insert(latch->parent); + // std::cerr << "inside latch map\n"; + // auto temp = ast_parent_map[latch->parent]; + // std::cerr << temp.second << "\n"; + // std::cerr << temp.first->stmts.size() << "\n"; + // std::vector &temp_ast = temp.first->stmts; + // std::cerr << "ast size: " << temp_ast.size() << "\n"; + + // bool is_last_block = false; + // // bool is_latch_in_other_loop = false; + + // if (dta_.get_preorder_bb_map()[latch->id] == (int)dta_.get_preorder().size() - 1) { + // is_last_block = true; + // } + // else { + // int next_preorder = dta_.get_preorder_bb_map()[latch->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[latch->id] + 1] : -1; + // int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; + + // if (blocks_id_map.count(next_preorder)) + // is_last_block = false; + // else { + // if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) + // is_last_block = true; + // else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) + // is_last_block = true; + // else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) + // is_last_block = true; + // else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) + // is_last_block = true; + // else + // is_last_block = false; + // } + // } + + // // if (latch->ast_to_basic_block_map.count(loop_latch_ast)) { + // // std::cerr << "break in latch: " << latch->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; + // // auto bb = latch->ast_to_basic_block_map.at(loop_latch_ast); + // // for (auto subloop: loop->subloops) { + // // if (subloop->blocks_id_map.count(bb->id)) + // // is_latch_in_other_loop = true; + // // } + // // } + + // temp_ast.pop_back(); + // if (!is_last_block) { + // while_block->continue_blocks.push_back(temp.first); + // temp_ast.push_back(std::make_shared()); + // } + // } + // } + return to(while_block); } @@ -719,8 +530,14 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { if (isa(bb->parent)) { for (auto loop : top_level_loops) { if (loop->header_block->parent == bb->parent) { - ast->stmts.push_back(loop->convert_to_ast_impl(dta)); - std::cerr << "found loop\n"; + std::cerr << "found outerloop\n"; + + std::vector, stmt_block::Ptr>> loop_out_blocks; + ast->stmts.push_back(loop->convert_to_ast_impl(dta, loop_out_blocks)); + + for (auto block: loop_out_blocks) { + worklist.push_back({block.first, block.second ? block.second : ast}); + } break; } } @@ -730,9 +547,6 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { if (bb_loop_map.count(bb->id)) continue; - if (visited_blocks.count(bb->parent)) - continue; - if_stmt::Ptr if_stmt_copy = std::make_shared(); if_stmt_copy->then_stmt = to(std::make_shared()); if_stmt_copy->else_stmt = to(std::make_shared()); @@ -758,14 +572,13 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { if (bb_loop_map.count(bb->id)) continue; - - if (visited_blocks.count(bb->parent)) - continue; // what is happening is that when we see a if stmt exit block we should // reduce the level of the tree, it is not being done now. - if (!bb->is_exit_block && !isa(bb->parent)) + if (!bb->is_exit_block && !isa(bb->parent)) { + std::cerr << "out bb: " << bb->id << "\n"; ast->stmts.push_back(to(bb->parent)); + } if (bb->successor.size()) { if (visited.count(bb->successor[0])) diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 77f2b0f..b5cabb2 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -498,15 +498,15 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "++++++ loop info ++++++ \n"; - // return ast; std::cerr << "++++++ convert to ast ++++++ \n"; ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; - + // block::loop_finder finder; // finder.ast = ast; // ast->accept(&finder); + // return ast; block::for_loop_finder for_finder; for_finder.ast = ast; From 489d5115e0d6eb177b2f295765a59e8722bcffc7 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:18:38 +0530 Subject: [PATCH 17/24] WIP v4: able to generate loop exit breaks as well --- src/blocks/loops.cpp | 52 +++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 0222787..283bde2 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -281,25 +281,17 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorelse_branch, to(while_block->body)}); visited.insert(bb->else_branch); } - - if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { - std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; - worklist.push_back({bb->successor[1], nullptr}); - visited.insert(bb->successor[1]); - } } - else { - if (bb->then_branch) { - ast_parent_map_loop[to(while_block->body)] = ast; - worklist.push_back({bb->then_branch, to(while_block->body)}); - visited.insert(bb->then_branch); - } + else if (bb->then_branch) { + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->then_branch, to(while_block->body)}); + visited.insert(bb->then_branch); + } - if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { - std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; - worklist.push_back({bb->successor[1], nullptr}); - visited.insert(bb->successor[1]); - } + if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { + std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); } } else { @@ -318,6 +310,13 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorelse_branch, to(if_stmt_copy->else_stmt)}); visited.insert(bb->else_branch); } + + if ((!bb->then_branch || !bb->else_branch) && bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { + std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); + } + ast->stmts.push_back(to(if_stmt_copy)); } } @@ -351,7 +350,7 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorstmts.push_back(to(std::make_shared())); - // TODO: also insert in continue stmt vector in while_stmt + while_block->continue_blocks.push_back(ast); } visited.insert(bb); } @@ -364,6 +363,11 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorsuccessor.size() <= 1); bool exit_bb_succ = false; if (bb->is_exit_block) { + for (auto subloop: subloops) { + if (bb == subloop->unique_exit_block) { + ast->stmts.push_back(to(std::make_shared())); + } + } for (auto exit: loop_exit_blocks) { for (auto pred: bb->predecessor) { if (pred->id == exit->id && bb->successor.size()) { @@ -380,6 +384,10 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorid] != (int)dta_.get_preorder().size() - 1) { + ast->stmts.push_back(to(std::make_shared())); + } } if (!bb->is_exit_block && !isa(bb->parent)) { @@ -570,6 +578,14 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { else { assert(bb->successor.size() <= 1); + if (bb->is_exit_block) { + for (auto loop: loops) { + if (bb == loop->unique_exit_block) { + ast->stmts.push_back(to(std::make_shared())); + } + } + } + if (bb_loop_map.count(bb->id)) continue; From 90b4aa420a9c31827d83a278c450eea0c72bf73f Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Fri, 29 Sep 2023 01:47:00 +0530 Subject: [PATCH 18/24] WIP v5: generates clean and correct code for all testcases --- src/blocks/loops.cpp | 78 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 283bde2..d2a35eb 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -257,6 +257,8 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorcond = to(bb->parent)->cond; if (to(to(bb->parent)->then_stmt)->stmts.size() == 0) { + std::cerr << "negated if cond\n"; not_expr::Ptr negated_cond = std::make_shared(); negated_cond->static_offset = while_block->cond->static_offset; negated_cond->expr1 = while_block->cond; + while_block->cond = negated_cond; if (bb->else_branch) { ast_parent_map_loop[to(while_block->body)] = ast; worklist.push_back({bb->else_branch, to(while_block->body)}); visited.insert(bb->else_branch); } + + if (!blocks_id_map.count(bb->successor[1]->id) && blocks_id_map.count(bb->successor[0]->id)) { + std::cerr << "inserting out of loop block (1): " << bb->successor[0]->id << bb->successor[1]->is_exit_block << "\n"; + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); + } + else { + std::cerr << "inserting out of loop block (0): " << bb->successor[0]->id << bb->successor[0]->is_exit_block << "\n"; + worklist.push_back({bb->successor[0], nullptr}); + visited.insert(bb->successor[0]); + } } - else if (bb->then_branch) { - ast_parent_map_loop[to(while_block->body)] = ast; - worklist.push_back({bb->then_branch, to(while_block->body)}); - visited.insert(bb->then_branch); - } + else { + if (bb->then_branch && blocks_id_map.count(bb->then_branch->id)) { + std::cerr << "loop cond then branch: " << bb->then_branch->id << "\n"; + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->then_branch, to(while_block->body)}); + visited.insert(bb->then_branch); + + // if (!blocks_id_map.count(bb->successor[1]->id)) { + // std::cerr << "pushing out of loop branch (1) out: " << bb->successor[1]->id << "\n"; + // worklist.push_back({bb->successor[1], ast_parent_map_loop[to(while_block->body)]}); + // visited.insert(bb->successor[1]); + // } + } + else if (bb->else_branch && blocks_id_map.count(bb->else_branch->id)) { + not_expr::Ptr negated_cond = std::make_shared(); + negated_cond->static_offset = while_block->cond->static_offset; + negated_cond->expr1 = while_block->cond; + while_block->cond = negated_cond; - if (bb->successor.size() == 2 && bb->successor[1]->is_exit_block) { - std::cerr << "inserting out of loop block" << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; - worklist.push_back({bb->successor[1], nullptr}); - visited.insert(bb->successor[1]); + std::cerr << "loop cond else branch: " << bb->else_branch->id << "\n"; + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->else_branch, to(while_block->body)}); + visited.insert(bb->else_branch); + + // if (!blocks_id_map.count(bb->successor[0]->id)) { + // std::cerr << "pushing out of loop branch (0) out: " << bb->successor[0]->id << "\n"; + // worklist.push_back({bb->successor[0], ast_parent_map_loop[to(while_block->body)]}); + // visited.insert(bb->successor[0]); + // } + } + + if (blocks_id_map.count(bb->successor[1]->id) && !blocks_id_map.count(bb->successor[0]->id)) { + std::cerr << "inserting out of loop block (0): " << bb->successor[0]->id << bb->successor[0]->is_exit_block << "\n"; + ast_parent_map_loop[to(while_block->body)] = ast; + worklist.push_back({bb->successor[0], ast_parent_map_loop[to(while_block->body)]}); + visited.insert(bb->successor[0]); + } + else { + std::cerr << "inserting out of loop block (1): " << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; + worklist.push_back({bb->successor[1], nullptr}); + visited.insert(bb->successor[1]); + } } } else { @@ -362,7 +410,8 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorsuccessor.size() <= 1); bool exit_bb_succ = false; - if (bb->is_exit_block) { + + if (bb->is_exit_block && !blocks_id_map.count(bb->id)) { for (auto subloop: subloops) { if (bb == subloop->unique_exit_block) { ast->stmts.push_back(to(std::make_shared())); @@ -390,6 +439,12 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorid) && !bb->is_exit_block) { + std::cerr << "case for 26: " << bb->id << worklist.size() << loop_id << "\n"; + return_blocks.push_back({bb, nullptr}); + continue; + } + if (!bb->is_exit_block && !isa(bb->parent)) { std::cerr << "bb: " << bb->id << "\n"; ast->dump(std::cerr, 0); @@ -546,6 +601,8 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto block: loop_out_blocks) { worklist.push_back({block.first, block.second ? block.second : ast}); } + std::cerr << "finish outerloop\n"; + std::cerr << worklist.size() << "\n"; break; } } @@ -581,6 +638,7 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { if (bb->is_exit_block) { for (auto loop: loops) { if (bb == loop->unique_exit_block) { + std::cerr << "inserted break: " << bb->id << "\n"; ast->stmts.push_back(to(std::make_shared())); } } From a6fee6ccb393a367e5f8f574b3cce1001f4b2201 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Fri, 29 Sep 2023 02:08:00 +0530 Subject: [PATCH 19/24] WIP v6: reduce number of redundant continue stmts, few still remain --- src/blocks/loops.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index d2a35eb..c830edd 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -383,7 +383,9 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorid)) + if (!blocks_id_map.count(next_preorder) || !blocks_id_map.count(next_next_preorder)) + is_last_block = true; + else if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) is_last_block = true; else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) is_last_block = true; @@ -397,6 +399,7 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorid << loop_id << "\n"; ast->stmts.push_back(to(std::make_shared())); while_block->continue_blocks.push_back(ast); } From 98359b45e1cd51d354da450a0af7756c0a6bf414 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sat, 30 Sep 2023 01:06:18 +0530 Subject: [PATCH 20/24] WIP --- src/blocks/loops.cpp | 4 +++- src/builder/builder_context.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index c830edd..aaa7aca 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -380,7 +380,9 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorid] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[bb->id] + 1] : -1; int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - if (blocks_id_map.count(next_preorder)) + if (loop_latch_blocks.size() == 1) + is_last_block = true; + else if (blocks_id_map.count(next_preorder)) is_last_block = false; else { if (!blocks_id_map.count(next_preorder) || !blocks_id_map.count(next_next_preorder)) diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index b5cabb2..d40865d 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -500,13 +500,13 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ loop info ++++++ \n"; std::cerr << "++++++ convert to ast ++++++ \n"; - ast = LI.convert_to_ast(block::to(ast)); + // ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; - // block::loop_finder finder; - // finder.ast = ast; - // ast->accept(&finder); - // return ast; + block::loop_finder finder; + finder.ast = ast; + ast->accept(&finder); + return ast; block::for_loop_finder for_finder; for_finder.ast = ast; From 7eeed4459e9b166bc47ec17aa91547f8efdf472d Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:17:29 +0530 Subject: [PATCH 21/24] Now postdom can also handle infinite loops --- include/blocks/dominance.h | 8 ++-- src/blocks/dominance.cpp | 67 +++++++++++++++++++++++---------- src/blocks/loops.cpp | 6 +++ src/builder/builder_context.cpp | 15 +++++--- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/include/blocks/dominance.h b/include/blocks/dominance.h index 9dfa598..85cd44e 100644 --- a/include/blocks/dominance.h +++ b/include/blocks/dominance.h @@ -20,6 +20,8 @@ class dominator_analysis { dominator_analysis(basic_block::cfg_block cfg, bool is_postdom = false); basic_block::cfg_block cfg_; bool is_postdom_; + int max_depth; + unsigned int max_depth_bb_id; std::vector &get_postorder_bb_map(); std::vector &get_postorder(); std::vector &get_preorder_bb_map(); @@ -44,10 +46,10 @@ class dominator_analysis { std::vector preorder_bb_map; void reverse_cfg(); void postorder_idom_helper(std::vector &visited, int id); - void postorder_dfs_helper(std::vector &visited_bbs, int id); - void postorder_dfs(); + void postorder_dfs_helper(std::vector &visited_bbs, int id, int depth); + void postorder_dfs(bool reverse_cfg); void preorder_dfs_helper(std::vector &visited_bbs, int id); - void preorder_dfs(); + void preorder_dfs(bool reverse_cfg); int intersect(int bb1_id, int bb2_id); }; diff --git a/src/blocks/dominance.cpp b/src/blocks/dominance.cpp index 234767c..d24630e 100644 --- a/src/blocks/dominance.cpp +++ b/src/blocks/dominance.cpp @@ -8,9 +8,6 @@ void dominator_analysis::reverse_cfg() { assert(0); std::shared_ptr virtual_exit_bb = std::make_shared("virtualexit0"); - virtual_exit_bb->id = cfg_.size(); - cfg_.push_back(virtual_exit_bb); - for (auto bb: cfg_) { if (bb->successor.size() == 0) { bb->successor.push_back(virtual_exit_bb); @@ -18,6 +15,21 @@ void dominator_analysis::reverse_cfg() { } } + // if CFG is an inifite loop, we don't have a exit block + // so we need to find the farthest block from the entry + // of the loop and consider that as one of the exit blocks + if (!virtual_exit_bb->predecessor.size()) { + std::cerr << "infinite loop\n"; + postorder_dfs(false); + + auto bb_virtual_backedge = cfg_[max_depth_bb_id]; + bb_virtual_backedge->successor.push_back(virtual_exit_bb); + virtual_exit_bb->predecessor.push_back(bb_virtual_backedge); + } + + virtual_exit_bb->id = cfg_.size(); + cfg_.push_back(virtual_exit_bb); + for (auto bb: cfg_) { basic_block::cfg_block temp_pred = bb->predecessor; bb->predecessor.clear(); @@ -35,12 +47,17 @@ dominator_analysis::dominator_analysis(basic_block::cfg_block cfg, bool is_postd } // TODO: Add a check for size, it should be greater than 2. + idom.clear(); idom.reserve(cfg_.size()); idom.assign(cfg_.size(), -1); + postorder.clear(); postorder.reserve(cfg_.size()); + postorder_bb_map.clear(); postorder_bb_map.reserve(cfg_.size()); postorder_bb_map.assign(cfg_.size(), -1); + preorder.clear(); preorder.reserve(cfg_.size()); + preorder_bb_map.clear(); preorder_bb_map.reserve(cfg_.size()); preorder_bb_map.assign(cfg_.size(), -1); @@ -58,30 +75,40 @@ void dominator_analysis::postorder_idom_helper(std::vector &visited, int i } } -void dominator_analysis::postorder_dfs_helper(std::vector &visited_bbs, int id) { - for (auto child: cfg_[id]->successor) { - if (!visited_bbs[child->id]) { - visited_bbs[child->id] = true; - postorder_dfs_helper(visited_bbs, child->id); - postorder.push_back(child->id); - } +void dominator_analysis::postorder_dfs_helper(std::vector &visited_bbs, int id, int depth) { + if (depth > max_depth) { + max_depth = depth; + max_depth_bb_id = id; + } + + for (auto child: cfg_[id]->successor) { + if (!visited_bbs[child->id]) { + visited_bbs[child->id] = true; + postorder_dfs_helper(visited_bbs, child->id, depth + 1); + postorder.push_back(child->id); } + } } -void dominator_analysis::postorder_dfs() { +void dominator_analysis::postorder_dfs(bool reverse_cfg) { + int current_depth = 0; + max_depth = current_depth; + std::vector visited_bbs(cfg_.size()); visited_bbs.assign(visited_bbs.size(), false); - if (is_postdom_) + if (reverse_cfg) visited_bbs[cfg_.size() - 1] = true; else visited_bbs[0] = true; - if (is_postdom_) { - postorder_dfs_helper(visited_bbs, cfg_.size() - 1); + if (reverse_cfg) { + max_depth_bb_id = cfg_.size() - 1; + postorder_dfs_helper(visited_bbs, cfg_.size() - 1, current_depth + 1); postorder.push_back(cfg_.size() - 1); } else { - postorder_dfs_helper(visited_bbs, 0); + max_depth_bb_id = 0; + postorder_dfs_helper(visited_bbs, 0, current_depth + 1); postorder.push_back(0); } } @@ -96,15 +123,15 @@ void dominator_analysis::preorder_dfs_helper(std::vector &visited_bbs, int } } -void dominator_analysis::preorder_dfs() { +void dominator_analysis::preorder_dfs(bool reverse_cfg) { std::vector visited_bbs(cfg_.size()); visited_bbs.assign(visited_bbs.size(), false); - if (is_postdom_) + if (reverse_cfg) visited_bbs[cfg_.size() - 1] = true; else visited_bbs[0] = true; - if (is_postdom_) { + if (reverse_cfg) { preorder.push_back(cfg_.size() - 1); preorder_dfs_helper(visited_bbs, cfg_.size() - 1); } @@ -200,8 +227,8 @@ int dominator_analysis::intersect(int bb1_id, int bb2_id) { } void dominator_analysis::analyze() { - preorder_dfs(); - postorder_dfs(); + preorder_dfs(is_postdom_); + postorder_dfs(is_postdom_); for (unsigned int i = 0; i < preorder.size(); i++) { preorder_bb_map[preorder[i]] = i; } diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index aaa7aca..7294ed3 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -184,6 +184,9 @@ void loop_info::analyze() { continue; int unique_postdom = post_dta.get_idom(loop->loop_exit_blocks[0]->id); + if (unique_postdom == -1) + continue; + bool unique_postdom_flag = true; for (auto exit_bb: loop->loop_exit_blocks) { if (post_dta.get_idom(exit_bb->id) != unique_postdom) { @@ -270,6 +273,8 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vector(); if_stmt_copy->then_stmt = to(std::make_shared()); if_stmt_copy->else_stmt = to(std::make_shared()); + if_stmt_copy->annotation = to(bb->parent)->annotation; + if (condition_block == bb) { while_block->cond = to(bb->parent)->cond; @@ -621,6 +626,7 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { if_stmt_copy->then_stmt = to(std::make_shared()); if_stmt_copy->else_stmt = to(std::make_shared()); if_stmt_copy->cond = to(bb->parent)->cond; + if_stmt_copy->annotation = to(bb->parent)->annotation; // push the then branch onto worklist. (worklist should be a pair ) ? if (bb->then_branch) { diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index d40865d..66274ac 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -303,6 +303,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { block::eliminate_redundant_vars(ast); } + // return ast; if (feature_unstructured) return ast; @@ -334,6 +335,8 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { dominator_analysis dom(BBs); dominator_analysis post_dom(post_BBs, true); + std::cerr << "max depth: " << dom.max_depth << "\n"; + std::cerr << "max depth bb id: " << dom.max_depth_bb_id << "\n"; std::cerr << "== postorder map ==\n"; for (int i: dom.get_postorder_bb_map()) { std::cerr << i << "\n"; @@ -391,6 +394,8 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { } std::cerr << "== postorder idom ==\n"; + std::cerr << "(postdom) max depth: " << post_dom.max_depth << "\n"; + std::cerr << "(postdom) max depth bb id: " << post_dom.max_depth_bb_id << "\n"; std::cerr << "== (postdom) postorder map ==\n"; for (int i: post_dom.get_postorder_bb_map()) { std::cerr << i << "\n"; @@ -500,13 +505,13 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ loop info ++++++ \n"; std::cerr << "++++++ convert to ast ++++++ \n"; - // ast = LI.convert_to_ast(block::to(ast)); + ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; - block::loop_finder finder; - finder.ast = ast; - ast->accept(&finder); - return ast; + // block::loop_finder finder; + // finder.ast = ast; + // ast->accept(&finder); + // return ast; block::for_loop_finder for_finder; for_finder.ast = ast; From 390a79bca59e6ab79a4e070072d577e91fa3887a Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sat, 30 Sep 2023 20:46:10 +0530 Subject: [PATCH 22/24] Improved handling of unconditional loops --- src/blocks/loops.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 7294ed3..736ced0 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -152,17 +152,6 @@ void loop_info::analyze() { } } - // Populate loop condition block - for(auto loop: loops) { - if (!loop->header_block) - continue; - - std::shared_ptr header = loop->header_block; - assert(header->successor.size() == 1 && "loop header cannot have more than one successor"); - if (isa(header->successor[0]->parent)) - loop->condition_block = header->successor[0]; - } - // Populate the loop exits for (auto loop: loops) { if (!loop->header_block) @@ -198,6 +187,22 @@ void loop_info::analyze() { loop->unique_exit_block = dta.cfg_[unique_postdom]; } + // Populate loop condition block + for(auto loop: loops) { + if (!loop->header_block) + continue; + + // this might be an unconditional loop or + // infinite loop. + if (loop->loop_exit_blocks.empty()) + continue; + + std::shared_ptr header = loop->header_block; + assert(header->successor.size() == 1 && "loop header cannot have more than one successor"); + if (isa(header->successor[0]->parent)) + loop->condition_block = header->successor[0]; + } + // Assign id to the loops for (unsigned int i = 0; i < loops.size(); i++) { loops[i]->loop_id = i; @@ -297,7 +302,7 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorsuccessor[1], nullptr}); visited.insert(bb->successor[1]); } - else { + else if (blocks_id_map.count(bb->successor[1]->id) && !blocks_id_map.count(bb->successor[0]->id)){ std::cerr << "inserting out of loop block (0): " << bb->successor[0]->id << bb->successor[0]->is_exit_block << "\n"; worklist.push_back({bb->successor[0], nullptr}); visited.insert(bb->successor[0]); @@ -316,7 +321,8 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorsuccessor[1]); // } } - else if (bb->else_branch && blocks_id_map.count(bb->else_branch->id)) { + + if (bb->else_branch && blocks_id_map.count(bb->else_branch->id)) { not_expr::Ptr negated_cond = std::make_shared(); negated_cond->static_offset = while_block->cond->static_offset; negated_cond->expr1 = while_block->cond; @@ -340,7 +346,7 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorsuccessor[0], ast_parent_map_loop[to(while_block->body)]}); visited.insert(bb->successor[0]); } - else { + else if (!blocks_id_map.count(bb->successor[1]->id) && blocks_id_map.count(bb->successor[0]->id)) { std::cerr << "inserting out of loop block (1): " << bb->successor[1]->id << bb->successor[1]->is_exit_block << "\n"; worklist.push_back({bb->successor[1], nullptr}); visited.insert(bb->successor[1]); From 7f69c8167566902ecff82a26d41cb5d6092411ef Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:56:03 +0530 Subject: [PATCH 23/24] Fix bugs and emit guards for latches that cut through and go to loop headers that are not immediate parent --- include/blocks/loops.h | 4 +- src/blocks/basic_blocks.cpp | 4 +- src/blocks/loops.cpp | 743 ++++++-------------------------- src/builder/builder_context.cpp | 9 +- 4 files changed, 145 insertions(+), 615 deletions(-) diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 0751167..3981881 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -7,10 +7,11 @@ #include using namespace block; +class loop_info; class loop { public: loop(std::shared_ptr header): header_block(header) {} - stmt::Ptr convert_to_ast_impl(dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks); + stmt::Ptr convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks, stmt::Ptr &jump_condition_def, stmt::Ptr &jump_condition_block); struct loop_bounds_ { stmt::Ptr ind_var; @@ -33,6 +34,7 @@ class loop { basic_block::cfg_block loop_latch_blocks; basic_block::cfg_block loop_exit_blocks; std::vector> subloops; + while_stmt::Ptr structured_ast_loop; }; class loop_info { diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp index 66f863f..139e720 100644 --- a/src/blocks/basic_blocks.cpp +++ b/src/blocks/basic_blocks.cpp @@ -96,7 +96,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { work_list.pop_front(); // push the exit block to the work_list work_list.push_front(exit_bb); - + std::cerr << "inside if handler: " << bb->name << "\n"; // if there is a then_stmt, create a basic block for it if (to(if_stmt_->then_stmt)->stmts.size() != 0) { auto then_bb = std::make_shared(std::to_string(++basic_block_count)); @@ -112,6 +112,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { bb->then_branch = then_bb; // push the block to the work_list, to expand it further work_list.push_front(then_bb); + std::cerr << "inside then" << "\n"; } // if there is a else_stmt, create a basic block for it if (to(if_stmt_->else_stmt)->stmts.size() != 0) { @@ -128,6 +129,7 @@ basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) { bb->else_branch = else_bb; // push the block to the work_list, to expand it further work_list.insert(work_list.begin() + 1, else_bb); + std::cerr << "inside else" << "\n"; } // if there is no then/else block, then have the exit block as successor as well. diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index 736ced0..a38589f 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -235,9 +235,12 @@ void loop_info::analyze() { std::set visited_blocks; std::map ast_parent_map_loop; -stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks) { +// std::map, while_stmt::Ptr> return_blocks_parent_loop; +int jump_condition_counter = 0; +stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks, stmt::Ptr &jump_condition_def, stmt::Ptr &jump_condition_block) { while_stmt::Ptr while_block = std::make_shared(); while_block->body = std::make_shared(); + structured_ast_loop = while_block; if (!condition_block) { while_block->cond = std::make_shared(); @@ -260,9 +263,11 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorheader_block->parent == bb->parent) { std::cerr << "found subloop\n"; std::vector, stmt_block::Ptr>> loop_out_blocks; - ast->stmts.push_back(subloop->convert_to_ast_impl(dta_, loop_out_blocks)); + stmt::Ptr jump_def, jump_block; + ast->stmts.push_back(subloop->convert_to_ast_impl(li, dta_, loop_out_blocks, jump_def, jump_block)); for (auto block: loop_out_blocks) { + // return_blocks_parent_loop.insert({block.first, to(ast->stmts.back())}); worklist.push_back({block.first, block.second ? block.second : ast}); } std::cerr << "finish subloop\n"; @@ -355,18 +360,30 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorcond = to(bb->parent)->cond; + bb->parent->dump(std::cerr, 0); + std::cerr << bb->successor[0]->id << " " << bb->successor[1]->id << "\n"; if (bb->then_branch) { - std::cerr << "non-cond if then\n"; + std::cerr << "non-cond if then: " << bb->id << "\n"; ast_parent_map_loop[to(if_stmt_copy->then_stmt)] = ast; - worklist.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); + if (!blocks_id_map.count(bb->then_branch->id) && !bb->then_branch->is_exit_block) { + return_blocks.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); + } + else { + worklist.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); + } visited.insert(bb->then_branch); } if (bb->else_branch) { - std::cerr << "non-cond if else\n"; + std::cerr << "non-cond if else: " << bb->id <<"\n"; ast_parent_map_loop[to(if_stmt_copy->else_stmt)] = ast; - worklist.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); + if (!blocks_id_map.count(bb->else_branch->id) && !bb->else_branch->is_exit_block) { + return_blocks.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); + } + else { + worklist.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); + } visited.insert(bb->else_branch); } @@ -382,7 +399,8 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vector(bb->parent)) { if (to(bb->parent)->label1 == to(header_block->parent)->label1) { bool is_last_block = false; - + bool is_goto_to_outerloop = false; + bb->parent->dump(std::cerr, 0); if (dta_.get_preorder_bb_map()[bb->id] == (int)dta_.get_preorder().size() - 1) { is_last_block = true; } @@ -411,17 +429,118 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vectorast_depth - 2 > (int)header_block->ast_depth) { + // figure out the parent while loop for this basic block + auto target_bb = bb->successor[0]; + auto pointer_bb = bb; + std::vector> loop_parent_tree; + do { + std::cerr << "iter: " << pointer_bb->id << "\n"; + + if (pointer_bb->predecessor.size() > 1) { + auto min_preorder_pred = std::min_element(pointer_bb->predecessor.begin(), pointer_bb->predecessor.end(), + [&dta_](std::shared_ptr bb1, std::shared_ptr bb2) { + return dta_.get_preorder_bb_map()[bb1->id] < dta_.get_preorder_bb_map()[bb2->id]; + }); + if (min_preorder_pred != pointer_bb->predecessor.end()) { + pointer_bb = *min_preorder_pred; + } + } + else { + pointer_bb = pointer_bb->predecessor[0]; + } + + for (auto loop: li.loops) { + if (loop->header_block == pointer_bb) { + loop_parent_tree.push_back(loop); + break; + } + } + } while (target_bb != pointer_bb); + + for (auto loops : loop_parent_tree) { + std::cerr << loops->header_block->id << "\n"; + } + + while_stmt::Ptr jump_target_loop = loop_parent_tree.back()->structured_ast_loop; + while_stmt::Ptr guard_target_loop = (*(loop_parent_tree.rbegin() + 1))->structured_ast_loop; + + std::cerr << "handingling break cond\n"; + is_goto_to_outerloop = true; + + auto jump_cond_def = std::make_shared(); + jump_cond_def->var_name = "control_guard" + std::to_string(jump_condition_counter++); + + auto scalar_type1 = std::make_shared(); + jump_cond_def->var_type = scalar_type1; + scalar_type1->scalar_type_id = scalar_type::INT_TYPE; + + auto var_expr1 = std::make_shared(); + var_expr1->var1 = jump_cond_def; + + auto const_expr1 = std::make_shared(); + const_expr1->value = 1; + const_expr1->is_64bit = false; + + auto assign_expr1 = std::make_shared(); + assign_expr1->var1 = var_expr1; + assign_expr1->expr1 = const_expr1; + + auto jump_expr = std::make_shared(); + jump_expr->expr1 = assign_expr1; + + ast->stmts.push_back(jump_expr); + + auto var_expr2 = std::make_shared(); + var_expr2->var1 = jump_cond_def; + + auto const_expr2 = std::make_shared(); + const_expr2->value = 0; + const_expr2->is_64bit = false; + + auto assign_expr2 = std::make_shared(); + assign_expr2->var1 = var_expr2; + assign_expr2->expr1 = const_expr2; + + auto expr_stmt2 = std::make_shared(); + expr_stmt2->expr1 = assign_expr2; + + // guard decl stmt + auto var_decl1 = std::make_shared(); + var_decl1->decl_var = jump_cond_def; + var_decl1->init_expr = const_expr2; + + auto while_body = to(while_block->body); + while_body->stmts.insert(while_body->stmts.begin(), var_decl1); + + // guard if stmt + auto if_stmt1 = std::make_shared(); + if_stmt1->else_stmt = std::make_shared(); + auto stmt_block1 = std::make_shared(); + if_stmt1->then_stmt = stmt_block1; + stmt_block1->stmts.push_back(std::make_shared()); + + auto var_expr3 = std::make_shared(); + var_expr3->var1 = jump_cond_def; + if_stmt1->cond = var_expr3; + + auto guard_while_body = to(guard_target_loop->body); + auto jump_while_body = to(jump_target_loop->body); + + guard_while_body->stmts.insert(guard_while_body->stmts.begin(), to(expr_stmt2)); + + auto guard_decl_insertion_point = std::find(jump_while_body->stmts.begin(), jump_while_body->stmts.end(), to(guard_target_loop)); + if (guard_decl_insertion_point != jump_while_body->stmts.end()) { + jump_while_body->stmts.insert(guard_decl_insertion_point + 1, to(if_stmt1)); + } + } if (!is_last_block) { std::cerr << "inserted continue: " << bb->id << loop_id << "\n"; - ast->stmts.push_back(to(std::make_shared())); + ast->stmts.push_back(is_goto_to_outerloop ? to(std::make_shared()) : to(std::make_shared())); while_block->continue_blocks.push_back(ast); } visited.insert(bb); } - else { - ast->stmts.push_back(to(std::make_shared())); - visited.insert(bb); - } } else { assert(bb->successor.size() <= 1); @@ -483,111 +602,6 @@ stmt::Ptr loop::convert_to_ast_impl(dominator_analysis &dta_, std::vector(exit_bb->parent)) - // assert(0 && "loop exit block must be an if_stmt"); - - // if (exit_bb->then_branch && !blocks_id_map.count(exit_bb->then_branch->id)) - // target_branch = 0; - // else if (exit_bb->else_branch && !blocks_id_map.count(exit_bb->else_branch->id)) - // target_branch = 1; - - // if (target_branch == -1) - // assert(0 && "one of the branches of if should have the exiting block"); - - // if (ast_parent_map.count(exit_bb->parent)) { - // std::cerr << "inside parent map\n"; - // auto temp = ast_parent_map[exit_bb->parent]; - // std::cerr << temp.second << "\n"; - // std::cerr << temp.first->stmts.size() << "\n"; - // std::vector &temp_ast = to(temp.second == -1 ? temp.first : to(temp.first->stmts[temp.second])->then_stmt)->stmts; - // std::cerr << "ast size: " << temp_ast.size() << "\n"; - - // std::shared_ptr exiting_bb = target_branch ? exit_bb->else_branch : exit_bb->then_branch; - // std::cerr << exiting_bb->id << "\n"; - // unsigned int preorder_index = dta_.get_preorder_bb_map()[exiting_bb->id] + 1; - // unsigned int unique_exit_index = dta_.get_preorder_bb_map()[unique_exit_block->id]; - // std::cerr << preorder_index << " " << unique_exit_index << "\n"; - - // for (;preorder_index < unique_exit_index; preorder_index++) { - // std::shared_ptr exiting_bb = dta_.cfg_[dta_.get_preorder()[preorder_index]]; - // if (!exiting_bb->is_exit_block) { - // visited_blocks.insert(exiting_bb->parent); - // temp_ast.push_back(exiting_bb->parent); - // } - // } - // std::cerr << preorder_index << " " << unique_exit_index << "\n"; - // if (preorder_index == unique_exit_index) - // temp_ast.push_back(std::make_shared()); - - // // if (preorder_index == unique_exit_index + 1) - // // temp_ast.push_back(std::make_shared()); - // } - // else { - // std::cerr << "not inside parent map\n"; - // } - // } - - // manage loop latches - // for (auto latch: loop_latch_blocks) { - // if (ast_parent_map.count(latch->parent)) { - // visited_blocks.insert(latch->parent); - // std::cerr << "inside latch map\n"; - // auto temp = ast_parent_map[latch->parent]; - // std::cerr << temp.second << "\n"; - // std::cerr << temp.first->stmts.size() << "\n"; - // std::vector &temp_ast = temp.first->stmts; - // std::cerr << "ast size: " << temp_ast.size() << "\n"; - - // bool is_last_block = false; - // // bool is_latch_in_other_loop = false; - - // if (dta_.get_preorder_bb_map()[latch->id] == (int)dta_.get_preorder().size() - 1) { - // is_last_block = true; - // } - // else { - // int next_preorder = dta_.get_preorder_bb_map()[latch->id] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[latch->id] + 1] : -1; - // int next_next_preorder = dta_.get_preorder_bb_map()[next_preorder] + 1 < (int)dta_.get_preorder().size() ? dta_.get_preorder()[dta_.get_preorder_bb_map()[next_preorder] + 1] : -1; - - // if (blocks_id_map.count(next_preorder)) - // is_last_block = false; - // else { - // if (unique_exit_block && (next_preorder == (int)unique_exit_block->id)) - // is_last_block = true; - // else if (unique_exit_block && (next_next_preorder == (int)unique_exit_block->id)) - // is_last_block = true; - // else if (next_preorder != -1 && next_next_preorder == -1 && dta_.cfg_[next_preorder]->is_exit_block) - // is_last_block = true; - // else if (next_preorder != -1 && next_next_preorder != -1 && dta_.cfg_[next_preorder]->is_exit_block && isa(dta_.cfg_[next_next_preorder]->parent)) - // is_last_block = true; - // else - // is_last_block = false; - // } - // } - - // // if (latch->ast_to_basic_block_map.count(loop_latch_ast)) { - // // std::cerr << "break in latch: " << latch->ast_to_basic_block_map.at(loop_latch_ast)->id << "\n"; - // // auto bb = latch->ast_to_basic_block_map.at(loop_latch_ast); - // // for (auto subloop: loop->subloops) { - // // if (subloop->blocks_id_map.count(bb->id)) - // // is_latch_in_other_loop = true; - // // } - // // } - - // temp_ast.pop_back(); - // if (!is_last_block) { - // while_block->continue_blocks.push_back(temp.first); - // temp_ast.push_back(std::make_shared()); - // } - // } - // } - return to(while_block); } @@ -610,9 +624,10 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto loop : top_level_loops) { if (loop->header_block->parent == bb->parent) { std::cerr << "found outerloop\n"; - + stmt::Ptr jump_def, jump_block; std::vector, stmt_block::Ptr>> loop_out_blocks; - ast->stmts.push_back(loop->convert_to_ast_impl(dta, loop_out_blocks)); + ast->stmts.push_back(loop->convert_to_ast_impl(*this, dta, loop_out_blocks, jump_def, jump_block)); + loop->structured_ast_loop = to(ast->stmts.back()); for (auto block: loop_out_blocks) { worklist.push_back({block.first, block.second ? block.second : ast}); @@ -684,496 +699,6 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { } } } - // // iterate using preorder bb - // // use stack for current parent block - // std::stack parent_stack; - // parent_stack.push(to(return_ast)); - - // for (unsigned int i = 0; i < dta.get_preorder().size(); i++) { - // auto bb = dta.cfg_[dta.get_preorder()[i]]; - - // std::cerr << "bb: " << bb->id << "\n"; - // if (isa(bb->parent)) { - // std::cerr << "inside label block\n"; - - // for (auto loop: top_level_loops) { - // if (loop->header_block->parent == bb->parent) { - // to(parent_stack.top())->stmts.push_back(loop->convert_to_ast_impl(dta)); - // break; - // } - // } - // } - // else if (isa(bb->parent)) { - // std::cerr << "inside if block\n"; - - // if (bb_loop_map.count(bb->id)) - // continue; - // std::cerr << "inside if block (exit 1)\n"; - - // if (visited_blocks.count(bb->parent)) - // continue; - // std::cerr << "inside if block (exit 2)\n"; - - // if (dta.get_preorder().size() <= i + 1) - // continue; - // std::cerr << "inside if block (exit 3)\n"; - - // if_stmt::Ptr if_stmt_copy = std::make_shared(); - // if_stmt_copy->then_stmt = to(std::make_shared()); - // if_stmt_copy->else_stmt = to(std::make_shared()); - // if_stmt_copy->cond = to(bb->parent)->cond; - - // int next_block = -1; - // if (dta.get_preorder()[i + 1] == (int)bb->then_branch->id) - // next_block = 0; - // else if (dta.get_preorder()[i + 1] == (int)bb->else_branch->id) - // next_block = 1; - - // assert(next_block != -1); - - // to(parent_stack.top())->stmts.push_back(if_stmt_copy); - // if (next_block == 0) { - // parent_stack.push(to(if_stmt_copy->then_stmt)); - // } - // else if (next_block == 1) { - // parent_stack.push(to(if_stmt_copy->else_stmt)); - // } - - // } - // else if (bb->is_exit_block) { - // std::cerr << "inside exit block\n"; - - // if (bb_loop_map.count(bb->id)) - // continue; - // std::cerr << "inside exit block (exit 1)\n"; - - // if (visited_blocks.count(bb->parent)) - // continue; - - // parent_stack.pop(); - // } - // else { - // std::cerr << "inside default block\n"; - - // if (bb_loop_map.count(bb->id)) - // continue; - // std::cerr << "inside default block (exit 1)\n"; - - // if (visited_blocks.count(bb->parent)) - // continue; - // std::cerr << "inside default block (exit 2)\n"; - - // to(parent_stack.top())->stmts.push_back(bb->parent); - // } - // } - - // for (auto bb: dta.cfg_) { - // std::cerr << bb->id << " " << bb_loop_map.count(bb->id) << " " << visited_blocks.count(bb->parent) << " " << bb->is_exit_block << "\n"; - // if (isa(bb->parent)) { - // std::cerr << "inside label block\n"; - // for (auto loop: top_level_loops) { - // if (loop->header_block->parent == bb->parent) { - // if (ast_parent_map_global.count(bb->parent)) { - // ast_parent_map_global[bb->parent]->stmts.push_back(loop->convert_to_ast_impl(dta)); - // } - // else { - // return_ast->stmts.push_back(loop->convert_to_ast_impl(dta)); - // } - // } - // } - // } - // else if (!bb_loop_map.count(bb->id) && !visited_blocks.count(bb->parent) && !bb->is_exit_block) { - // std::cerr << "inside if block\n"; - // stmt::Ptr push_block = bb->parent; - - // if (isa(bb->parent)) { - // if_stmt::Ptr if_stmt_copy = std::make_shared(); - // if_stmt_copy->then_stmt = to(std::make_shared()); - // if_stmt_copy->else_stmt = to(std::make_shared()); - // if_stmt_copy->cond = to(bb->parent)->cond; - // push_block = to(if_stmt_copy); - - // for (auto stmt: to(to(bb->parent)->then_stmt)->stmts) { - // if (!isa(stmt)) { - // std::cerr << "ifstmt\n"; - // visited_blocks.insert(stmt); - // to(if_stmt_copy->then_stmt)->stmts.push_back(stmt); - // } - // ast_parent_map_global.insert({stmt, to(if_stmt_copy->then_stmt)}); - // } - // for (auto stmt: to(to(bb->parent)->else_stmt)->stmts) { - // if (!isa(stmt)) { - // std::cerr << "elsestmt\n"; - // visited_blocks.insert(stmt); - // to(if_stmt_copy->else_stmt)->stmts.push_back(stmt); - // } - // ast_parent_map_global.insert({stmt, to(if_stmt_copy->else_stmt)}); - // } - // } - // else if (isa(bb->parent)) { - // continue; - // } - - // visited_blocks.insert(bb->parent); - // return_ast->stmts.push_back(push_block); - // } - // } return return_ast; - -// std::cerr << "before ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "before ast\n"; - - // for (auto loop_map: preorder_loops_map) { - // for (auto preorder: loop_map.second) { - // replace_loop_exits(loops[preorder], ast, dta); - // replace_loop_latches(loops[preorder], ast, dta); - // } - // } - - // std::cerr << "after ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "after ast\n"; - - // return ast; - - - // std::cerr << "before ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "before ast\n"; - // block::stmt::Ptr loop_header_ast = get_loop_block(loops[postorder]->header_block, ast); - // std::cerr << loops[postorder]->header_block->ast_index << "\n"; - // loop_header_ast->dump(std::cerr, 0); - // while_stmt::Ptr while_block = std::make_shared(); - // while_block->body = std::make_shared(); - // while_block->cond = std::make_shared(); - // to(while_block->cond)->value = 1; - // if (isa(loop_header_ast)) { - // loop_header_ast = to(loop_header_ast)->body; - // } - - // if (isa(loop_header_ast)) { - // unsigned int ast_index = loops[postorder]->header_block->ast_index; - // // handle unconditional loops - // if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(to(loop_header_ast)->stmts[ast_index + 1])) { - // for (auto bb: loops[postorder]->blocks) { - // to(while_block->body)->stmts.push_back(bb->parent); - // } - // // pop loop backedge - // to(while_block->body)->stmts.pop_back(); - - // // set always true condition - // while_block->cond = std::make_shared(); - // to(while_block->cond)->value = 1; - - // // unconditional loops can have only one backedge !? - // assert(loops[postorder]->loop_latch_blocks.size() == 1); - // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - // std::cerr << i << "\n"; - // worklist.push_back(std::make_tuple(i, std::ref(to(loop_header_ast)->stmts), nullptr)); - // } - - // worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); - // } - // else if (to(loop_header_ast)->stmts[ast_index] == loops[postorder]->header_block->parent) { - // stmt_block::Ptr then_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->then_stmt); - // stmt_block::Ptr else_block = to(to(to(loop_header_ast)->stmts[ast_index + 1])->else_stmt); - // std::cerr << "stmt block\n"; - - // // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; - // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - // while_block->cond = to(to(loop_header_ast)->stmts[ast_index + 1])->cond; - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - - // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // if (backedge_iter != backedge_blocks.end()) { - // std::cerr << "replaced BE\n"; - // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // } - // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // // if (else_block->stmts.size() != 0) - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - // // // else { - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // to(loop_header_ast)->stmts.push_back(stmt); - // // // } - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // to(loop_header_ast)->stmts.push_back(stmt); - // // } - // // else { - // // for (auto body_stmt: then_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - // // if block to be replaced with while block - // worklist.push_back(std::make_tuple(ast_index, std::ref(to(loop_header_ast)->stmts), to(while_block))); - // } - // } - // else if (isa(loop_header_ast)) { - // unsigned int ast_index = loops[postorder]->header_block->ast_index; - // stmt_block::Ptr if_then_block = to(to(loop_header_ast)->then_stmt); - // stmt_block::Ptr if_else_block = to(to(loop_header_ast)->else_stmt); - - // if (if_then_block->stmts.size() != 0) { - // std::cerr << "if then block\n"; - // // handle unconditional loops - // if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_then_block->stmts[ast_index + 1])) { - // for (auto bb: loops[postorder]->blocks) { - // to(while_block->body)->stmts.push_back(bb->parent); - // } - // // pop loop backedge - // to(while_block->body)->stmts.pop_back(); - - // // set always true condition - // while_block->cond = std::make_shared(); - // to(while_block->cond)->value = 1; - - // // unconditional loops can have only one backedge !? - // assert(loops[postorder]->loop_latch_blocks.size() == 1); - // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - // worklist.push_back(std::make_tuple(i, std::ref(if_then_block->stmts), nullptr)); - // } - - // worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); - // } - // else if (if_then_block->stmts[ast_index] == loops[postorder]->header_block->parent) { - // stmt_block::Ptr then_block = to(to(if_then_block->stmts[ast_index + 1])->then_stmt); - // stmt_block::Ptr else_block = to(to(if_then_block->stmts[ast_index + 1])->else_stmt); - - // // while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; - // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - // while_block->cond = to(if_then_block->stmts[ast_index + 1])->cond; - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - - // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // if (backedge_iter != backedge_blocks.end()) { - // std::cerr << "replaced BE\n"; - // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // } - // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // if_then_block->stmts.push_back(stmt); - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // if_then_block->stmts.push_back(stmt); - // // } - // // else { - // // for (auto body_stmt: then_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - // // if block to be replaced with while block - // worklist.push_back(std::make_tuple(ast_index, std::ref(if_then_block->stmts), to(while_block))); - // } - // } - - // if (if_else_block->stmts.size() != 0) { - // std::cerr << "if else block\n"; - // // handle unconditional loops - // if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent && !isa(if_else_block->stmts[ast_index + 1])) { - // for (auto bb: loops[postorder]->blocks) { - // to(while_block->body)->stmts.push_back(bb->parent); - // } - // // pop loop backedge - // to(while_block->body)->stmts.pop_back(); - - // // set always true condition - // while_block->cond = std::make_shared(); - // to(while_block->cond)->value = 1; - - // // unconditional loops can have only one backedge !? - // assert(loops[postorder]->loop_latch_blocks.size() == 1); - // for (unsigned int i = ast_index + 2; i < loops[postorder]->loop_latch_blocks[0]->ast_index; i++) { - // worklist.push_back(std::make_tuple(i, std::ref(if_else_block->stmts), nullptr)); - // } - - // worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); - // } - // else if (if_else_block->stmts[ast_index] == loops[postorder]->header_block->parent) { - // stmt_block::Ptr then_block = to(to(if_else_block->stmts[ast_index + 1])->then_stmt); - // stmt_block::Ptr else_block = to(to(if_else_block->stmts[ast_index + 1])->else_stmt); - - // // while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; - // if (then_block->stmts.size() == 0 && else_block->stmts.size() != 0) { - // while_block->cond = to(if_else_block->stmts[ast_index + 1])->cond; - // not_expr::Ptr new_cond = std::make_shared(); - // new_cond->static_offset = while_block->cond->static_offset; - // new_cond->expr1 = while_block->cond; - // while_block->cond = new_cond; - - // for (auto body_stmt: else_block->stmts) { - // to(while_block->body)->stmts.push_back(body_stmt); - // } - - // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // if (backedge_iter != backedge_blocks.end()) { - // std::cerr << "replaced BE\n"; - // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // } - // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // if_else_block->stmts.push_back(stmt); - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), else_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - // // else if (then_block->stmts.size() == 1 && isa(then_block->stmts.back())) { - // // not_expr::Ptr new_cond = std::make_shared(); - // // new_cond->static_offset = while_block->cond->static_offset; - // // new_cond->expr1 = while_block->cond; - // // while_block->cond = new_cond; - - // // then_block->stmts.pop_back(); - // // for (auto stmt: then_block->stmts) - // // if_else_block->stmts.push_back(stmt); - // // } - // // else { - // // for (auto body_stmt: then_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - - // // auto backedge_iter = std::find(backedge_blocks.begin(), backedge_blocks.end(), then_block); - // // if (backedge_iter != backedge_blocks.end()) { - // // std::cerr << "replaced BE\n"; - // // std::replace(backedge_blocks.begin(), backedge_blocks.end(), *backedge_iter, to(while_block->body)); - // // } - // // while_block->continue_blocks.insert(while_block->continue_blocks.begin(), backedge_blocks.begin(), backedge_blocks.end()); - // // } - - // // for (auto body_stmt: else_block->stmts) { - // // to(while_block->body)->stmts.push_back(body_stmt); - // // } - // // if block to be replaced with while block - // worklist.push_back(std::make_tuple(ast_index, std::ref(if_else_block->stmts), to(while_block))); - // } - // } - // } - - // // process worklist - // std::sort(worklist.begin(), worklist.end(), [](std::tuple>, stmt::Ptr> a, std::tuple>, stmt::Ptr> b) { - // return std::get<0>(a) > std::get<0>(b); - // }); - // for (auto item : worklist) { - // std::vector &temp_ast = std::get<1>(item); - // if (std::get<2>(item)) { - // std::replace(temp_ast.begin(), temp_ast.end(), temp_ast[std::get<0>(item) + 1], std::get<2>(item)); - // temp_ast.erase(temp_ast.begin() + std::get<0>(item)); - // } - // } - - // for (auto item : worklist) { - // std::vector &temp_ast = std::get<1>(item); - // if (!std::get<2>(item)) { - // temp_ast.erase(temp_ast.begin() + std::get<0>(item)); - // } - // } - // worklist.clear(); - - // std::cerr << "after ast\n"; - // ast->dump(std::cerr, 0); - // std::cerr << "after ast\n"; } diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index 66274ac..c26cadb 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -365,8 +365,8 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "get_idom(int) test: get_idom(0): " << dom.get_idom(0) << "\n"; std::cerr << "get_idom(int) test: get_idom(-1): " << dom.get_idom(-1) << "\n"; - for (int i: dom.get_idom()) { - std::cerr << i << "\n"; + for (unsigned int i = 0; i < dom.get_idom().size(); i++) { + std::cerr << i << " : " << dom.get_idom()[i] << "\n"; } std::cerr << "== idom ==\n"; @@ -424,8 +424,8 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "get_idom(int) test: get_idom(0): " << post_dom.get_idom(0) << "\n"; std::cerr << "get_idom(int) test: get_idom(-1): " << post_dom.get_idom(-1) << "\n"; - for (int i: post_dom.get_idom()) { - std::cerr << i << "\n"; + for (unsigned int i = 0; i < post_dom.get_idom().size(); i++) { + std::cerr << i << " : " << post_dom.get_idom()[i] << "\n"; } std::cerr << "== (postdom) idom ==\n"; @@ -504,6 +504,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ loop info ++++++ \n"; + // return ast; std::cerr << "++++++ convert to ast ++++++ \n"; ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; From 863b433894d1d7bee28284931efe0b2a88d949a4 Mon Sep 17 00:00:00 2001 From: Vedant Paranjape <22630228+VedantParanjape@users.noreply.github.com> Date: Sun, 28 Jan 2024 21:33:45 +0530 Subject: [PATCH 24/24] Added support for emitting multiple guard blocks for goto that cut through more than 2 loops --- include/blocks/loops.h | 2 +- src/blocks/loops.cpp | 243 +++++++++++++++++++++++--------- src/builder/builder_context.cpp | 2 - 3 files changed, 174 insertions(+), 73 deletions(-) diff --git a/include/blocks/loops.h b/include/blocks/loops.h index 3981881..2149f5f 100644 --- a/include/blocks/loops.h +++ b/include/blocks/loops.h @@ -11,7 +11,7 @@ class loop_info; class loop { public: loop(std::shared_ptr header): header_block(header) {} - stmt::Ptr convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks, stmt::Ptr &jump_condition_def, stmt::Ptr &jump_condition_block); + stmt::Ptr convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks); struct loop_bounds_ { stmt::Ptr ind_var; diff --git a/src/blocks/loops.cpp b/src/blocks/loops.cpp index a38589f..d7762f9 100644 --- a/src/blocks/loops.cpp +++ b/src/blocks/loops.cpp @@ -237,7 +237,7 @@ std::set visited_blocks; std::map ast_parent_map_loop; // std::map, while_stmt::Ptr> return_blocks_parent_loop; int jump_condition_counter = 0; -stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks, stmt::Ptr &jump_condition_def, stmt::Ptr &jump_condition_block) { +stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std::vector, stmt_block::Ptr>> &return_blocks) { while_stmt::Ptr while_block = std::make_shared(); while_block->body = std::make_shared(); structured_ast_loop = while_block; @@ -263,8 +263,7 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std if (subloop->header_block->parent == bb->parent) { std::cerr << "found subloop\n"; std::vector, stmt_block::Ptr>> loop_out_blocks; - stmt::Ptr jump_def, jump_block; - ast->stmts.push_back(subloop->convert_to_ast_impl(li, dta_, loop_out_blocks, jump_def, jump_block)); + ast->stmts.push_back(subloop->convert_to_ast_impl(li, dta_, loop_out_blocks)); for (auto block: loop_out_blocks) { // return_blocks_parent_loop.insert({block.first, to(ast->stmts.back())}); @@ -364,7 +363,9 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std std::cerr << bb->successor[0]->id << " " << bb->successor[1]->id << "\n"; if (bb->then_branch) { - std::cerr << "non-cond if then: " << bb->id << "\n"; + std::cerr << "non-cond if then: " << bb->id << " " << bb->then_branch->id << "\n"; + bb->then_branch->parent->dump(std::cerr, 0); + to(if_stmt_copy->then_stmt)->dump(std::cerr, 0); ast_parent_map_loop[to(if_stmt_copy->then_stmt)] = ast; if (!blocks_id_map.count(bb->then_branch->id) && !bb->then_branch->is_exit_block) { return_blocks.push_back({bb->then_branch, to(if_stmt_copy->then_stmt)}); @@ -376,7 +377,9 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std } if (bb->else_branch) { - std::cerr << "non-cond if else: " << bb->id <<"\n"; + std::cerr << "non-cond if else: " << bb->id << " " << bb->else_branch->id <<"\n"; + bb->else_branch->parent->dump(std::cerr, 0); + to(if_stmt_copy->else_stmt)->dump(std::cerr, 0); ast_parent_map_loop[to(if_stmt_copy->else_stmt)] = ast; if (!blocks_id_map.count(bb->else_branch->id) && !bb->else_branch->is_exit_block) { return_blocks.push_back({bb->else_branch, to(if_stmt_copy->else_stmt)}); @@ -400,6 +403,10 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std if (to(bb->parent)->label1 == to(header_block->parent)->label1) { bool is_last_block = false; bool is_goto_to_outerloop = false; + std::cerr << "goto handler\n"; + std::cerr << "ast dump\n"; + ast->dump(std::cerr, 0); + std::cerr << "bb dump\n"; bb->parent->dump(std::cerr, 0); if (dta_.get_preorder_bb_map()[bb->id] == (int)dta_.get_preorder().size() - 1) { is_last_block = true; @@ -434,6 +441,7 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std auto target_bb = bb->successor[0]; auto pointer_bb = bb; std::vector> loop_parent_tree; + std::vector> mixed_walkback_tree; do { std::cerr << "iter: " << pointer_bb->id << "\n"; @@ -450,89 +458,178 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std pointer_bb = pointer_bb->predecessor[0]; } + // runtime can be optimized if we create a hashmap for (header_block->id => loop) map + // also a map for (conditional_block->id => loop) for (auto loop: li.loops) { + if (isa(pointer_bb->parent) && mixed_walkback_tree.size() == 0) { + bool skip_if_stmt = false; + for (auto iloop: li.loops) { + if (iloop->condition_block->id == pointer_bb->id) { + skip_if_stmt = true; + break; + } + } + if (skip_if_stmt) + continue; + + std::cerr << "looping back from a if statement\n"; + mixed_walkback_tree.push_back(pointer_bb); + } + if (loop->header_block == pointer_bb) { loop_parent_tree.push_back(loop); + mixed_walkback_tree.push_back(loop->header_block); break; } } } while (target_bb != pointer_bb); + std::cerr << "loop parent tree\n"; for (auto loops : loop_parent_tree) { std::cerr << loops->header_block->id << "\n"; } - while_stmt::Ptr jump_target_loop = loop_parent_tree.back()->structured_ast_loop; - while_stmt::Ptr guard_target_loop = (*(loop_parent_tree.rbegin() + 1))->structured_ast_loop; - - std::cerr << "handingling break cond\n"; - is_goto_to_outerloop = true; - - auto jump_cond_def = std::make_shared(); - jump_cond_def->var_name = "control_guard" + std::to_string(jump_condition_counter++); - - auto scalar_type1 = std::make_shared(); - jump_cond_def->var_type = scalar_type1; - scalar_type1->scalar_type_id = scalar_type::INT_TYPE; - - auto var_expr1 = std::make_shared(); - var_expr1->var1 = jump_cond_def; - - auto const_expr1 = std::make_shared(); - const_expr1->value = 1; - const_expr1->is_64bit = false; - - auto assign_expr1 = std::make_shared(); - assign_expr1->var1 = var_expr1; - assign_expr1->expr1 = const_expr1; - - auto jump_expr = std::make_shared(); - jump_expr->expr1 = assign_expr1; - - ast->stmts.push_back(jump_expr); - - auto var_expr2 = std::make_shared(); - var_expr2->var1 = jump_cond_def; - - auto const_expr2 = std::make_shared(); - const_expr2->value = 0; - const_expr2->is_64bit = false; - - auto assign_expr2 = std::make_shared(); - assign_expr2->var1 = var_expr2; - assign_expr2->expr1 = const_expr2; + std::cerr << "mixed walkback tree\n"; + for (auto bb: mixed_walkback_tree) { + std::cerr << bb->id << "\n"; + } - auto expr_stmt2 = std::make_shared(); - expr_stmt2->expr1 = assign_expr2; + bool use_mixed_tree = false; + if (isa(mixed_walkback_tree[0]->parent) && mixed_walkback_tree.size() > loop_parent_tree.size()) + use_mixed_tree = true; + + // generate guard variable definitions + std::cerr << "creating guard variable definitions\n"; + std::vector> guard_variables; + std::vector> guard_variable_defs; + for (unsigned i = 0; i < loop_parent_tree.size() - 2 + (unsigned)use_mixed_tree; i++) { + // create the var and set it's attributes + auto guard_variable = std::make_shared(); + guard_variable->var_name = "control_guard" + std::to_string(jump_condition_counter++); + guard_variable->var_type = std::make_shared(); + to(guard_variable->var_type)->scalar_type_id = scalar_type::INT_TYPE; + + // create a constant equal to 0 + auto int_constant_zero = std::make_shared(); + int_constant_zero->value = 0; + int_constant_zero->is_64bit = false; + + // create the variable declaration statement + auto guard_variable_declaration = std::make_shared(); + guard_variable_declaration->decl_var = guard_variable; + guard_variable_declaration->init_expr = int_constant_zero; + + guard_variables.push_back(guard_variable); + guard_variable_defs.push_back(guard_variable_declaration); + guard_variable_declaration->dump(std::cerr, 0); + } - // guard decl stmt - auto var_decl1 = std::make_shared(); - var_decl1->decl_var = jump_cond_def; - var_decl1->init_expr = const_expr2; + std::cerr << "creating guard variable assign statements\n"; + std::vector, std::shared_ptr>> set_guard_variable_exprs; + for (auto guard_var: guard_variables) { + // create a constant equal to 0 + auto int_constant_zero = std::make_shared(); + int_constant_zero->value = 0; + int_constant_zero->is_64bit = false; + + // create a constant equal to 1 + auto int_constant_one = std::make_shared(); + int_constant_one->value = 1; + int_constant_one->is_64bit = false; + + // create an expr for guard variable equal to 0 + auto guard_variable_expr_zero = std::make_shared(); + guard_variable_expr_zero->var1 = guard_var; + + // create an expr for guard variable equal to 1 + auto guard_variable_expr_one = std::make_shared(); + guard_variable_expr_one->var1 = guard_var; + + // create a guard variable assign expr for equal to 0 + auto guard_variable_assign_expr_zero = std::make_shared(); + guard_variable_assign_expr_zero->var1 = guard_variable_expr_zero; + guard_variable_assign_expr_zero->expr1 = int_constant_zero; + + // create a guard variable assign expr for equal to 1 + auto guard_variable_assign_expr_one = std::make_shared(); + guard_variable_assign_expr_one->var1 = guard_variable_expr_one; + guard_variable_assign_expr_one->expr1 = int_constant_one; + + // create the guard variable expression statement equal to 0 + auto guard_variable_expr_statement_zero = std::make_shared(); + guard_variable_expr_statement_zero->expr1 = guard_variable_assign_expr_zero; + + // create the guard variable expression statement equal to 1 + auto guard_variable_expr_statement_one = std::make_shared(); + guard_variable_expr_statement_one->expr1 = guard_variable_assign_expr_one; + + set_guard_variable_exprs.push_back({guard_variable_expr_statement_zero, guard_variable_expr_statement_one}); + guard_variable_expr_statement_zero->dump(std::cerr, 0); + guard_variable_expr_statement_one->dump(std::cerr, 0); + } - auto while_body = to(while_block->body); - while_body->stmts.insert(while_body->stmts.begin(), var_decl1); + std::cerr << "creating guard if statements\n"; + std::vector> guard_if_blocks; + for (unsigned i = 0; i < guard_variables.size(); i++) { + // create guard if statement + auto guard_if_statement = std::make_shared(); + auto guard_statement_block = std::make_shared(); + guard_if_statement->then_stmt = guard_statement_block; + guard_if_statement->else_stmt = std::make_shared(); + + // create guard if condition + auto guard_if_condition_expr = std::make_shared(); + guard_if_condition_expr->var1 = guard_variables[i]; + + // set the guard if condition + guard_if_statement->cond = guard_if_condition_expr; + + // insert set expressions inside if only if it is not the last guard block + if (guard_variables.size() >= 2 && i < guard_variables.size() - 1) + guard_statement_block->stmts.push_back(to(set_guard_variable_exprs[i + 1].second)); + + // insert break/continue inside the if statement based on the location of it + if (i < guard_variables.size() - 1) + guard_statement_block->stmts.push_back(std::make_shared()); + else + guard_statement_block->stmts.push_back(std::make_shared()); + + guard_if_blocks.push_back(guard_if_statement); + guard_if_statement->dump(std::cerr, 0); + } - // guard if stmt - auto if_stmt1 = std::make_shared(); - if_stmt1->else_stmt = std::make_shared(); - auto stmt_block1 = std::make_shared(); - if_stmt1->then_stmt = stmt_block1; - stmt_block1->stmts.push_back(std::make_shared()); + // first we need to set the innermost guard variable = 1; + ast->stmts.push_back(set_guard_variable_exprs[0].second); - auto var_expr3 = std::make_shared(); - var_expr3->var1 = jump_cond_def; - if_stmt1->cond = var_expr3; + // now we can take care of inserting other operations + // 1) insert guard variable definition + // 2) set guard variable = 0 + // 3) inser the if guard block + unsigned i = 0; + if (use_mixed_tree) { + i = 0; + } + else { + i = 1; + } + for (unsigned blocks_counter = 0; i + 1 < loop_parent_tree.size() && blocks_counter < guard_variables.size(); i++, blocks_counter++) { + while_stmt::Ptr guard_set_insertion_loop = loop_parent_tree[i]->structured_ast_loop; + while_stmt::Ptr if_block_insertion_loop = loop_parent_tree[i + 1]->structured_ast_loop; - auto guard_while_body = to(guard_target_loop->body); - auto jump_while_body = to(jump_target_loop->body); + auto guard_set_insertion_block = to(guard_set_insertion_loop->body); + auto if_block_insertion_block = to(if_block_insertion_loop->body); - guard_while_body->stmts.insert(guard_while_body->stmts.begin(), to(expr_stmt2)); + guard_set_insertion_block->stmts.insert(guard_set_insertion_block->stmts.begin(), to(set_guard_variable_exprs[blocks_counter].first)); - auto guard_decl_insertion_point = std::find(jump_while_body->stmts.begin(), jump_while_body->stmts.end(), to(guard_target_loop)); - if (guard_decl_insertion_point != jump_while_body->stmts.end()) { - jump_while_body->stmts.insert(guard_decl_insertion_point + 1, to(if_stmt1)); + auto guard_insertion_loop = std::find(if_block_insertion_block->stmts.begin(), if_block_insertion_block->stmts.end(), to(guard_set_insertion_loop)); + if (guard_insertion_loop != if_block_insertion_block->stmts.end()) { + if_block_insertion_block->stmts.insert(guard_insertion_loop + 1, to(guard_if_blocks[blocks_counter])); + if_block_insertion_block->stmts.insert(if_block_insertion_block->stmts.begin(), to(guard_variable_defs[blocks_counter])); + } } + + std::cerr << "handling break cond\n"; + is_goto_to_outerloop = true; } if (!is_last_block) { std::cerr << "inserted continue: " << bb->id << loop_id << "\n"; @@ -546,6 +643,7 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std assert(bb->successor.size() <= 1); bool exit_bb_succ = false; + std::cerr << "bb (open): " << bb->id << "\n"; if (bb->is_exit_block && !blocks_id_map.count(bb->id)) { for (auto subloop: subloops) { if (bb == subloop->unique_exit_block) { @@ -576,7 +674,13 @@ stmt::Ptr loop::convert_to_ast_impl(loop_info &li, dominator_analysis &dta_, std if (!blocks_id_map.count(bb->id) && !bb->is_exit_block) { std::cerr << "case for 26: " << bb->id << worklist.size() << loop_id << "\n"; - return_blocks.push_back({bb, nullptr}); + + if (isa(bb->successor[0]->parent) && (int)bb->ast_depth - 2 > (int)bb->successor[0]->successor[0]->ast_depth) { + return_blocks.push_back({bb, ast}); + } + else { + return_blocks.push_back({bb, nullptr}); + } continue; } @@ -624,9 +728,8 @@ block::stmt_block::Ptr loop_info::convert_to_ast(block::stmt_block::Ptr ast) { for (auto loop : top_level_loops) { if (loop->header_block->parent == bb->parent) { std::cerr << "found outerloop\n"; - stmt::Ptr jump_def, jump_block; std::vector, stmt_block::Ptr>> loop_out_blocks; - ast->stmts.push_back(loop->convert_to_ast_impl(*this, dta, loop_out_blocks, jump_def, jump_block)); + ast->stmts.push_back(loop->convert_to_ast_impl(*this, dta, loop_out_blocks)); loop->structured_ast_loop = to(ast->stmts.back()); for (auto block: loop_out_blocks) { diff --git a/src/builder/builder_context.cpp b/src/builder/builder_context.cpp index c26cadb..6762789 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -504,7 +504,6 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { std::cerr << "++++++ loop info ++++++ \n"; - // return ast; std::cerr << "++++++ convert to ast ++++++ \n"; ast = LI.convert_to_ast(block::to(ast)); std::cerr << "++++++ convert to ast ++++++ \n"; @@ -512,7 +511,6 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) { // block::loop_finder finder; // finder.ast = ast; // ast->accept(&finder); - // return ast; block::for_loop_finder for_finder; for_finder.ast = ast;