Skip to content

Commit

Permalink
Generate idom_map and add loop info pass skeleton
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
VedantParanjape committed Jul 11, 2023
1 parent 994ff9f commit 3e3518e
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 24 deletions.
8 changes: 4 additions & 4 deletions include/blocks/basic_blocks.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
#ifndef BASIC_BLOCKS_H
#define BASIC_BLOCKS_H
#include "blocks/block_visitor.h"
#include "blocks/stmt.h"
#include <vector>
#include <deque>
#include <string>

class basic_block {
public:
typedef std::vector<std::shared_ptr<basic_block>> cfg_block;
basic_block(std::string label): name(label) {};

std::vector<std::shared_ptr<basic_block>> predecessor;
std::vector<std::shared_ptr<basic_block>> successor;
cfg_block predecessor;
cfg_block successor;
block::expr::Ptr branch_expr;
block::stmt::Ptr parent;
unsigned int index;
unsigned int id;
std::string name;
};

std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_block::Ptr ast);
basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast);

#endif
15 changes: 12 additions & 3 deletions include/blocks/dominance.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,37 @@
#include "blocks/block_visitor.h"
#include "blocks/basic_blocks.h"
#include "blocks/stmt.h"
#include <map>
#include <vector>
#include <stack>
#include <string>
#include <bitset>
#include <algorithm>

class dominator_tree {
class dominator_analysis {
public:
dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg);
// struct dominator_tree_ {
// dominator_tree_(int id): bb_id(id);
// int bb_id;
// std::vector<std::shared_ptr<dominator_tree_>> child_nodes;
// } dominator_tree;
dominator_analysis(basic_block::cfg_block &cfg);
std::vector<int> &get_postorder_bb_map();
std::vector<int> &get_postorder();
std::vector<int> &get_idom();
std::map<int, std::vector<int>> &get_idom_map();
int get_idom(int bb_id);
std::vector<int> 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<int> idom;
std::map<int, std::vector<int>> idom_map;
std::vector<int> postorder;
std::vector<int> postorder_bb_map;
std::vector<std::shared_ptr<basic_block>> &cfg_;
basic_block::cfg_block &cfg_;
void postorder_dfs_helper(std::vector<bool> &visited_bbs, int id);
void postorder_dfs();
int intersect(int bb1_id, int bb2_id);
Expand Down
40 changes: 40 additions & 0 deletions include/blocks/loops.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions include/builder/builder_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/basic_blocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using namespace block;

std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_block::Ptr ast) {
basic_block::cfg_block generate_basic_blocks(block::stmt_block::Ptr ast) {
std::deque<std::shared_ptr<basic_block>> work_list;
std::vector<std::shared_ptr<basic_block>> return_list;
basic_block::cfg_block return_list;
int basic_block_count = 0;

// step 1: fill the work_list
Expand All @@ -31,7 +31,7 @@ std::vector<std::shared_ptr<basic_block>> generate_basic_blocks(block::stmt_bloc
bb->name = "stmt" + bb->name;

if (stmt_block_->stmts.size() > 0) {
std::vector<std::shared_ptr<basic_block>> 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) {
Expand Down
56 changes: 44 additions & 12 deletions src/blocks/dominance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

using namespace block;

dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_block>> &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);
Expand All @@ -14,7 +14,7 @@ dominator_tree::dominator_tree(std::vector<std::shared_ptr<basic_block>> &cfg) :
analyze();
}

void dominator_tree::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id) {
void dominator_analysis::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;
Expand All @@ -23,7 +23,7 @@ void dominator_tree::postorder_dfs_helper(std::vector<bool> &visited_bbs, int id
}
}
}
void dominator_tree::postorder_dfs() {
void dominator_analysis::postorder_dfs() {
std::vector<bool> visited_bbs(cfg_.size());
visited_bbs.assign(visited_bbs.size(), false);
visited_bbs[0] = true;
Expand All @@ -32,26 +32,39 @@ void dominator_tree::postorder_dfs() {
postorder.push_back(0);
}

std::vector<int> &dominator_tree::get_postorder_bb_map() {
std::vector<int> &dominator_analysis::get_postorder_bb_map() {
return postorder_bb_map;
}

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

std::vector<int> &dominator_tree::get_idom() {
std::vector<int> &dominator_analysis::get_idom() {
return idom;
}

int dominator_tree::get_idom(int bb_id) {
if (bb_id >= 0 && bb_id < idom.size()) {
std::map<int, std::vector<int>> &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<int> 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;
}
Expand All @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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";
// }
}
9 changes: 9 additions & 0 deletions src/blocks/loops.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "blocks/loops.h"
#include <algorithm>

void loop_info::analyze() {
std::vector<int> idom = dta.get_idom();
for (unsigned int i = 0; i < idom.size(); i++) {
std::cout << i << " : " << idom[i] << "\n";
}
}
27 changes: 25 additions & 2 deletions src/builder/builder_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ block::stmt::Ptr builder_context::extract_ast_from_function_impl(void) {
block::eliminate_redundant_vars(ast);
}

std::vector<std::shared_ptr<basic_block>> BBs = generate_basic_blocks(block::to<block::stmt_block>(ast));
basic_block::cfg_block BBs = generate_basic_blocks(block::to<block::stmt_block>(ast));

std::cerr << "++++++ basic blocks ++++++ \n";
for (auto bb: BBs) {
Expand All @@ -315,7 +315,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()) {
Expand All @@ -330,12 +330,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;

Expand Down

0 comments on commit 3e3518e

Please sign in to comment.