From 8a9c32e820f48b02dbe246af62a5b663df071e9c Mon Sep 17 00:00:00 2001 From: ridethepig Date: Mon, 22 May 2023 11:15:19 +0800 Subject: [PATCH] first workable Mem2Reg --- .vscode/launch.json | 2 +- include/llir_type.h | 2 +- include/llir_value.h | 12 +++---- include/visitor.h | 7 +++- scripts/mytester.py | 2 +- src/main.cpp | 10 +++--- src/pass_build_cfg.cpp | 19 +++++----- src/pass_mem2reg.cpp | 78 +++++++++++++++++++++------------------- src/visitor_factory.cpp | 6 ++-- src/visitor_llir_gen.cpp | 3 +- 10 files changed, 76 insertions(+), 65 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 28ce5eb..6b467a7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -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}" } ] diff --git a/include/llir_type.h b/include/llir_type.h index 9cf76df..b18fd9a 100644 --- a/include/llir_type.h +++ b/include/llir_type.h @@ -1,10 +1,10 @@ #pragma once #include "common.h" +#include #include #include #include -#include namespace antlrSysY { diff --git a/include/llir_value.h b/include/llir_value.h index 9765e53..a26213d 100644 --- a/include/llir_value.h +++ b/include/llir_value.h @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include namespace antlrSysY { @@ -25,7 +25,7 @@ DEF_PTR_T(ConstantInt); // typedef std::tuple 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 successors; std::list predecessors; - BasicBlockPtr_t IDOM; // dominating node + BasicBlockPtr_t IDOM; // dominating node std::unordered_set idom_set; // immediate dominated nodes std::unordered_set DOM_set; // dominated nodes std::unordered_set DF_set; diff --git a/include/visitor.h b/include/visitor.h index 11e0a2c..cb6f8e0 100644 --- a/include/visitor.h +++ b/include/visitor.h @@ -81,7 +81,12 @@ std::shared_ptr 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 diff --git a/scripts/mytester.py b/scripts/mytester.py index 012ba6c..f361b44 100644 --- a/scripts/mytester.py +++ b/scripts/mytester.py @@ -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}}", diff --git a/src/main.cpp b/src/main.cpp index a60dabf..9e91e1d 100644 --- a/src/main.cpp +++ b/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 diff --git a/src/pass_build_cfg.cpp b/src/pass_build_cfg.cpp index 6ff3c86..a8f0b70 100644 --- a/src/pass_build_cfg.cpp +++ b/src/pass_build_cfg.cpp @@ -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(bb->inst_list.front())){ + if (bb->inst_list.size() == 1 && Value::is(bb->inst_list.front())) { auto br = Value::as(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) { diff --git a/src/pass_mem2reg.cpp b/src/pass_mem2reg.cpp index 055b697..3522de8 100644 --- a/src/pass_mem2reg.cpp +++ b/src/pass_mem2reg.cpp @@ -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(user)) { - const auto li = dynamic_cast(user); + if (dynamic_cast(user)) { + const auto li = dynamic_cast(user); if (li->type != inst->type) { return false; } } - else if (dynamic_cast(user)) { - const auto si = dynamic_cast(user); + else if (dynamic_cast(user)) { + const auto si = dynamic_cast(user); if (si->operand_list[1] == inst || si->type != inst->type) { return false; } } - else if (dynamic_cast(user)) { - const auto gep = dynamic_cast(user); + else if (dynamic_cast(user)) { + const auto gep = dynamic_cast(user); for (int i = 1; i < gep->operand_list.size(); ++i) { if (!Value::is(gep->operand_list[i]) || !Value::as(gep->operand_list[i])->value) { return false; @@ -46,20 +46,20 @@ struct AllocaInfo { std::vector 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(use.user); - if (dynamic_cast(user)) { - const auto si = dynamic_cast(user); + auto user = dynamic_cast(use.user); + if (dynamic_cast(user)) { + const auto si = dynamic_cast(user); info.def_blocks.push_back(si->parent_bb); info.only_store = si; } else { - assert(dynamic_cast(user)); - const auto li = dynamic_cast(user); + assert(dynamic_cast(user)); + const auto li = dynamic_cast(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 alloca_list; std::unordered_map 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(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(inst); // assert(is_alloca_promotable(ai) && "Invalid alloca"); - if (!Type::isType(PointerType::pointedType(ai->type))) - continue; + if (!Type::isType(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 _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 rename_list = {{func->bb_list.front(), nullptr, _init_values}}; std::vector 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(inst)) { - assert(alloca_to_id.count(Value::as(inst))); + // we skip non-integer alloca, they are not in our alloca_list + if (Value::is(inst) && alloca_to_id.count(Value::as(inst))) { rename_info.bb->inst_list.remove(inst); } else if (Value::is(inst)) { diff --git a/src/visitor_factory.cpp b/src/visitor_factory.cpp index 302dc9c..7ac5451 100644 --- a/src/visitor_factory.cpp +++ b/src/visitor_factory.cpp @@ -143,9 +143,11 @@ std::shared_ptr 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(type, incoming_vals, parent_bb); + auto inst = std::make_shared(type, incoming_vals, parent_bb); + inst->name = name; parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); return inst; } diff --git a/src/visitor_llir_gen.cpp b/src/visitor_llir_gen.cpp index 692782b..b94f85c 100644 --- a/src/visitor_llir_gen.cpp +++ b/src/visitor_llir_gen.cpp @@ -286,7 +286,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl } else if (Value::is(inst->operand_list[i])) { auto op0 = Value::as(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 &bl ostr << ", "; } } + ostr << " ; alloca: " << inst->name; break; } // These should not be generated in frontend stage