fix dominance

This commit is contained in:
ridethepig 2023-05-20 13:23:09 +08:00
parent c2e91b1e3c
commit 375a325899
6 changed files with 99 additions and 24 deletions

View File

@ -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;

View File

@ -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++;

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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};