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 9714dc4..2983422 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 327ebff..c060af0 100644 --- a/src/builder/builder_context.cpp +++ b/src/builder/builder_context.cpp @@ -296,7 +296,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 << ", "; } @@ -314,6 +314,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;