fix dominance
This commit is contained in:
parent
c2e91b1e3c
commit
375a325899
@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace antlrSysY {
|
||||
|
||||
@ -161,10 +162,10 @@ public:
|
||||
std::list<BasicBlockPtr_t> successors;
|
||||
std::list<BasicBlockPtr_t> predecessors;
|
||||
|
||||
BasicBlockPtr_t idomer; // dominating node
|
||||
std::list<BasicBlockPtr_t> idom_list; // immediate dominated nodes
|
||||
std::list<BasicBlockPtr_t> dom_list; // dominated nodes
|
||||
std::list<BasicBlockPtr_t> dom_frontier;
|
||||
BasicBlockPtr_t IDOM; // dominating node
|
||||
std::unordered_set<BasicBlockPtr_t> idom_set; // immediate dominated nodes
|
||||
std::unordered_set<BasicBlockPtr_t> DOM_set; // dominated nodes
|
||||
std::unordered_set<BasicBlockPtr_t> DF_set;
|
||||
int dom_level;
|
||||
int _dom_helper_index;
|
||||
int dom_dfs_in;
|
||||
|
||||
@ -17,7 +17,7 @@ static void _bitwise_set(std::vector<bool> &op1, int l, int r, bool val) {
|
||||
|
||||
static void _gen_dom_level(BasicBlockPtr_t bb, int level) {
|
||||
bb->dom_level = level;
|
||||
for (auto succ : bb->idom_list) {
|
||||
for (auto succ : bb->idom_set) {
|
||||
_gen_dom_level(succ, level + 1);
|
||||
}
|
||||
}
|
||||
@ -30,13 +30,13 @@ void gen_dominance(FunctionPtr_t func) {
|
||||
const int N = func->bb_list.size();
|
||||
auto itr = func->bb_list.begin();
|
||||
for (auto basicblock : func->bb_list) {
|
||||
basicblock->idom_list.clear();
|
||||
basicblock->dom_list.clear();
|
||||
basicblock->idom_set.clear();
|
||||
basicblock->DOM_set.clear();
|
||||
basicblock->_dom_helper_index = bb_list.size();
|
||||
bb_list.push_back(basicblock);
|
||||
}
|
||||
std::vector<std::vector<bool>> dom(N);
|
||||
dom[0].resize(N);
|
||||
dom[0].resize(N, 0);
|
||||
dom[0][0] = 1; // Dom(0) = {0}
|
||||
// Dom(i) <- N (= {0, 1, 2,...})
|
||||
for (int i = 1; i < N; ++i) {
|
||||
@ -49,7 +49,7 @@ void gen_dominance(FunctionPtr_t func) {
|
||||
int i = 0;
|
||||
for (int i = 1; i < N; ++i) {
|
||||
auto cur_bb = bb_list[i];
|
||||
std::vector<bool> temp(true, N);
|
||||
std::vector<bool> temp(N, 1);
|
||||
// temp = {i} union (intersect Dom(j)), j in pred(i)
|
||||
for (auto pred : cur_bb->predecessors) {
|
||||
_bitwise_and(temp, dom[pred->_dom_helper_index]);
|
||||
@ -66,26 +66,26 @@ void gen_dominance(FunctionPtr_t func) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
for (int j = 0; j < N; ++j) {
|
||||
if (dom[i][j]) {
|
||||
bb_list[i]->dom_list.push_back(bb_list[j]);
|
||||
bb_list[i]->DOM_set.insert(bb_list[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// get domees and immediate domer
|
||||
for (int i = 0; i < N; ++i) {
|
||||
for (auto domer1 : bb_list[i]->dom_list) {
|
||||
for (auto domer1 : bb_list[i]->DOM_set) {
|
||||
if (domer1 == bb_list[i]) continue;
|
||||
bool flag = true;
|
||||
// if dom(i)[j] dom dom(i)[k], it cannot be the immediate domer of i
|
||||
for (auto domer2 : bb_list[i]->dom_list) {
|
||||
for (auto domer2 : bb_list[i]->DOM_set) {
|
||||
if (domer2 == bb_list[i] || domer2 == domer1) continue;
|
||||
if (std::find(domer2->dom_list.begin(), domer2->dom_list.end(), domer1) != domer2->dom_list.end()) {
|
||||
if (std::find(domer2->DOM_set.begin(), domer2->DOM_set.end(), domer1) != domer2->DOM_set.end()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
bb_list[i]->idomer = domer1;
|
||||
domer1->idom_list.push_back(bb_list[i]);
|
||||
bb_list[i]->IDOM = domer1;
|
||||
domer1->idom_set.insert(bb_list[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -109,15 +109,15 @@ void gen_dominance_frontier(FunctionPtr_t func) {
|
||||
runner <- IDOM(runner)
|
||||
*/
|
||||
for (auto bb : func->bb_list) {
|
||||
bb->dom_frontier.clear();
|
||||
bb->DF_set.clear();
|
||||
}
|
||||
for (auto n : func->bb_list) {
|
||||
if (n->predecessors.size() >= 2) {
|
||||
for (auto pred : n->predecessors) {
|
||||
auto runner = pred;
|
||||
while (runner != n->idomer) {
|
||||
runner->dom_frontier.push_back(n);
|
||||
runner = runner->idomer;
|
||||
while (runner != n->IDOM) {
|
||||
runner->DF_set.insert(n);
|
||||
runner = runner->IDOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,7 @@ void update_dfs_numbers(BasicBlockPtr_t bb, bool rst) {
|
||||
static int dfs_num;
|
||||
if (rst) dfs_num = 0;
|
||||
bb->dom_dfs_in = dfs_num++;
|
||||
for (auto child : bb->dom_list) {
|
||||
for (auto child : bb->DOM_set) {
|
||||
update_dfs_numbers(child, false);
|
||||
}
|
||||
bb->dom_dfs_out = dfs_num++;
|
||||
|
||||
@ -94,7 +94,7 @@ int main(int argc, const char **argv) {
|
||||
|
||||
std::vector<std::shared_ptr<Pass>> passes = {
|
||||
std::make_shared<PassBuildCFG>(),
|
||||
// std::make_shared<PassMem2Reg>(),
|
||||
std::make_shared<PassMem2Reg>(),
|
||||
};
|
||||
|
||||
for (auto pass : passes) {
|
||||
|
||||
@ -2,9 +2,37 @@
|
||||
#include "common.h"
|
||||
#include "llir.h"
|
||||
#include "passes.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace antlrSysY {
|
||||
|
||||
static void print_cfg_info(BasicBlockPtr_t bb) {
|
||||
std::cout << "---" << bb->name << "---\n";
|
||||
std::cout << " pred: [";
|
||||
for (auto pred : bb->predecessors) {
|
||||
std::cout << pred->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " succ: [";
|
||||
for (auto succ : bb->successors) {
|
||||
std::cout << succ->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
static void print_cfg(BasicBlockPtr_t rt, bool rst = false) {
|
||||
static std::unordered_set<BasicBlockPtr_t> vis;
|
||||
if (rst) vis.clear();
|
||||
print_cfg_info(rt);
|
||||
for (auto succ : rt->successors) {
|
||||
if (!vis.count(succ)) {
|
||||
vis.insert(succ);
|
||||
print_cfg(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) {
|
||||
pred->successors.push_back(succ);
|
||||
succ->predecessors.push_back(pred);
|
||||
@ -16,7 +44,7 @@ static void _build_cfg(const FunctionPtr_t func) {
|
||||
if (bb->inst_list.size() == 1 && Value::is<InstBranch>(bb->inst_list.front())){
|
||||
auto br = Value::as<InstBranch>(bb->inst_list.front());
|
||||
if (br->operand_list.size() == 1) {
|
||||
LOG(DEBUG) << "remove dummy jump block:" << bb->name;
|
||||
VLOG(6) << "remove dummy jump block:" << bb->name;
|
||||
for (auto &use : bb->use_list) {
|
||||
use.user->operand_list[use.op_index] = br->operand_list[0];
|
||||
br->operand_list[0]->use_list.push_back({br->operand_list[0], use.user, use.op_index});
|
||||
@ -55,6 +83,8 @@ static void _build_cfg(const FunctionPtr_t func) {
|
||||
else
|
||||
++ itr;
|
||||
}
|
||||
|
||||
print_cfg(func->bb_list.front(), true);
|
||||
}
|
||||
|
||||
void PassBuildCFG::run(const Module &module) {
|
||||
|
||||
@ -123,13 +123,57 @@ struct RenameInfo {
|
||||
std::vector<ValuePtr_t> value_list;
|
||||
};
|
||||
|
||||
static void print_dom_info(BasicBlockPtr_t bb) {
|
||||
std::cout << bb->name << ":\n";
|
||||
std::cout << " level: " << bb->dom_level << "\n";
|
||||
std::cout << " pred: [";
|
||||
for (auto pred : bb->predecessors) {
|
||||
std::cout << pred->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " succ: [";
|
||||
for (auto succ : bb->successors) {
|
||||
std::cout << succ->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " idomer: ";
|
||||
if (bb->IDOM) std::cout << bb->IDOM->name;
|
||||
else std::cout << "null";
|
||||
std::cout << "\n";
|
||||
std::cout << " dom: [";
|
||||
for (auto dom : bb->DOM_set) {
|
||||
std::cout << dom->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " idom: [";
|
||||
for (auto idom : bb->idom_set) {
|
||||
std::cout << idom->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " DF: [";
|
||||
for (auto df : bb->DF_set) {
|
||||
std::cout << df->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
static void print_dom_tree(BasicBlockPtr_t rt) {
|
||||
print_dom_info(rt);
|
||||
for (auto idom : rt->idom_set) {
|
||||
print_dom_tree(idom);
|
||||
}
|
||||
}
|
||||
|
||||
// llvm:PromoteMemoryToRegister.cpp
|
||||
// https://roife.github.io/2022/02/07/mem2reg/
|
||||
// https://github.com/Enna1/LLVM-Study-Notes/blob/master/source/ssa/SSA-Construction.rst
|
||||
static void _mem_2_reg(FunctionPtr_t func) {
|
||||
VLOG(4) << "Run mem2reg for " << func->name;
|
||||
VLOG(4) << " Gen Dominance Tree & Frontier";
|
||||
gen_dominance(func);
|
||||
gen_dominance_frontier(func);
|
||||
print_dom_tree(func->bb_list.front());
|
||||
// actually, all variable alloca is placed at block head, so we collect them first
|
||||
std::vector<InstAllocaPtr_t> alloca_list;
|
||||
std::unordered_map<InstAllocaPtr_t, int> alloca_to_id;
|
||||
@ -191,7 +235,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
while (!worklist.empty()) {
|
||||
auto bb = worklist.front();
|
||||
worklist.pop();
|
||||
for (auto frontier : bb->dom_frontier) {
|
||||
for (auto frontier : bb->DF_set) {
|
||||
auto frontier_index = bb_to_id.at(frontier);
|
||||
if (!visited[frontier_index]) {
|
||||
visited[frontier_index] = true;
|
||||
|
||||
@ -724,7 +724,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
||||
auto _lval = _scope_tab.get_name(name);
|
||||
sysy_assert(_lval.has_value());
|
||||
auto lval = _lval.value();
|
||||
VLOG(5) << "lVal found: " << lval->to_string();
|
||||
VLOG(6) << "lVal found: " << lval->to_string();
|
||||
// @retval: ConstantInt
|
||||
if (lval->type->type_tag == Type::TypeTag::IntegerType) {
|
||||
return {lval};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user