diff --git a/.vscode/settings.json b/.vscode/settings.json index e234d5d..c40b051 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "clangd.arguments": [ - "--compile-commands-dir=${workspaceFolder}/build" + "--compile-commands-dir=${workspaceFolder}/build", + "--header-insertion=never" ], "cmake.configureOnOpen": true, "antlr4.rrd.saveDir": "${workspaceFolder}/build", @@ -14,5 +15,7 @@ "[python]": { "editor.defaultFormatter": "ms-python.autopep8" }, - "python.formatting.provider": "none" + "python.formatting.provider": "none", + "editor.indentSize": "tabSize", + "editor.tabSize": 2, } \ No newline at end of file diff --git a/include/llir_instruction.h b/include/llir_instruction.h index 946ec2f..8cfdba3 100644 --- a/include/llir_instruction.h +++ b/include/llir_instruction.h @@ -36,14 +36,13 @@ enum class InstTag { ExtractEle }; -class Instruction : public Value { +class Instruction : public User { public: int ir_seqno = -1; InstTag tag; - std::shared_ptr parent_bb; - std::vector> operand_list; - Instruction(InstTag inst_tag, TypePtr_t type, std::shared_ptr parent_bb) - : Value("", type), tag(inst_tag), parent_bb(parent_bb) {} + BasicBlockPtr_t parent_bb; + Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb) + : User("", type), tag(inst_tag), parent_bb(parent_bb) {} virtual std::string to_string() override { switch (tag) { case InstTag::Add: return "add"; @@ -91,8 +90,8 @@ public: InstStore(std::shared_ptr value, std::shared_ptr pointer, std::shared_ptr parent_bb) : Instruction(InstTag::Store, TypeHelper::TYPE_VOID, parent_bb) { assert(value); - operand_list.push_back(value); - operand_list.push_back(pointer); + Add_Operand(value); + Add_Operand(pointer); } }; @@ -100,7 +99,7 @@ class InstLoad : public Instruction { public: InstLoad(std::shared_ptr value, TypePtr_t type, std::shared_ptr parent_bb) : Instruction(InstTag::Load, type, parent_bb) { - operand_list.push_back(value); + Add_Operand(value); } virtual std::string to_IR_string() override { std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); @@ -118,8 +117,8 @@ public: std::shared_ptr parent_bb ) : Instruction(inst_tag, val_type, parent_bb) { - operand_list.push_back(op1); - operand_list.push_back(op2); + Add_Operand(op1); + Add_Operand(op2); } virtual std::string to_IR_string() override { std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); @@ -133,7 +132,7 @@ class InstZext : public Instruction { public: InstZext(std::shared_ptr op, std::shared_ptr parent_bb) : Instruction(InstTag::Zext, TypeHelper::TYPE_I32, parent_bb) { - operand_list.push_back(op); + Add_Operand(op); } virtual std::string to_IR_string() override { std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno); @@ -146,14 +145,14 @@ public: // conditional branch InstBranch(ValuePtr_t cond, BasicBlockPtr_t true_block, BasicBlockPtr_t false_block, BasicBlockPtr_t parent_bb) : Instruction(InstTag::Br, TypeHelper::TYPE_VOID, parent_bb) { - this->operand_list.push_back(cond); - this->operand_list.push_back(true_block); - this->operand_list.push_back(false_block); + this->Add_Operand(cond); + this->Add_Operand(true_block); + this->Add_Operand(false_block); } // unconditional branch InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) : Instruction(InstTag::Br, TypeHelper::TYPE_VOID, parent_bb) { - this->operand_list.push_back(target_block); + this->Add_Operand(target_block); } }; @@ -161,7 +160,7 @@ class InstReturn : public Instruction { public: InstReturn(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb) : Instruction(InstTag::Ret, TypeHelper::TYPE_VOID, parent_bb) { - this->operand_list.push_back(ret_val); + this->Add_Operand(ret_val); } InstReturn(BasicBlockPtr_t parent_bb) : Instruction(InstTag::Ret, TypeHelper::TYPE_VOID, parent_bb) {} }; @@ -171,8 +170,10 @@ class InstCall : public Instruction { public: InstCall(FunctionPtr_t func, const std::vector &args, BasicBlockPtr_t parent_bb) : Instruction(InstTag::Call, func->get_type()->return_type, parent_bb) { - operand_list.push_back(func); - operand_list.insert(operand_list.end(), args.begin(), args.end()); + Add_Operand(func); + for (auto arg : args) { + Add_Operand(arg); + } } virtual std::string to_IR_string() override { if (Type::isType(type)) { @@ -203,8 +204,10 @@ public: aim_to = nullptr; } element_type = extract_type(pointer, indices); - operand_list.push_back(pointer); - operand_list.insert(operand_list.end(), indices.begin(), indices.end()); + Add_Operand(pointer); + for (auto index : indices) { + Add_Operand(index); + } } virtual std::string to_IR_string() override { diff --git a/include/llir_type.h b/include/llir_type.h index f87d54f..cf62da8 100644 --- a/include/llir_type.h +++ b/include/llir_type.h @@ -6,6 +6,9 @@ #include namespace antlrSysY { +class Type; +typedef std::shared_ptr TypePtr_t; + class Type { public: enum class TypeTag { @@ -82,8 +85,6 @@ public: } }; -typedef std::shared_ptr TypePtr_t; - class TypeHelper { public: static bool isIntegerType(TypePtr_t type) { diff --git a/include/llir_value.h b/include/llir_value.h index 2d6065e..d308de2 100644 --- a/include/llir_value.h +++ b/include/llir_value.h @@ -9,13 +9,29 @@ #include #include #include +#include namespace antlrSysY { +class Value; +class BasicBlock; +class User; +class Function; +class Instruction; +typedef std::shared_ptr ValuePtr_t; +typedef std::shared_ptr BasicBlockPtr_t; +typedef std::shared_ptr FunctionPtr_t; +typedef std::shared_ptr UserPtr_t; +typedef std::shared_ptr InstructionPtr_t; +typedef std::tuple UseEdge_t; +// Define, User, operand-index + class Value { public: std::string name; TypePtr_t type; + std::list use_list; + Value(const std::string &name, TypePtr_t type) : name(name), type(type) {} virtual ~Value() = default; @@ -46,8 +62,16 @@ public: } }; + class User : public Value { public: + std::vector operand_list; + + User(const std::string &name, TypePtr_t type) : Value(name, type) {} + void Add_Operand(ValuePtr_t op) { + operand_list.push_back(op); + use_list.push_back({op, std::make_shared(this), operand_list.size()}); + } }; class BasicBlock; @@ -96,15 +120,19 @@ public: BasicBlockListNode_t itr; std::list> successors; std::list> predecessors; + + BasicBlockPtr_t idomer; + std::list idomee_list; + std::list domer_list; + std::list dom_frontier; + int dom_level; + int _dom_helper_index; + BasicBlock(const std::string &name, std::shared_ptr parent) : Value(name, TypeHelper::TYPE_LABEL) { this->parent = parent; } }; -typedef std::shared_ptr ValuePtr_t; -typedef std::shared_ptr BasicBlockPtr_t; -typedef std::shared_ptr FunctionPtr_t; - class Constant : public Value { public: Constant(const std::string &name, TypePtr_t type) : Value(name, type) {} diff --git a/include/pass.h b/include/pass.h index 808e1d8..c066dd9 100644 --- a/include/pass.h +++ b/include/pass.h @@ -12,4 +12,10 @@ public: virtual void run(const Module &module) = 0; }; +class PassMem2Reg : public Pass { +public: + PassMem2Reg() : Pass("mem2reg") {} + virtual void run(const Module &module) override; +}; + } // namespace antlrSysY \ No newline at end of file diff --git a/src/dominance_algo.cpp b/src/dominance_algo.cpp new file mode 100644 index 0000000..7b6c88c --- /dev/null +++ b/src/dominance_algo.cpp @@ -0,0 +1,106 @@ +#include "llir.h" +#include "visitor.h" +#include + +namespace antlrSysY { + +static void _bitwise_and(std::vector& op1, const std::vector& op2) { + for (int i = 0; i < op1.size(); ++ i) { + op1[i] = op1[i] & op2[i]; + } +} + +static void _bitwise_set(std::vector& op1, int l, int r,bool val) { + for (int i = l; i < r; ++ i) { + op1[i] = val; + } +} + +static void _gen_dom_level(BasicBlockPtr_t bb, int level) { + bb->dom_level = level; + for (auto succ : bb->idomee_list) { + _gen_dom_level(succ, level + 1); + } +} + +void gen_dominance(FunctionPtr_t func) { + // 编译器设计 2E 352 | Engineering A Compiler P479 + // Note: n \in Dom(n) + // Basic iterative idea: Dom(n) = {n} union (intersect Dom(pred(n))) + std::vector> domers; + std::vector bb_list; + const int N = func->bb_list.size(); + auto itr = func->bb_list.begin(); + for (auto basicblock : func->bb_list) { + basicblock->idomee_list.clear(); + basicblock->domer_list.clear(); + domers.push_back({}); + domers.back().resize(N, true); // Dom(i) <- N + basicblock->_dom_helper_index = bb_list.size(); + bb_list.push_back(basicblock); + } + _bitwise_set(domers[0], 1, N, false); // Dom(0) <- {0} + + bool changed = true; + while (changed) { + changed = false; + int i = 0; + for (int i = 1; i < N; ++ i) { + auto cur_bb = bb_list[i]; + std::vector temp(true, N); + // temp = {i} union (intersect Dom(j)), j in pred(i) + for (auto pred : cur_bb->predecessors) { + _bitwise_and(temp, domers[pred->_dom_helper_index]); + } + temp[i] = true; + // if temp != Dom(i) + if (!(temp == domers[i])) { + domers[i] = temp; // Dom(i) <- temp + changed = true; // changed <- true + } + } + } + // set each basicblock's domer + for (int i = 0; i < N; ++ i) { + for (int j = 0; j < N; ++ j) { + if (domers[i][j]) { + bb_list[i]->domer_list.push_back(bb_list[j]); + } + } + } + // get domees and immediate domer + for (int i = 0; i < N; ++ i) { + for (auto domer1 : bb_list[i]->domer_list) { + 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]->domer_list) { + if (domer2 == bb_list[i] || domer2 == domer1) + continue; + if (std::find(domer2->domer_list.begin(), domer2->domer_list.end(), domer1) != domer2->domer_list.end()) { + flag = false; + break; + } + } + if (flag) { + bb_list[i]->idomer = domer1; + domer1->idomee_list.push_back(bb_list[i]); + break; + } + } + } + _gen_dom_level(bb_list[0], 0); +} + +void gen_dominance_frontier(FunctionPtr_t func) { + // 编译器设计 2E 368 + // for all node in CFG: DF(n) <- Empty + for (auto bb : func->bb_list) { + bb->dom_frontier.clear(); + } + // for all node in CFG: + +} + +} \ No newline at end of file diff --git a/src/pass_mem2reg.cpp b/src/pass_mem2reg.cpp new file mode 100644 index 0000000..aab4496 --- /dev/null +++ b/src/pass_mem2reg.cpp @@ -0,0 +1,14 @@ +#include "passes.h" +#include "llir.h" +#include "common.h" + +namespace antlrSysY { + +void PassMem2Reg::run(const Module& module) { + for (auto func : module.function_list) { + if (func->is_libfunc()) continue; + + } +} + +} \ No newline at end of file