Skip to content

Commit

Permalink
Implement dominator_tree analysis pass
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
VedantParanjape committed Jul 11, 2023
1 parent 7590972 commit 994ff9f
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/blocks/basic_blocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
34 changes: 34 additions & 0 deletions include/blocks/dominance.h
Original file line number Diff line number Diff line change
@@ -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 <vector>
#include <stack>
#include <string>
#include <bitset>
#include <algorithm>

class dominator_tree {
public:
dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg);
std::vector<int> &get_postorder_bb_map();
std::vector<int> &get_postorder();
std::vector<int> &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<int> idom;
std::vector<int> postorder;
std::vector<int> postorder_bb_map;
std::vector<std::shared_ptr<basic_block>> &cfg_;
void postorder_dfs_helper(std::vector<bool> &visited_bbs, int id);
void postorder_dfs();
int intersect(int bb1_id, int bb2_id);
};


#endif
1 change: 1 addition & 0 deletions include/builder/builder_context.h
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
5 changes: 5 additions & 0 deletions src/blocks/basic_blocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@ std::vector<std::shared_ptr<basic_block>> 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;
}
116 changes: 116 additions & 0 deletions src/blocks/dominance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "blocks/dominance.h"

using namespace block;

dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_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);
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<bool> &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<bool> 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<int> &dominator_tree::get_postorder_bb_map() {
return postorder_bb_map;
}

std::vector<int> &dominator_tree::get_postorder() {
return postorder;
}

std::vector<int> &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<basic_block> 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);
}
24 changes: 23 additions & 1 deletion src/builder/builder_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 << ", ";
}
Expand All @@ -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;

Expand Down

0 comments on commit 994ff9f

Please sign in to comment.