first workable Mem2Reg
This commit is contained in:
parent
5e6107a02e
commit
8a9c32e820
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug",
|
||||
"program": "${workspaceFolder}/build/sysy",
|
||||
"args": ["../sysytests/functional_2022/21_if_test2.sy", "-S", "-o", "build/21_my.ll", "-emit-llvm"],
|
||||
"args": ["../sysytests/functional_2022/21_if_test2.sy", "-S", "-o", "build/21_my.ll", "-O1", "-emit-llvm"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace antlrSysY {
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace antlrSysY {
|
||||
|
||||
@ -25,7 +25,7 @@ DEF_PTR_T(ConstantInt);
|
||||
// typedef std::tuple<ValuePtr_t, UserPtr_t, int> UseEdge_t;
|
||||
struct Use {
|
||||
ValuePtr_t value;
|
||||
User* user;
|
||||
User *user;
|
||||
unsigned op_index;
|
||||
};
|
||||
// Define, User, operand-index
|
||||
@ -66,7 +66,7 @@ public:
|
||||
panic("No applicable for IR gen");
|
||||
}
|
||||
|
||||
void u_remove_use(User* user) {
|
||||
void u_remove_use(User *user) {
|
||||
// use_list.erase(
|
||||
// std::remove_if(
|
||||
// use_list.begin(), use_list.end(), [user](const UseEdge_t &use) { return std::get<1>(use) == user; }
|
||||
@ -78,7 +78,7 @@ public:
|
||||
itr = use_list.erase(itr);
|
||||
}
|
||||
else {
|
||||
++ itr;
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,7 +101,7 @@ public:
|
||||
}
|
||||
for (auto use : use_list) {
|
||||
auto user = use.user;
|
||||
auto index = use.op_index;
|
||||
auto index = use.op_index;
|
||||
user->operand_list[index] = value;
|
||||
assert(value);
|
||||
value->use_list.push_back({value, user, index});
|
||||
@ -162,7 +162,7 @@ public:
|
||||
std::list<BasicBlockPtr_t> successors;
|
||||
std::list<BasicBlockPtr_t> predecessors;
|
||||
|
||||
BasicBlockPtr_t IDOM; // dominating node
|
||||
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;
|
||||
|
||||
@ -81,7 +81,12 @@ std::shared_ptr<InstGEP> build_InstGEP(
|
||||
BasicBlockPtr_t parent_bb
|
||||
);
|
||||
|
||||
InstPhiPtr_t build_InstPhi(TypePtr_t type, const decltype(Function::bb_list) &incoming_vals, BasicBlockPtr_t parent_bb);
|
||||
InstPhiPtr_t build_InstPhi(
|
||||
TypePtr_t type,
|
||||
const decltype(Function::bb_list) &incoming_vals,
|
||||
BasicBlockPtr_t parent_bb,
|
||||
const std::string &name
|
||||
);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
@ -228,7 +228,7 @@ scheme_ref = {
|
||||
|
||||
scheme_my = {
|
||||
"name": "my",
|
||||
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm",
|
||||
"sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1",
|
||||
"ir_asm": "llc --march=x86 --relocation-model=pic {ir} -o {asm}",
|
||||
"asm_obj": "as --32 {asm} -o {obj}",
|
||||
"obj_bin": f"clang -m32 -Ofast -fPIE {{obj}} {LIB_PATH} -o {{bin}}",
|
||||
|
||||
10
src/main.cpp
10
src/main.cpp
@ -62,11 +62,11 @@ int main(int argc, const char **argv) {
|
||||
#pragma region Logger
|
||||
el::Configurations defaultConf;
|
||||
defaultConf.setToDefault();
|
||||
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%level %loc %msg");
|
||||
defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%levshort %loc %msg");
|
||||
defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%levshort %loc %msg");
|
||||
defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%levshort %loc %msg");
|
||||
defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%levshort %loc %msg");
|
||||
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%levshort%vlevel %loc %msg");
|
||||
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
|
||||
el::Loggers::reconfigureLogger("default", defaultConf);
|
||||
#pragma endregion
|
||||
|
||||
@ -26,8 +26,8 @@ static void print_cfg(BasicBlockPtr_t rt, bool rst = false) {
|
||||
if (rst) vis.clear();
|
||||
print_cfg_info(rt);
|
||||
for (auto succ : rt->successors) {
|
||||
if (!vis.count(succ)) {
|
||||
vis.insert(succ);
|
||||
if (!vis.count(succ)) {
|
||||
vis.insert(succ);
|
||||
print_cfg(succ);
|
||||
}
|
||||
}
|
||||
@ -39,9 +39,9 @@ static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) {
|
||||
}
|
||||
|
||||
static void _build_cfg(const FunctionPtr_t func) {
|
||||
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end(); ) {
|
||||
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) {
|
||||
auto bb = *itr;
|
||||
if (bb->inst_list.size() == 1 && Value::is<InstBranch>(bb->inst_list.front())){
|
||||
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) {
|
||||
VLOG(6) << "remove dummy jump block:" << bb->name;
|
||||
@ -53,7 +53,7 @@ static void _build_cfg(const FunctionPtr_t func) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++ itr;
|
||||
++itr;
|
||||
}
|
||||
for (auto basicblock : func->bb_list) {
|
||||
auto _inst_br = basicblock->inst_list.back();
|
||||
@ -71,9 +71,9 @@ static void _build_cfg(const FunctionPtr_t func) {
|
||||
}
|
||||
}
|
||||
// remove unreachable blocks
|
||||
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end(); ){
|
||||
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) {
|
||||
auto bb = *itr;
|
||||
if (bb->predecessors.size() == 0){
|
||||
if (bb->predecessors.size() == 0) {
|
||||
for (auto succ : bb->successors) {
|
||||
succ->predecessors.remove(bb);
|
||||
}
|
||||
@ -81,10 +81,9 @@ static void _build_cfg(const FunctionPtr_t func) {
|
||||
itr = func->bb_list.erase(itr);
|
||||
}
|
||||
else
|
||||
++ itr;
|
||||
++itr;
|
||||
}
|
||||
|
||||
print_cfg(func->bb_list.front(), true);
|
||||
if (VLOG_IS_ON(6)) print_cfg(func->bb_list.front(), true);
|
||||
}
|
||||
|
||||
void PassBuildCFG::run(const Module &module) {
|
||||
|
||||
@ -14,20 +14,20 @@ namespace antlrSysY {
|
||||
static bool is_alloca_promotable(InstAllocaPtr_t inst) {
|
||||
for (const auto use : inst->use_list) {
|
||||
auto user = use.user;
|
||||
if (dynamic_cast<InstLoad*>(user)) {
|
||||
const auto li = dynamic_cast<InstLoad*>(user);
|
||||
if (dynamic_cast<InstLoad *>(user)) {
|
||||
const auto li = dynamic_cast<InstLoad *>(user);
|
||||
if (li->type != inst->type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<InstStore*>(user)) {
|
||||
const auto si = dynamic_cast<InstStore*>(user);
|
||||
else if (dynamic_cast<InstStore *>(user)) {
|
||||
const auto si = dynamic_cast<InstStore *>(user);
|
||||
if (si->operand_list[1] == inst || si->type != inst->type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<InstGEP*>(user)) {
|
||||
const auto gep = dynamic_cast<InstGEP*>(user);
|
||||
else if (dynamic_cast<InstGEP *>(user)) {
|
||||
const auto gep = dynamic_cast<InstGEP *>(user);
|
||||
for (int i = 1; i < gep->operand_list.size(); ++i) {
|
||||
if (!Value::is<ConstantInt>(gep->operand_list[i]) || !Value::as<ConstantInt>(gep->operand_list[i])->value) {
|
||||
return false;
|
||||
@ -46,20 +46,20 @@ struct AllocaInfo {
|
||||
std::vector<BasicBlockPtr_t> use_blocks = {};
|
||||
bool only_in_1_block = true;
|
||||
BasicBlockPtr_t only_block = nullptr;
|
||||
InstStore* only_store = nullptr;
|
||||
InstStore *only_store = nullptr;
|
||||
};
|
||||
|
||||
static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
|
||||
for (auto use : ai->use_list) {
|
||||
auto user = dynamic_cast<Instruction*>(use.user);
|
||||
if (dynamic_cast<InstStore*>(user)) {
|
||||
const auto si = dynamic_cast<InstStore*>(user);
|
||||
auto user = dynamic_cast<Instruction *>(use.user);
|
||||
if (dynamic_cast<InstStore *>(user)) {
|
||||
const auto si = dynamic_cast<InstStore *>(user);
|
||||
info.def_blocks.push_back(si->parent_bb);
|
||||
info.only_store = si;
|
||||
}
|
||||
else {
|
||||
assert(dynamic_cast<InstLoad*>(user));
|
||||
const auto li = dynamic_cast<InstLoad*>(user);
|
||||
assert(dynamic_cast<InstLoad *>(user));
|
||||
const auto li = dynamic_cast<InstLoad *>(user);
|
||||
info.use_blocks.push_back(li->parent_bb);
|
||||
}
|
||||
if (info.only_in_1_block) {
|
||||
@ -69,18 +69,20 @@ static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
|
||||
info.only_in_1_block = false;
|
||||
}
|
||||
}
|
||||
std::cout << "Alloca " << ai->name;
|
||||
std::cout << " Def: [";
|
||||
for (auto blk : info.def_blocks) {
|
||||
std::cout << blk->name << ", ";
|
||||
if (VLOG_IS_ON(6)) {
|
||||
std::cout << "Alloca " << ai->name;
|
||||
std::cout << " Def: [";
|
||||
for (auto blk : info.def_blocks) {
|
||||
std::cout << blk->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " Use: [";
|
||||
for (auto blk : info.use_blocks) {
|
||||
std::cout << blk->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " Use: [";
|
||||
for (auto blk : info.def_blocks) {
|
||||
std::cout << blk->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
// static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) {
|
||||
@ -149,8 +151,10 @@ static void print_dom_info(BasicBlockPtr_t bb) {
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " idomer: ";
|
||||
if (bb->IDOM) std::cout << bb->IDOM->name;
|
||||
else std::cout << "null";
|
||||
if (bb->IDOM)
|
||||
std::cout << bb->IDOM->name;
|
||||
else
|
||||
std::cout << "null";
|
||||
std::cout << "\n";
|
||||
std::cout << " dom: [";
|
||||
for (auto dom : bb->DOM_set) {
|
||||
@ -163,7 +167,7 @@ static void print_dom_info(BasicBlockPtr_t bb) {
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << " DF: [";
|
||||
for (auto df : bb->DF_set) {
|
||||
for (auto df : bb->DF_set) {
|
||||
std::cout << df->name << ", ";
|
||||
}
|
||||
std::cout << "]\n";
|
||||
@ -185,7 +189,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
VLOG(4) << " Gen Dominance Tree & Frontier";
|
||||
gen_dominance(func);
|
||||
gen_dominance_frontier(func);
|
||||
print_dom_tree(func->bb_list.front());
|
||||
if (VLOG_IS_ON(6)) 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;
|
||||
@ -197,12 +201,12 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
for (auto bb : func->bb_list) {
|
||||
for (auto inst : bb->inst_list) {
|
||||
if (Value::is<InstAlloca>(inst)) {
|
||||
assert(inst->parent_bb == bb);
|
||||
// assert(inst->parent_bb == bb);
|
||||
// 貌似没问题,parent_bb是插入alloca的时候的那个block,而alloca实际上是被插入在entry_block的
|
||||
assert(bb == func->bb_list.front() && "Alloca should be at front of a func");
|
||||
auto ai = Value::as<InstAlloca>(inst);
|
||||
// assert(is_alloca_promotable(ai) && "Invalid alloca");
|
||||
if (!Type::isType<IntegerType>(PointerType::pointedType(ai->type)))
|
||||
continue;
|
||||
if (!Type::isType<IntegerType>(PointerType::pointedType(ai->type))) continue;
|
||||
alloca_list.push_back(ai);
|
||||
}
|
||||
}
|
||||
@ -248,13 +252,14 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
auto bb = worklist.front();
|
||||
worklist.pop();
|
||||
for (auto frontier : bb->DF_set) {
|
||||
// LOG(DEBUG) << "visiting " << bb->name <<" : " << frontier->name;
|
||||
auto frontier_index = bb_to_id.at(frontier);
|
||||
if (!visited[frontier_index]) {
|
||||
visited[frontier_index] = true;
|
||||
if (livein_blocks.count(frontier)) {
|
||||
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, bb->predecessors, bb);
|
||||
// if (livein_blocks.count(frontier)) {
|
||||
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->predecessors, frontier, ai->name);
|
||||
phi_to_allocaid.insert({inst_phi, i});
|
||||
}
|
||||
// }
|
||||
if (!def_blocks.count(frontier)) {
|
||||
worklist.push(frontier);
|
||||
}
|
||||
@ -266,8 +271,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
// renaming
|
||||
VLOG(4) << " variable renaming";
|
||||
std::vector<ValuePtr_t> _init_values;
|
||||
for (int i = 0; i < alloca_list.size(); ++ i)
|
||||
_init_values.push_back(ConstantInt::make_shared(0));
|
||||
for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::make_shared(0));
|
||||
std::vector<RenameInfo> rename_list = {{func->bb_list.front(), nullptr, _init_values}};
|
||||
std::vector<bool> visited(bb_to_id.size(), 0);
|
||||
while (!rename_list.empty()) {
|
||||
@ -292,8 +296,8 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
||||
// process instruction
|
||||
for (auto itr = rename_info.bb->inst_list.begin(); itr != rename_info.bb->inst_list.end();) {
|
||||
auto inst = *itr++;
|
||||
if (Value::is<InstAlloca>(inst)) {
|
||||
assert(alloca_to_id.count(Value::as<InstAlloca>(inst)));
|
||||
// we skip non-integer alloca, they are not in our alloca_list
|
||||
if (Value::is<InstAlloca>(inst) && alloca_to_id.count(Value::as<InstAlloca>(inst))) {
|
||||
rename_info.bb->inst_list.remove(inst);
|
||||
}
|
||||
else if (Value::is<InstLoad>(inst)) {
|
||||
|
||||
@ -143,9 +143,11 @@ std::shared_ptr<InstGEP> build_InstGEP(
|
||||
InstPhiPtr_t build_InstPhi(
|
||||
TypePtr_t type,
|
||||
const decltype(Function::bb_list) &incoming_vals,
|
||||
BasicBlockPtr_t parent_bb
|
||||
BasicBlockPtr_t parent_bb,
|
||||
const std::string &name
|
||||
) {
|
||||
auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb);
|
||||
auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb);
|
||||
inst->name = name;
|
||||
parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
||||
}
|
||||
else if (Value::is<FParam>(inst->operand_list[i])) {
|
||||
auto op0 = Value::as<FParam>(inst->operand_list[i]);
|
||||
ostr << op0->to_IR_string() << ", ";
|
||||
ostr << op0->to_IR_string();
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "Unexpected type of op_i: " << inst->operand_list[i]->to_string();
|
||||
@ -467,6 +467,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
||||
ostr << ", ";
|
||||
}
|
||||
}
|
||||
ostr << " ; alloca: " << inst->name;
|
||||
break;
|
||||
}
|
||||
// These should not be generated in frontend stage
|
||||
|
||||
Loading…
Reference in New Issue
Block a user