diff --git a/.vscode/launch.json b/.vscode/launch.json index 7e09f50..b67a59a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,8 +9,9 @@ "request": "launch", "name": "Debug", "program": "${workspaceFolder}/build/sysy", - "args": ["../sysytests/functional_2022/28_while_test3.sy", "-S", "-o", "build/my.s", "-O1", "-emit-llvm"], + // "args": ["../sysytests/functional_2021/069_greatest_common_divisor.sy", "-S", "-o", "build/my.s", "-O1", "-emit-llvm"], + "args" : ["-S", "../sysytests/functional_2022/88_many_params2.sy", "-o", "build/my.s", "-emit-llvm", "-O1"], "cwd": "${workspaceFolder}" - } + }, ] } \ No newline at end of file diff --git a/include/common.h b/include/common.h index c4c2492..10c29d2 100644 --- a/include/common.h +++ b/include/common.h @@ -45,15 +45,16 @@ inline sptr(DST) strict_shared_cast(SRC src) { throw GrammarException(__FILE__, __LINE__, (message)); \ } while (0) -#define sysy_assert(cond) \ - do { \ - if (!(cond)) throw GrammarException(__FILE__, __LINE__, #cond); \ - } while (0) - #define DEF_PTR_T(type) \ class type; \ typedef std::shared_ptr type##Ptr_t +#define GET_MACRO(_1, _2, NAME, ...) NAME +#define _sysy_assert1(expr) assert(expr) +#define _sysy_assert2(expr, info) \ + (static_cast(expr) ? void(0) : ([&]() { info }(), __assert_fail(#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))) +#define sysy_assert(...) GET_MACRO(__VA_ARGS__, _sysy_assert2, _sysy_assert1)(__VA_ARGS__) + namespace CompSysY { template diff --git a/include/llir_type.h b/include/llir_type.h index a6bc64b..6e93ac7 100644 --- a/include/llir_type.h +++ b/include/llir_type.h @@ -116,7 +116,7 @@ public: int type_size = 0; // = dim_size * size(elem_type) ArrayType() : Type(TypeTag::ArrayType) {} ArrayType(TypePtr_t element_type, int element_count) - : Type(TypeTag::ArrayType), elem_count(element_count), elem_type(element_type) {} + : Type(TypeTag::ArrayType), elem_type(element_type), elem_count(element_count) {} static std::shared_ptr build_from_list(const std::vector &dim_list) { TypePtr_t array_type = TypeHelper::TYPE_I32; sysy_assert(dim_list.size() != 0); diff --git a/include/mc_inst.h b/include/mc_inst.h index cd30de4..d0cd786 100644 --- a/include/mc_inst.h +++ b/include/mc_inst.h @@ -95,8 +95,6 @@ inline const char *enum_to_string(const MOpTag &tag) { return _str_tab[(unsigned)tag]; } -// TODO Basic idea: value = id of globalvar in glob_list - class MOperand { public: MOpTag op_type = MOpTag::Invalid; @@ -140,8 +138,8 @@ public: bool is_precolored() const { return op_type == MOpTag::PreColor; } - bool need_clr() const { - return is_precolored() || op_type == MOpTag::Virt; + bool is_virt() const { + return op_type == MOpTag::Virt; } bool is_imm() const { return op_type == MOpTag::Imm; @@ -152,7 +150,7 @@ public: bool is_reg() const { return op_type == MOpTag::PreColor || op_type == MOpTag::Virt || op_type == MOpTag::Colored; } - std::string to_string(); + std::string to_string() const; }; struct MOperandHash { @@ -206,6 +204,9 @@ inline MInstTag inverse_cond(MInstTag src_tag) { } } +// Instruction insertion type +enum class InsType { Before, After, Head, Tail }; + class MInst { public: MInstTag inst_tag; @@ -215,11 +216,18 @@ public: // Similarly, it makes difference when computing address int width = 4; + std::list::iterator itr; sptr(MBasicBlock) parent_bb; MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : inst_tag(tag), parent_bb(parent_bb) {} - virtual ~MInst() = default; - virtual std::vector get_def() = 0; - virtual std::vector get_use() = 0; + virtual ~MInst() = default; + virtual std::vector get_def() const = 0; + virtual std::vector get_use() const = 0; + virtual bool is_transfer() const { + return false; + } + + static void PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty); + static void PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty); }; class MBasicBlock { @@ -260,8 +268,7 @@ public: std::vector global_list; std::unordered_map global_id_map; void IR2MC(const Module &ir_module); - void MC2ASM(std::ostream &ostr) const; - bool debug1 = false; + void MC2ASM(std::ostream &ostr, bool debug = false) const; }; class MInstBinary : public MInst { @@ -271,14 +278,24 @@ public: MOperand op2; MInstBinary(MInstTag type, sptr(MBasicBlock) parent_bb) : MInst(type, parent_bb) {} - static sptr(MInstBinary) New(MInstTag type, sptr(MBasicBlock) parent_bb, int width) { - auto inst = make_shared(type, parent_bb); - parent_bb->inst_list.push_back(inst); + static sptr(MInstBinary) New(MInstTag type, sptr(MBasicBlock) parent_bb, int width, InsType ins_ty = InsType::Tail) { + auto inst = make_shared(type, parent_bb); inst->width = width; + MInst::PostNew(inst, parent_bb, ins_ty); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, bool insert_after = false) { + auto parent_bb = rel_inst->parent_bb; + auto inst = make_shared(type, parent_bb); + inst->width = width; + auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst); + assert(rel_inst_itr != parent_bb->inst_list.end()); + if (insert_after) std::advance(rel_inst_itr, 1); + parent_bb->inst_list.insert(rel_inst_itr, inst); + return inst; + } + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; class MInstJump : public MInst { @@ -291,8 +308,11 @@ public: parent_bb->inst_list.push_back(inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; + bool is_transfer() const override { + return true; + } }; class MInstBranch : public MInst { @@ -307,8 +327,11 @@ public: parent_bb->inst_list.push_back(inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; + bool is_transfer() const override { + return true; + } }; class MInstLoad : public MInst { @@ -334,8 +357,8 @@ public: inst->width = width; return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; class MInstStore : public MInst { @@ -361,8 +384,8 @@ public: inst->width = width; return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; class MInstMove : public MInst { @@ -387,8 +410,8 @@ public: parent_bb->inst_list.insert(rel_inst_itr, inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; // class MInstSymbol : public MInst { @@ -417,8 +440,11 @@ public: parent_bb->inst_list.push_back(inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; + bool is_transfer() const override { + return true; + } }; class MInstComment : public MInst { @@ -430,8 +456,17 @@ public: parent_bb->inst_list.push_back(inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + static sptr(MInstComment) New(sptr(MInst) rel_inst, bool insert_after = false) { + auto parent_bb = rel_inst->parent_bb; + auto inst = make_shared(parent_bb); + auto rel_inst_itr = STD_FIND(parent_bb->inst_list, rel_inst); + assert(rel_inst_itr != parent_bb->inst_list.end()); + if (insert_after) std::advance(rel_inst_itr, 1); + parent_bb->inst_list.insert(rel_inst_itr, inst); + return inst; + } + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; class MInstCall : public MInst { @@ -443,12 +478,9 @@ public: parent_bb->inst_list.push_back(inst); return inst; } - virtual std::vector get_def() override; - virtual std::vector get_use() override; + virtual std::vector get_def() const override; + virtual std::vector get_use() const override; }; -void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector &use); void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector &use); -void set_bb_def_use(sptr(MFunction) func); - } // namespace CompSysY \ No newline at end of file diff --git a/include/pass.h b/include/pass.h index b3f6313..aa4315f 100644 --- a/include/pass.h +++ b/include/pass.h @@ -15,13 +15,13 @@ public: virtual void run(const Module &module) = 0; }; -class PassMem2Reg : public Pass { +class PassMem2Reg final : public Pass { public: PassMem2Reg() : Pass("mem2reg") {} virtual void run(const Module &module) override; }; -class PassBuildCFG : public Pass { +class PassBuildCFG final : public Pass { public: PassBuildCFG() : Pass("build_cfg") {} virtual void run(const Module &module) override; @@ -35,12 +35,23 @@ public: virtual void run(const MCModule &module) = 0; }; -class PassRegAlloc : public MCPass { +class PassRegAlloc final : public MCPass { public: PassRegAlloc() : MCPass("regalloc") {} virtual void run(const MCModule &module) override; const static int K = 32 - 5; // Not Allocate-able: x0, gp, tp; Reserve: sp, ra + // exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4) + static inline std::unordered_set _ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + private: + struct MvCmp { + bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const { + if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst; + if (lhs->src != rhs->src) return lhs->src < rhs->src; + return false; + } + }; /*以下这些集合**各不相交** precolored:机器寄存器集合,每个寄存器都预先指派了一种颜色 initial:临时寄存器集合,其中的元素既没有预着色,也没有被处理 @@ -57,7 +68,7 @@ private: void add_edge(const MOperand &u, const MOperand &v); void make_work_list(sptr(MFunction) func); bool move_related(const MOperand &n); - std::set node_moves(const MOperand &n); + std::set node_moves(const MOperand &n); std::set adjacent(const MOperand &n); void decrement_degree(const MOperand &m); void enable_moves(const MOperand &n); @@ -66,17 +77,18 @@ private: void add_work_list(const MOperand &u); bool OK(const MOperand &t, const MOperand &r); bool conservative(const std::set &nodes); - MOperand get_alias(MOperand n); + MOperand get_alias(const MOperand &n); void combine(const MOperand &u, const MOperand &v); void freeze(); void freeze_moves(const MOperand &u); void select_spill(); void assign_colors(sptr(MFunction) func); void rewrite_program(sptr(MFunction) func); + void clear(); std::map> adj_list; std::set> adj_set; std::map degree; - std::map> move_list; + std::map> move_list; std::map color; std::map alias; std::set initial; @@ -87,13 +99,12 @@ private: std::set coalesced_nodes; std::set colored_nodes; std::vector select_stack; - std::set coalesced_moves; - std::set constrained_moves; - std::set frozen_moves; - std::set worklist_moves; - std::set active_moves; - - void clear(); + std::set coalesced_moves; + std::set constrained_moves; + std::set frozen_moves; + std::set worklist_moves; + std::set active_moves; + std::map spill_space; }; } // namespace CompSysY \ No newline at end of file diff --git a/scripts/mytester.py b/scripts/mytester.py index a4710be..7e85d4d 100644 --- a/scripts/mytester.py +++ b/scripts/mytester.py @@ -118,6 +118,7 @@ class Compiler: log_file = open(log, "a+") Print_C.print_procedure(f"Generating {asm}") completed = subprocess.run(sy_asm_instr.format(asm=asm, sy=sy).split(), stdout=log_file, stderr=log_file, bufsize=1) + # print(sy_asm_instr.format(asm=asm, sy=sy)) log_file.close() if completed.returncode != 0: Print_C.print_error(f"Generate {bin} failed! See {log}") @@ -233,7 +234,7 @@ scheme_ref = { scheme_my = { "name": "my", - "sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1", + "sy_ir": f"build/sysy -S {{sy}} -o {{ir}} -emit-llvm -O1 -no-asm", "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/algo_dominance.cpp b/src/algo_dominance.cpp index ac1a3c9..340837c 100644 --- a/src/algo_dominance.cpp +++ b/src/algo_dominance.cpp @@ -5,15 +5,15 @@ namespace CompSysY { 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]; + 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 _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; @@ -28,7 +28,6 @@ void gen_dominance(FunctionPtr_t func) { // Basic iterative idea: Dom(n) = {n} union (intersect Dom(pred(n))) std::vector bb_list; const int N = func->bb_list.size(); - auto itr = func->bb_list.begin(); for (auto basicblock : func->bb_list) { basicblock->idom_set.clear(); basicblock->DOM_set.clear(); @@ -46,7 +45,6 @@ void gen_dominance(FunctionPtr_t func) { 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(N, 1); diff --git a/src/main.cpp b/src/main.cpp index 32ef127..390aa27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,6 +76,7 @@ int main(int argc, const char **argv) { defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%levshort %loc %msg"); defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format, "%levshort%vlevel %loc %msg"); defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, "%levshort %msg"); + defaultConf.setGlobally(el::ConfigurationType::ToFile, "false"); el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); el::Loggers::reconfigureLogger("default", defaultConf); #pragma endregion @@ -141,9 +142,7 @@ int main(int argc, const char **argv) { // asm before reg alloc auto virt_asm_file = output_file.substr(0, output_file.rfind(".")) + "_virt.asm"; std::ofstream ofs_virt_asm_file(virt_asm_file); - mc_module.debug1 = true; - mc_module.MC2ASM(ofs_virt_asm_file); - mc_module.debug1 = false; + mc_module.MC2ASM(ofs_virt_asm_file, true); ofs_virt_asm_file.close(); std::vector mc_passes = {std::make_shared()}; diff --git a/src/mc_asmgen.cpp b/src/mc_asmgen.cpp index e2eb896..2f4ae65 100644 --- a/src/mc_asmgen.cpp +++ b/src/mc_asmgen.cpp @@ -158,11 +158,11 @@ static void emit_cmp(std::ostream &ostr, sptr(MInstBinary) inst) { break; case MInstTag::Eq: ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl; - ostr << fmt::format("\tseqz\t{}, {}, 1", rd, rd) << endl; + ostr << fmt::format("\tseqz\t{}, {}", rd, rd) << endl; break; case MInstTag::Ne: ostr << fmt::format("\t{}\t{}, {}, {}", opcode, rd, rs1, rs2) << endl; - ostr << fmt::format("\tsnez\t{}, {}, 1", rd, rd) << endl; + ostr << fmt::format("\tsnez\t{}, {}", rd, rd) << endl; break; default: assert(0); } @@ -225,6 +225,9 @@ static void emit_load(std::ostream &ostr, sptr(MInstLoad) inst) { } static void emit_store(std::ostream &ostr, sptr(MInstStore) inst) { + if (!(inst->offset.is_imm() && !inst->addr.is_imm() && !inst->data.is_imm())) { + LOG(ERROR) << "shit"; + } assert(inst->offset.is_imm() && !inst->addr.is_imm() && !inst->data.is_imm()); auto data = inst->data.to_string(); auto offset = inst->offset.to_string(); @@ -284,6 +287,9 @@ static void emit_array(std::ostream &ostr, sptr(ConstantArr) arr) { zero_cnt++; } } + if (zero_cnt) { + ostr << fmt::format("\t.zero\t{}\n", zero_cnt * 4); + } } static void stack_postprocess(sptr(MFunction) func) { @@ -368,14 +374,14 @@ void emit_function(std::ostream &ostr, sptr(MFunction) func) { ostr << fmt::format("/* -- End Function {} --*/", func->ir_func->name) << endl; } -void MCModule::MC2ASM(std::ostream &ostr) const { +void MCModule::MC2ASM(std::ostream &ostr, bool debug) const { // header, specifying align and arch ostr << "\t.text\n" << "\t.attribute\t4,\t16\n" << "\t.attribute\t5,\t\"rv64i2p0_m2p0_f2p0_d2p0\"\n"; ostr << "\t.file\t\"" << this->file_name << "\"\n" << endl; for (auto func : this->function_list) { - if (!debug1) stack_postprocess(func); + if (!debug) stack_postprocess(func); emit_function(ostr, func); } diff --git a/src/mc_codegen.cpp b/src/mc_codegen.cpp index 8d7a161..c622434 100644 --- a/src/mc_codegen.cpp +++ b/src/mc_codegen.cpp @@ -14,12 +14,17 @@ static auto gen_imm(int imm, sptr(MBasicBlock) mc_bb, bool force_reg = false) { return operand; } // load to register, should use pseudo `mv` - // TODO TrivialCompiler added a opt trick here, insert before a control tansfer? + // ! TrivialCompiler added a opt trick here, insert before a control tansfer? + // * No, it is for phi elimination, in case you insert after a jump, which break the bb if (imm == 0) { return MOperand::PreClrReg(RV64Reg::x0); } - auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); - auto inst_move = MInstMove::New(mc_bb); + auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); + sptr(MInstMove) inst_move; + if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer()) + inst_move = MInstMove::New(mc_bb->inst_list.back()); + else + inst_move = MInstMove::New(mc_bb); inst_move->src = operand; inst_move->dst = vr; return vr; @@ -62,7 +67,12 @@ static MOperand value2moperand( width = 4; else if (shared_cast(fparam->type)) width = XLEN; - auto inst_load = MInstLoad::New(mc_bb, width); // ld vr, (i-8)*8(sp) + sptr(MInstLoad) inst_load; + // ld vr, (i-8)*8(sp) + if (!mc_bb->inst_list.empty() && mc_bb->inst_list.back()->is_transfer()) + inst_load = MInstLoad::New(mc_bb->inst_list.back(), width); + else + inst_load = MInstLoad::New(mc_bb, width); // auto inst_move = MInstMove::New(inst_load); // lui vr_t, inst_load->addr = MOperand::PreClrReg(RV64Reg::sp); inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN); @@ -72,10 +82,10 @@ static MOperand value2moperand( return vr; } else if (auto glob = shared_cast(ir_value)) { - auto itr = val2mop.find(ir_value); - if (itr != val2mop.end()) { - return itr->second; - } + // auto itr = val2mop.find(ir_value); + // if (itr != val2mop.end()) { + // return itr->second; + // } // auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true); // auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); // val2mop.insert({ir_value, vr}); @@ -86,7 +96,7 @@ static MOperand value2moperand( if (force_reg) { auto inst_la = MInstMove::New(mc_bb); auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); - val2mop.insert({ir_value, vr}); + // val2mop.insert({ir_value, vr}); inst_la->dst = vr; inst_la->src = op_glob; return vr; @@ -129,7 +139,7 @@ void MCModule::IR2MC(const Module &ir_module) { this->function_list.push_back(mc_func); mc_func->ir_func = func; mc_func->id = fn_id_cnt++; - + bb_id_cnt = 0; // copy pred/succ info std::unordered_map bb_ir2mc; for (auto bb : func->bb_list) { @@ -174,10 +184,10 @@ void MCModule::IR2MC(const Module &ir_module) { auto addr = value2moperand(st->operand_list[1], mc_bb, mp_val2op, true); int width = XLEN; if (shared_cast(st->operand_list[0]->type)) width = 4; - auto mc_li = MInstStore::New(mc_bb, width); - mc_li->addr = addr; - mc_li->data = data; - mc_li->offset = MOperand::Imm(0); + auto mc_st = MInstStore::New(mc_bb, width); + mc_st->addr = addr; + mc_st->data = data; + mc_st->offset = MOperand::Imm(0); continue; } if (auto gep = shared_cast(inst)) { @@ -278,7 +288,7 @@ void MCModule::IR2MC(const Module &ir_module) { auto target_func = cal->operand_list[0]; int nparams = cal->operand_list.size() - 1; for (int i = 1; i < cal->operand_list.size(); ++i) { - auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op); + auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true); if (i <= 8) { auto inst_move = MInstMove::New(mc_bb); inst_move->src = rparam; @@ -295,7 +305,7 @@ void MCModule::IR2MC(const Module &ir_module) { } if (nparams > 8) { // sp -= (n-8)*8 - auto add_inst = new MInstBinary(MInstTag::Sub, mc_bb); + auto add_inst = MInstBinary::New(MInstTag::Sub, mc_bb, 8); add_inst->dst = MOperand::PreClrReg(RV64Reg::sp); add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp); add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); @@ -306,7 +316,7 @@ void MCModule::IR2MC(const Module &ir_module) { if (nparams > 8) { // sp += (n-8)*8 - auto add_inst = new MInstBinary(MInstTag::Add, mc_bb); + auto add_inst = MInstBinary::New(MInstTag::Add, mc_bb, 8); add_inst->dst = MOperand::PreClrReg(RV64Reg::sp); add_inst->op1 = MOperand::PreClrReg(RV64Reg::sp); add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); @@ -465,31 +475,28 @@ void MCModule::IR2MC(const Module &ir_module) { LOG(WARNING) << "Condition without branch"; } } - // else if (InstTag::And <= bin->tag && bin->tag <= InstTag::Or) - else { - MInstTag minst_tag; - switch (bin->tag) { - case InstTag::Add: minst_tag = MInstTag::Add; break; - case InstTag::Sub: minst_tag = MInstTag::Sub; break; - case InstTag::Mul: minst_tag = MInstTag::Mul; break; - case InstTag::Div: minst_tag = MInstTag::Div; break; - case InstTag::Mod: minst_tag = MInstTag::Mod; break; - case InstTag::Lt: minst_tag = MInstTag::Lt; break; - case InstTag::Le: minst_tag = MInstTag::Le; break; - case InstTag::Ge: minst_tag = MInstTag::Ge; break; - case InstTag::Gt: minst_tag = MInstTag::Gt; break; - case InstTag::Eq: minst_tag = MInstTag::Eq; break; - case InstTag::Ne: minst_tag = MInstTag::Ne; break; - default: assert(0); - } - auto dst = value2moperand(inst, mc_bb, mp_val2op); - auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op, true); - auto mc_op2 = value2moperand(op2, mc_bb, mp_val2op, BTWN(minst_tag, MInstTag::Mul, MInstTag::Mod)); - auto inst_bin = MInstBinary::New(minst_tag, mc_bb, 4); - inst_bin->dst = dst; - inst_bin->op1 = mc_op1; - inst_bin->op2 = mc_op2; + MInstTag minst_tag; + switch (bin->tag) { + case InstTag::Add: minst_tag = MInstTag::Add; break; + case InstTag::Sub: minst_tag = MInstTag::Sub; break; + case InstTag::Mul: minst_tag = MInstTag::Mul; break; + case InstTag::Div: minst_tag = MInstTag::Div; break; + case InstTag::Mod: minst_tag = MInstTag::Mod; break; + case InstTag::Lt: minst_tag = MInstTag::Lt; break; + case InstTag::Le: minst_tag = MInstTag::Le; break; + case InstTag::Ge: minst_tag = MInstTag::Ge; break; + case InstTag::Gt: minst_tag = MInstTag::Gt; break; + case InstTag::Eq: minst_tag = MInstTag::Eq; break; + case InstTag::Ne: minst_tag = MInstTag::Ne; break; + default: assert(0); } + auto dst = value2moperand(inst, mc_bb, mp_val2op); + auto mc_op1 = value2moperand(op1, mc_bb, mp_val2op, true); + auto mc_op2 = value2moperand(op2, mc_bb, mp_val2op, BTWN(minst_tag, MInstTag::Mul, MInstTag::Mod)); + auto inst_bin = MInstBinary::New(minst_tag, mc_bb, 4); + inst_bin->dst = dst; + inst_bin->op1 = mc_op1; + inst_bin->op2 = mc_op2; continue; } if (auto zxt = shared_cast(inst)) { @@ -535,12 +542,16 @@ void MCModule::IR2MC(const Module &ir_module) { par_mv_pred.insert({pred_mc_bb, {vr, phi_src_op}}); } } + for (auto &pmv : par_mv_cur) { auto inst_mv = MInstMove::New(mc_bb, true); inst_mv->src = pmv.src; inst_mv->dst = pmv.dst; } for (auto &pmv_pair : par_mv_pred) { + sysy_assert(pmv_pair.first->inst_list.back()->is_transfer(), { + LOG(ERROR) << (int)(pmv_pair.first->inst_list.back()->inst_tag) << " " << pmv_pair.first->id; + }); auto inst_mv = MInstMove::New(pmv_pair.first->inst_list.back()); inst_mv->src = pmv_pair.second.src; inst_mv->dst = pmv_pair.second.dst; @@ -549,65 +560,6 @@ void MCModule::IR2MC(const Module &ir_module) { } } -void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector &use) { - if (auto bin = shared_cast(inst)) { - def.push_back(bin->dst); - use.push_back(bin->op1); - use.push_back(bin->op2); - return; - } - if (auto mov = shared_cast(inst)) { - def.push_back(mov->dst); - use.push_back(mov->src); - return; - } - if (auto ld = shared_cast(inst)) { - def.push_back(ld->dst); - use.push_back(ld->addr); - // use.push_back(ld->offset); - return; - } - if (auto st = shared_cast(inst)) { - use.push_back(st->addr); - use.push_back(st->data); - // use.push_back(st->offset); - return; - } - if (auto cal = shared_cast(inst)) { - // arg-occupied regs get implicitly used here - for (int i = 0; i < cal->ir_func->fparam_list.size() && i < 8; ++i) { - use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); - } - // caller-saved regs should also be considered as re-defined - // a0-a7 - for (int i = 0; i < 8; ++i) { - def.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); - } - def.push_back(MOperand::PreClrReg(RV64Reg::t0)); - def.push_back(MOperand::PreClrReg(RV64Reg::t1)); - def.push_back(MOperand::PreClrReg(RV64Reg::t2)); - def.push_back(MOperand::PreClrReg(RV64Reg::t3)); - def.push_back(MOperand::PreClrReg(RV64Reg::t4)); - def.push_back(MOperand::PreClrReg(RV64Reg::t5)); - def.push_back(MOperand::PreClrReg(RV64Reg::t6)); - def.push_back(MOperand::PreClrReg(RV64Reg::ra)); - return; - } - if (auto br = shared_cast(inst)) { - use.push_back(br->op1); - use.push_back(br->op2); - return; - } - if (auto bin = shared_cast(inst)) { - use.push_back(MOperand::PreClrReg(RV64Reg::a0)); - return; - } - // if (auto sym = shared_cast(inst)) { - // def.push_back(sym->dst); - // return; - // } -} - void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector &use) { if (auto bin = shared_cast(inst)) { def.push_back(&bin->dst); @@ -643,24 +595,4 @@ void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector // } } -void set_bb_def_use(sptr(MFunction) func) { - for (auto bb : func->bb_list) { - bb->def.clear(); - bb->use.clear(); - auto add_def = [&](MOperand &def) { - if (def.need_clr()) bb->def.insert(def); - }; - auto add_use = [&](MOperand &use) { - if (use.need_clr()) bb->use.insert(use); - }; - for (auto inst : bb->inst_list) { - std::vector def; - std::vector use; - get_inst_defuse(inst, def, use); - for (auto &elem : def) add_def(elem); - for (auto &elem : use) add_use(elem); - } - } -} - } // namespace CompSysY \ No newline at end of file diff --git a/src/mc_inst.cpp b/src/mc_inst.cpp index 7fd9b2e..3839ea2 100644 --- a/src/mc_inst.cpp +++ b/src/mc_inst.cpp @@ -3,11 +3,11 @@ namespace CompSysY { std::string MBasicBlock::to_string() { - std::string str = "LBB" + std::to_string(parent_func->id) + "_" + std::to_string(id); + std::string str = "L_BB" + std::to_string(parent_func->id) + "_" + std::to_string(id); return str; } -std::string MOperand::to_string() { +std::string MOperand::to_string() const { std::string ret; switch (op_type) { case MOpTag::Imm: ret = fmt::format("{}", value); break; @@ -20,85 +20,117 @@ std::string MOperand::to_string() { return ret; } -std::vector MInstBinary::get_def() { +std::vector MInstBinary::get_def() const { return {dst}; } -std::vector MInstJump::get_def() { +std::vector MInstJump::get_def() const { return {}; } -std::vector MInstBranch::get_def() { +std::vector MInstBranch::get_def() const { return {}; } -std::vector MInstLoad::get_def() { +std::vector MInstLoad::get_def() const { return {dst}; } -std::vector MInstStore::get_def() { +std::vector MInstStore::get_def() const { return {}; } -std::vector MInstMove::get_def() { +std::vector MInstMove::get_def() const { return {dst}; } -std::vector MInstReturn::get_def() { +std::vector MInstReturn::get_def() const { return {}; } -std::vector MInstComment::get_def() { +std::vector MInstComment::get_def() const { return {}; } -std::vector MInstCall::get_def() { - std::vector def; +std::vector MInstCall::get_def() const { // caller-saved regs should also be considered as re-defined - // a0-a7 - for (int i = 0; i < 8; ++i) { - def.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); - } - def.push_back(MOperand::PreClrReg(RV64Reg::t0)); - def.push_back(MOperand::PreClrReg(RV64Reg::t1)); - def.push_back(MOperand::PreClrReg(RV64Reg::t2)); - def.push_back(MOperand::PreClrReg(RV64Reg::t3)); - def.push_back(MOperand::PreClrReg(RV64Reg::t4)); - def.push_back(MOperand::PreClrReg(RV64Reg::t5)); - def.push_back(MOperand::PreClrReg(RV64Reg::t6)); - def.push_back(MOperand::PreClrReg(RV64Reg::ra)); - return def; + return { + MOperand::PreClrReg(RV64Reg::a0), + MOperand::PreClrReg(RV64Reg::a1), + MOperand::PreClrReg(RV64Reg::a2), + MOperand::PreClrReg(RV64Reg::a3), + MOperand::PreClrReg(RV64Reg::a4), + MOperand::PreClrReg(RV64Reg::a5), + MOperand::PreClrReg(RV64Reg::a6), + MOperand::PreClrReg(RV64Reg::a7), + MOperand::PreClrReg(RV64Reg::t0), + MOperand::PreClrReg(RV64Reg::t1), + MOperand::PreClrReg(RV64Reg::t2), + MOperand::PreClrReg(RV64Reg::t3), + MOperand::PreClrReg(RV64Reg::t4), + MOperand::PreClrReg(RV64Reg::t5), + MOperand::PreClrReg(RV64Reg::t6), + MOperand::PreClrReg(RV64Reg::ra), + }; } -std::vector MInstBinary::get_use() { - return {op1, op2}; +std::vector MInstBinary::get_use() const { + std::vector use; + if (op1.is_reg()) use.push_back(op1); + if (op2.is_reg()) use.push_back(op2); + return use; } -std::vector MInstJump::get_use() { +std::vector MInstJump::get_use() const { return {}; } -std::vector MInstBranch::get_use() { - return {op1, op2}; +std::vector MInstBranch::get_use() const { + std::vector use; + if (op1.is_reg()) use.push_back(op1); + if (op2.is_reg()) use.push_back(op2); + return use; } -std::vector MInstLoad::get_use() { +std::vector MInstLoad::get_use() const { + // addr must be reg, offset must not be reg return {addr}; } -std::vector MInstStore::get_use() { +std::vector MInstStore::get_use() const { + // both addr and data must be reg, offset must not be reg return {addr, data}; } -std::vector MInstMove::get_use() { - return {src}; +std::vector MInstMove::get_use() const { + std::vector use; + if (src.is_reg()) use.push_back(src); + return use; } -std::vector MInstReturn::get_use() { +std::vector MInstReturn::get_use() const { return {MOperand::PreClrReg(RV64Reg::a0)}; } -std::vector MInstComment::get_use() { +std::vector MInstComment::get_use() const { return {}; } -std::vector MInstCall::get_use() { +std::vector MInstCall::get_use() const { + // arg-occupied regs get implicitly used here std::vector use; for (int i = 0; i < ir_func->fparam_list.size() && i < 8; ++i) { use.push_back(MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i))); } return use; } + +void MInst::PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty) { + switch (ins_ty) { + case InsType::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break; + case InsType::Tail: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst); break; + default: sysy_assert(0); + } +} + +void MInst::PostNew(sptr(MInst) inst, sptr(MInst) rel_inst, InsType ins_ty) { + switch (ins_ty) { + case InsType::Before: + case InsType::After: + default: sysy_assert(0); + } +} + } // namespace CompSysY \ No newline at end of file diff --git a/src/pass_reg_alloc.cpp b/src/pass_reg_alloc.cpp index 60414e9..2cc54d1 100644 --- a/src/pass_reg_alloc.cpp +++ b/src/pass_reg_alloc.cpp @@ -13,17 +13,34 @@ static std::set set_union(const std::set &u1, const std::set &u2) { pred/succ和前面LLIR里面的定义一致,直接是从那边复制的 def和use集合,说的是在一个bb里面定值/使用的变量的集合 -def[bb] = {var | var is assigned in this bb} -use[bb] = {var | var is used in this bb } +def[inst] = {var | var is assigned in this inst} +:在基本块B中定值,但是定值前在B中没有被引用的变量的集合 +use[inst] = {var | var is used in this inst } +:在基本块B中引用,但是引用前在B中没有被定值的变量集合 live(on one edge) 存在一条从该edge通向var的一个use,且中间不经过任何的def live-in 一个变量在所有的in-edge上都是live的 live-out 一个变量在所有的out-edge上都是live的 + data-flow equation: livein[n] = use[n] union (liveout[n] - def[n]) liveout[n] = union livein[s], for s in succ[n] */ static void liveness_analysis(sptr(MFunction) func) { + // re-set def/use for each bb + for (auto bb : func->bb_list) { + bb->def.clear(); + bb->use.clear(); + for (auto inst : bb->inst_list) { + for (auto &u : inst->get_use()) { + if (!ASSOC_FOUND(bb->def, u)) bb->use.insert(u); + } + for (auto &d : inst->get_def()) { + if (!ASSOC_FOUND(bb->use, d)) bb->def.insert(d); + } + } + } + // this will be run for multiple times, thus have to clear for (auto bb : func->bb_list) { bb->livein = bb->use; @@ -49,6 +66,19 @@ static void liveness_analysis(sptr(MFunction) func) { } bb->livein = newin; } + // std::set outquote = bb->liveout; + // std::set inquote = bb->livein; + // bb->livein = bb->use; + // for (auto elem : bb->liveout) { + // if (!ASSOC_FOUND(bb->def, elem)) bb->livein.insert(elem); + // } + // bb->liveout.clear(); + // for (auto succ : bb->succ_list) { + // bb->liveout.insert(succ->livein.begin(), succ->livein.end()); + // } + // if (bb->liveout != outquote || bb->livein != inquote) { + // changed = true; + // } } } LOG(TRACE) << "Live Analysis done for " << func->ir_func->name; @@ -113,37 +143,36 @@ void PassRegAlloc::build(sptr(MFunction) func) { // forall I \in instructions(b) in reversed-order for (auto inst_it = bb->inst_list.rbegin(); inst_it != bb->inst_list.rend(); ++inst_it) { // if isMoveInst(I) - std::vector def_I; - std::vector use_I; - get_inst_defuse(*inst_it, def_I, use_I); + std::vector def_I = (*inst_it)->get_def(); + std::vector use_I = (*inst_it)->get_use(); if (auto inst_mv = shared_cast(*inst_it)) { - if (inst_mv->dst.need_clr() && inst_mv->src.need_clr()) { + // make sure it is a reg-reg move + if (use_I.size()) { // live <- live - use(I) live.erase(inst_mv->src); // forall n in def(I) UNION use(I) // moveList[n] <- moveList[n] UNION {I} - move_list[inst_mv->dst].insert(inst_mv); - move_list[inst_mv->src].insert(inst_mv); + move_list[inst_mv->dst].insert(inst_mv.get()); + move_list[inst_mv->src].insert(inst_mv.get()); // worklistMoves <- worklistMoves UNION {I} - worklist_moves.insert(inst_mv); + worklist_moves.insert(inst_mv.get()); } } // live <- live UNION def(I) for (auto &d : def_I) { - if (d.need_clr()) live.insert(d); + live.insert(d); } // forall d in def(I) for (auto &d : def_I) { - if (!d.need_clr()) continue; // forall l in live for (auto &l : live) add_edge(l, d); } // live <- use(I) UNION (live - def(I)) for (auto &d : def_I) { - if (d.need_clr()) live.erase(d); + live.erase(d); } for (auto &u : use_I) { - if (u.need_clr()) live.insert(u); + live.insert(u); } } } @@ -163,9 +192,7 @@ void PassRegAlloc::make_work_list(sptr(MFunction) func) { else // 低度数mv无关节点表 simplifyWorklist <- simplifyWorklist U {n} */ - // initial 其实就是所有的虚拟寄存器 - for (auto i = 0; i < func->virt_reg_cnt; ++i) { - auto vr = MOperand::VirtReg(i); + for (auto vr : initial) { if (degree[vr] >= K) { spill_worklist.insert(vr); } @@ -176,10 +203,11 @@ void PassRegAlloc::make_work_list(sptr(MFunction) func) { simplify_worklist.insert(vr); } } + initial.clear(); } // movelist[n] INTERSECT (activemoves UNION worklistmoves) -std::set PassRegAlloc::node_moves(const MOperand &n) { +std::set PassRegAlloc::node_moves(const MOperand &n) { // for empty set, it does not even exists, so do not use `.at(n)` auto ret = move_list[n]; for (auto itr = ret.begin(); itr != ret.end();) { @@ -247,12 +275,13 @@ void PassRegAlloc::simplify() { simplify_worklist.erase(simplify_worklist.begin()); select_stack.push_back(n); auto adjacent_n = adjacent(n); - for (auto &m : adjacent_n) { + for (auto const &m : adjacent_n) { decrement_degree(m); } } void PassRegAlloc::coalesce() { + // for any t in Adjacent(v), s.t. OK(t,u) auto _adj_ok = [&](const MOperand &u, const MOperand &v) -> bool { auto adj_v = adjacent(v); for (auto &t : adj_v) @@ -260,9 +289,11 @@ void PassRegAlloc::coalesce() { return true; }; auto m = *worklist_moves.begin(); - auto u = get_alias(m->dst); - auto v = get_alias(m->src); - if (v.op_type == MOpTag::PreColor) { + auto u = get_alias(m->dst); // x + auto v = get_alias(m->src); // y + // if y in precolored then (u, v) = (y, x) + // else (u,v)=(x,y) + if (v.is_precolored()) { std::swap(u, v); } worklist_moves.erase(m); @@ -270,12 +301,12 @@ void PassRegAlloc::coalesce() { coalesced_moves.insert(m); add_work_list(u); } - else if (v.op_type == MOpTag::PreColor || ASSOC_FOUND(adj_set, std::make_pair(u, v))) { + else if (v.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(u, v))) { constrained_moves.insert(m); add_work_list(u); add_work_list(v); } - else if ((u.op_type == MOpTag::PreColor && _adj_ok(u, v)) || (u.op_type != MOpTag::PreColor && conservative(set_union(adjacent(u), adjacent(v))))) { + else if ((u.is_precolored() && _adj_ok(u, v)) || (!u.is_precolored() && conservative(set_union(adjacent(u), adjacent(v))))) { coalesced_moves.insert(m); combine(u, v); add_work_list(u); @@ -285,19 +316,27 @@ void PassRegAlloc::coalesce() { } } +// 把一个节点放回去继续简化 void PassRegAlloc::add_work_list(const MOperand &u) { - if (u.op_type != MOpTag::PreColor && !move_related(u) && degree.at(u) < K) { + if (!u.is_precolored() && !move_related(u) && degree.at(u) < K) { freeze_worklist.erase(u); simplify_worklist.insert(u); } } - +/* +degree[t] < K || t in precolored || (t,r) in adjSet +*/ bool PassRegAlloc::OK(const MOperand &t, const MOperand &r) { - return degree[t] < K || t.op_type == MOpTag::PreColor || ASSOC_FOUND(adj_set, std::make_pair(t, r)); + return degree[t] < K || t.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(t, r)); } -MOperand PassRegAlloc::get_alias(MOperand n) { - while (ASSOC_FOUND(coalesced_nodes, n)) n = alias[n]; +/* +if n in coalescedNodes then + GetAlias(alias[n]) +else n +*/ +MOperand PassRegAlloc::get_alias(const MOperand &n) { + if (ASSOC_FOUND(coalesced_nodes, n)) return get_alias(alias[n]); return n; } @@ -318,10 +357,8 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) { coalesced_nodes.insert(v); alias[v] = u; // movelist[u] <- movelist[u] UNION movelist[v] - auto &movelist_u = move_list.at(u); - auto &movelist_v = move_list.at(v); - for (auto mv : movelist_v) { - movelist_u.insert(mv); + for (auto mv : move_list.at(v)) { + move_list[u].insert(mv); } // TODO: TrivialCompiler skipped the enablemoves below enable_moves(v); @@ -344,9 +381,10 @@ void PassRegAlloc::freeze() { void PassRegAlloc::freeze_moves(const MOperand &u) { for (auto &m : node_moves(u)) { - auto x = get_alias(m->src); - auto v = get_alias(m->dst); - if (v == get_alias(u)) v = x; + auto &x = m->dst; + auto &y = m->src; + auto v = get_alias(y); + if (v == get_alias(u)) v = get_alias(x); active_moves.erase(m); frozen_moves.insert(m); if (node_moves(v).empty() && degree[v] < K) { @@ -366,25 +404,24 @@ void PassRegAlloc::select_spill() { } } // TODO: heuristic to be improved, other than simply select the max degree + spill_worklist.erase(m); simplify_worklist.insert(m); freeze_moves(m); - spill_worklist.erase(m); } void PassRegAlloc::assign_colors(sptr(MFunction) func) { while (!select_stack.empty()) { auto n = select_stack.back(); select_stack.pop_back(); - // exclude: x0, ra, sp, gp, tp (0, 1, 2, 3, 4) - std::unordered_set ok_colors = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + // directly copy from pre-defined ok_colors + std::unordered_set ok_colors = _ok_colors; for (auto &w : adj_list[n]) { auto alias = get_alias(w); - if (alias.op_type == MOpTag::PreColor || alias.op_type == MOpTag::Colored) { + if (alias.op_type == MOpTag::PreColor) { ok_colors.erase(alias.value); } - else if (ASSOC_FOUND(color, alias)) { - auto color_alias = color[alias]; + else if (ASSOC_FOUND(colored_nodes, alias)) { + auto color_alias = color.at(alias); ok_colors.erase(color_alias.value); } } @@ -403,23 +440,16 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) { else color[n] = color[n_alias]; } - // patch all the color info back to the MCIR tree, note the pointer type here - for (auto bb : func->bb_list) { - for (auto inst : bb->inst_list) { - std::vector def; - std::vector use; - get_inst_defuse(inst, def, use); - for (auto d : def) { - if (ASSOC_FOUND(color, *d)) *d = color.at(*d); - } - for (auto u : use) { - if (ASSOC_FOUND(color, *u)) *u = color.at(*u); - } - } - } } void PassRegAlloc::rewrite_program(sptr(MFunction) func) { + std::set new_temps; +#if 0 + auto gen_tmp_reg = [&]() { + auto vr = func->virt_reg_cnt++; + new_temps.insert(MOperand::VirtReg(vr)); + return vr; + }; for (auto v : spilled_nodes) { LOG(TRACE) << "Spill node " << v.to_string(); for (auto bb : func->bb_list) { @@ -432,13 +462,13 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) { get_inst_defuse(inst, def, use); for (auto d : def) { if (*d != v) continue; - if (vr < 0) vr = func->virt_reg_cnt++; + if (vr < 0) vr = gen_tmp_reg(); d->value = vr; lastdef = inst; } for (auto u : use) { if (*u != v) continue; - if (vr < 0) vr = func->virt_reg_cnt++; + if (vr < 0) vr = gen_tmp_reg(); u->value = vr; if (!lastdef && !firstuse) firstuse = inst; } @@ -446,13 +476,15 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) { } auto gen_off = [&](sptr(MInst) inst) { auto off_imm = MOperand::Imm(func->stack_size); + return off_imm; if (is_in_imm_range(off_imm.value)) { return off_imm; } else { + assert(0); //TODO bug here auto inst_mv = MInstMove::New(inst); inst_mv->src = off_imm; - inst_mv->dst = MOperand::VirtReg(func->virt_reg_cnt++); + inst_mv->dst = MOperand::VirtReg(gen_tmp_reg()); return inst_mv->dst; } }; @@ -471,12 +503,56 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) { } func->stack_size += XLEN; } +#else + for (auto v : spilled_nodes) { + LOG(TRACE) << "Spill node " << v.to_string(); + for (auto bb : func->bb_list) { + for (auto inst : bb->inst_list) { + std::vector def; + std::vector use; + get_inst_defuse(inst, def, use); + for (auto d : def) { + if (*d != v) continue; + auto vr = MOperand::VirtReg(func->virt_reg_cnt++); + new_temps.insert(vr); + auto inst_st = MInstStore::New(inst, XLEN, true); + inst_st->addr = MOperand::PreClrReg(RV64Reg::sp); + inst_st->data = vr; + inst_st->offset = MOperand::Imm(func->stack_size); + auto cmt = MInstComment::New(inst_st); + cmt->comment = fmt::format("spill def {} to stack", d->to_string()); + d->value = vr.value; + } + for (auto u : use) { + if (*u != v) continue; + auto vr = MOperand::VirtReg(func->virt_reg_cnt++); + new_temps.insert(vr); + auto inst_ld = MInstLoad::New(inst, XLEN); + inst_ld->addr = MOperand::PreClrReg(RV64Reg::sp); + inst_ld->dst = vr; + inst_ld->offset = MOperand::Imm(func->stack_size); + auto cmt = MInstComment::New(inst_ld); + cmt->comment = fmt::format("load from spilled use {}", u->to_string()); + u->value = vr.value; + } + } + } + func->stack_size += XLEN; + } +#endif + spilled_nodes.clear(); + initial = colored_nodes; + initial.insert(coalesced_nodes.begin(), coalesced_nodes.end()); + initial.insert(new_temps.begin(), new_temps.end()); + colored_nodes.clear(); + coalesced_nodes.clear(); } /* Internal util for initialize data structures */ void PassRegAlloc::clear() { + // initial.clear(); adj_list.clear(); adj_set.clear(); degree.clear(); @@ -495,9 +571,11 @@ void PassRegAlloc::clear() { frozen_moves.clear(); worklist_moves.clear(); active_moves.clear(); - + spill_space.clear(); // pre-define each pre-colored register's degree as inf - for (int reg = 0; reg < 32; ++reg) degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF}); + for (int reg = 0; reg < 32; ++reg) { + degree.insert({MOperand::PreClrReg((RV64Reg)reg), INF}); + } } /* @@ -516,10 +594,13 @@ void emit_function(std::ostream &ostr, sptr(MFunction) func); void PassRegAlloc::reg_alloc(sptr(MFunction) func) { clear(); - set_bb_def_use(func); liveness_analysis(func); + // std::ofstream dbg("dbgfunc.asm", std::ios::app); + // emit_function(dbg, func); + // dbg.close(); build(func); make_work_list(func); + LOG(TRACE) << "Simplify start for " << func->ir_func->name; bool flag = true; do { flag = false; @@ -527,15 +608,15 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) { simplify(); flag = true; } - if (!worklist_moves.empty()) { + else if (!worklist_moves.empty()) { coalesce(); flag = true; } - if (!freeze_worklist.empty()) { + else if (!freeze_worklist.empty()) { freeze(); flag = true; } - if (!spill_worklist.empty()) { + else if (!spill_worklist.empty()) { select_spill(); flag = true; } @@ -544,7 +625,6 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) { assign_colors(func); if (!spilled_nodes.empty()) { rewrite_program(func); - emit_function(std::cout, func); reg_alloc(func); } } @@ -552,7 +632,27 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) { void PassRegAlloc::run(const MCModule &module) { for (auto func : module.function_list) { LOG(INFO) << "Run " << pass_name << " for func " << func->ir_func->name; + // 初始化initial集合为所有的虚拟寄存器 + initial.clear(); + for (int i = 0; i < func->virt_reg_cnt; ++i) { + auto vr = MOperand::VirtReg(i); + initial.insert(vr); + } reg_alloc(func); + // patch all the color info back to the MCIR tree, note the pointer type here + for (auto bb : func->bb_list) { + for (auto inst : bb->inst_list) { + std::vector def; + std::vector use; + get_inst_defuse(inst, def, use); + for (auto d : def) { + if (ASSOC_FOUND(color, *d)) *d = color.at(*d); + } + for (auto u : use) { + if (ASSOC_FOUND(color, *u)) *u = color.at(*u); + } + } + } } } diff --git a/src/visitor_llir_gen.cpp b/src/visitor_llir_gen.cpp index 76738fe..d0f7030 100644 --- a/src/visitor_llir_gen.cpp +++ b/src/visitor_llir_gen.cpp @@ -416,7 +416,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl if (Value::is(inst->operand_list[0])) { auto op0 = Value::as(inst->operand_list[0]); assert(op0->ir_seqno >= 0); - ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << "to "; + ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << " to "; } else if (Value::is(inst->operand_list[0])) { auto op0 = Value::as(inst->operand_list[0]); @@ -511,7 +511,6 @@ void Visitor::llir_gen(std::ostream &ostr) { << " " << init_value->value << std::endl; } else if (global_var_type->pointed_type->type_tag == Type::TypeTag::ArrayType) { - // sysy_assert(global_var->) auto array_type = std::dynamic_pointer_cast(global_var_type->pointed_type); auto init_value = std::dynamic_pointer_cast(global_var->init_value); if (init_value != nullptr) {