diff --git a/include/common.h b/include/common.h index 10c29d2..81616c4 100644 --- a/include/common.h +++ b/include/common.h @@ -35,7 +35,7 @@ inline sptr(DST) strict_shared_cast(SRC src) { #define STD_FIND(container, val) std::find(container.begin(), container.end(), val) #define STD_FOUND(container, val) (STD_FIND(container, val) != container.end()) -#define ASSOC_FOUND(cont, val) (cont.find(val) != cont.end()) +#define INSET(cont, val) (cont.find(val) != cont.end()) #define INF (0x3f3f3f3f) #define BTWN(v, l, r) (l <= v && v <= r) diff --git a/include/mc_inst.h b/include/mc_inst.h index d0cd786..c18349e 100644 --- a/include/mc_inst.h +++ b/include/mc_inst.h @@ -205,7 +205,7 @@ inline MInstTag inverse_cond(MInstTag src_tag) { } // Instruction insertion type -enum class InsType { Before, After, Head, Tail }; +enum class InsertPos { Before, After, Head, Tail }; class MInst { public: @@ -215,19 +215,27 @@ public: // in other cases, since stack is XLEN-padded, for single signed int variable, ld/lw sd/sw do not make much difference // 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() const = 0; - virtual std::vector get_use() const = 0; + virtual ~MInst() = default; + virtual std::vector get_def() const { + return {}; + }; + virtual std::vector get_def_ptr() { + return {}; + }; + virtual std::vector get_use() const { + return {}; + }; + virtual std::vector get_use_ptr() { + return {}; + }; 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); + static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_pos); + static void PostNew(sptr(MInst) inst, MInstTag tag, sptr(MInst) rel_inst, InsertPos ins_pos); }; class MBasicBlock { @@ -276,40 +284,35 @@ public: MOperand dst; MOperand op1; 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, InsType ins_ty = InsType::Tail) { - auto inst = make_shared(type, parent_bb); + static sptr(MInstBinary) + New(MInstTag type, sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos = InsertPos::Tail) { + auto inst = make_shared(); inst->width = width; - MInst::PostNew(inst, parent_bb, ins_ty); + MInst::PostNew(inst, type, parent_bb, ins_pos); return inst; } - 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); + static sptr(MInstBinary) New(MInstTag type, sptr(MInst) rel_inst, int width, InsertPos ins_pos = InsertPos::Before) { + auto inst = make_shared(); + inst->width = width; + MInst::PostNew(inst, type, rel_inst, ins_pos); return inst; } virtual std::vector get_def() const override; + virtual std::vector get_def_ptr() override; virtual std::vector get_use() const override; + virtual std::vector get_use_ptr() override; }; class MInstJump : public MInst { public: sptr(MBasicBlock) target; - MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jmp, parent_bb) {} static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + auto inst = make_shared(); + PostNew(inst, MInstTag::Jmp, parent_bb, InsertPos::Tail); return inst; } - virtual std::vector get_def() const override; - virtual std::vector get_use() const override; bool is_transfer() const override { return true; } @@ -321,14 +324,13 @@ public: MOperand op1; MOperand op2; MInstTag branch_tag; - MInstBranch(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Branch, parent_bb) {} static sptr(MInstBranch) New(sptr(MBasicBlock) parent_bb) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + auto inst = make_shared(); + PostNew(inst, MInstTag::Branch, parent_bb, InsertPos::Tail); return inst; } - virtual std::vector get_def() const override; virtual std::vector get_use() const override; + virtual std::vector get_use_ptr() override; bool is_transfer() const override { return true; } @@ -339,26 +341,23 @@ public: MOperand dst; MOperand addr; MOperand offset; - MInstLoad(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Load, parent_bb) {} - static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) { + auto inst = make_shared(); inst->width = width; + PostNew(inst, MInstTag::Load, parent_bb, ins_pos); return inst; } - static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, 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); + static sptr(MInstLoad) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) { + auto inst = make_shared(); inst->width = width; + PostNew(inst, MInstTag::Load, rel_inst, ins_pos); return inst; } virtual std::vector get_def() const override; + virtual std::vector get_def_ptr() override; virtual std::vector get_use() const override; + virtual std::vector get_use_ptr() override; }; class MInstStore : public MInst { @@ -366,81 +365,50 @@ public: MOperand data; MOperand addr; MOperand offset; - MInstStore(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Store, parent_bb) {} - static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + static sptr(MInstStore) New(sptr(MBasicBlock) parent_bb, int width, InsertPos ins_pos) { + auto inst = make_shared(); inst->width = width; + PostNew(inst, MInstTag::Store, parent_bb, ins_pos); return inst; } - static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, 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); + static sptr(MInstStore) New(sptr(MInst) rel_inst, int width, InsertPos ins_pos) { + auto inst = make_shared(); inst->width = width; + PostNew(inst, MInstTag::Store, rel_inst, ins_pos); return inst; } - virtual std::vector get_def() const override; virtual std::vector get_use() const override; + virtual std::vector get_use_ptr() override; }; class MInstMove : public MInst { public: MOperand dst; MOperand src; - MInstMove(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Move, parent_bb) {} - static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) { - auto inst = make_shared(parent_bb); - if (insert_begin) - parent_bb->inst_list.push_front(inst); - else - parent_bb->inst_list.push_back(inst); + static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Move, parent_bb, ins_pos); return inst; } - static sptr(MInstMove) 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); + static sptr(MInstMove) New(sptr(MInst) rel_inst, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Move, rel_inst, ins_pos); return inst; } virtual std::vector get_def() const override; + virtual std::vector get_def_ptr() override; virtual std::vector get_use() const override; + virtual std::vector get_use_ptr() override; }; -// class MInstSymbol : public MInst { -// public: -// MOperand dst; -// sptr(GlobalVar) symbol; -// MInstSymbol(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Globsym, parent_bb) {} -// static sptr(MInstSymbol) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) { -// auto inst = make_shared(parent_bb); -// if (insert_begin) -// parent_bb->inst_list.push_front(inst); -// else -// parent_bb->inst_list.push_back(inst); -// return inst; -// } -// }; - class MInstReturn : public MInst { public: - MInstReturn(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Ret, parent_bb) {} - static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) { - auto inst = make_shared(parent_bb); - if (insert_begin) - parent_bb->inst_list.push_front(inst); - else - parent_bb->inst_list.push_back(inst); + static sptr(MInstReturn) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Ret, parent_bb, ins_pos); return inst; } - virtual std::vector get_def() const override; virtual std::vector get_use() const override; bool is_transfer() const override { return true; @@ -450,37 +418,28 @@ public: class MInstComment : public MInst { public: std::string comment; - MInstComment(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Comment, parent_bb) {} - static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + static sptr(MInstComment) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Comment, parent_bb, ins_pos); return inst; } - 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); + static sptr(MInstComment) New(sptr(MInst) rel_inst, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Comment, rel_inst, ins_pos); return inst; } - virtual std::vector get_def() const override; - virtual std::vector get_use() const override; }; class MInstCall : public MInst { public: sptr(Function) ir_func; - MInstCall(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Call, parent_bb) {} - static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb) { - auto inst = make_shared(parent_bb); - parent_bb->inst_list.push_back(inst); + static sptr(MInstCall) New(sptr(MBasicBlock) parent_bb, InsertPos ins_pos) { + auto inst = make_shared(); + PostNew(inst, MInstTag::Call, parent_bb, ins_pos); return inst; } virtual std::vector get_def() const override; + virtual std::vector get_def_ptr() override; virtual std::vector get_use() const override; }; - -void get_inst_defuse(sptr(MInst) inst, std::vector &def, std::vector &use); } // namespace CompSysY \ No newline at end of file diff --git a/include/pass.h b/include/pass.h index aa4315f..ea2184e 100644 --- a/include/pass.h +++ b/include/pass.h @@ -45,6 +45,7 @@ public: 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; private: + // 可以按照指令内容(而不是指针地址)来给Move排序,使得算法具有更好的确定性,便于调试 struct MvCmp { bool operator()(MInstMove *const &lhs, const MInstMove *const &rhs) const { if (lhs->dst != rhs->dst) return lhs->dst < rhs->dst; @@ -59,14 +60,14 @@ private: freezeWorklist:低度数的传送有关的结点表。 spillWorklist:高度数的结点表。 spilledNodes:在本轮中要被溢出的结点集合,初始为空。 - coalescedNodes:已合并的寄存器集合。当合并uV时,将y加人到这个集合中,w则被放回到某个工作表中(或反之)。 + coalescedNodes:已合并的寄存器集合。当合并u,v时,将v加人到这个集合中,u则被放回到某个工作表中(或反之)。 coloredNodes :已成功着色的结点集合。 selectstack:一个包含从图中删除的临时变量的栈 */ - void reg_alloc(sptr(MFunction)); - void build(sptr(MFunction)); + void reg_alloc(MFunction *); + void build(MFunction *); void add_edge(const MOperand &u, const MOperand &v); - void make_work_list(sptr(MFunction) func); + void make_work_list(MFunction *func); bool move_related(const MOperand &n); std::set node_moves(const MOperand &n); std::set adjacent(const MOperand &n); @@ -82,9 +83,11 @@ private: void freeze(); void freeze_moves(const MOperand &u); void select_spill(); - void assign_colors(sptr(MFunction) func); - void rewrite_program(sptr(MFunction) func); + void assign_colors(MFunction *func); + void rewrite_program(MFunction *func); void clear(); + void set_color(MFunction *); + void apply_coalesced(MFunction *); std::map> adj_list; std::set> adj_set; std::map degree; @@ -104,7 +107,6 @@ private: 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/src/main.cpp b/src/main.cpp index 390aa27..d1030a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,11 +63,9 @@ int main(int argc, const char **argv) { auto flg_O0 = arg_parser["-O0"] == true; auto emit_llvm = arg_parser["-emit-llvm"] == true; auto no_asm = arg_parser["-no-asm"] == true; - // std::cout << source_file << " " << output_file << " " << flg_O1 << - // std::endl; #pragma endregion - START_EASYLOGGINGPP(argc, argv); #pragma region Logger + START_EASYLOGGINGPP(argc, argv); el::Configurations defaultConf; defaultConf.setToDefault(); defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%levshort %loc %msg"); diff --git a/src/mc_asmgen.cpp b/src/mc_asmgen.cpp index 2f4ae65..501b9f0 100644 --- a/src/mc_asmgen.cpp +++ b/src/mc_asmgen.cpp @@ -8,12 +8,12 @@ using std::endl; static void bb_debug(std::ostream &ostr, sptr(MBasicBlock) bb) { ostr << "pred:"; for (auto item : bb->pred_list) { - ostr << "L_BB_" << item->id << ","; + ostr << item->to_string() << ","; } ostr << "\n"; ostr << "succ:"; for (auto item : bb->succ_list) { - ostr << "L_BB_" << item->id << ","; + ostr << item->to_string() << ","; } ostr << "\n"; ostr << "livein:"; @@ -312,10 +312,14 @@ static void stack_postprocess(sptr(MFunction) func) { void emit_function(std::ostream &ostr, sptr(MFunction) func) { // function header - ostr << "\t.globl\t" << func->ir_func->name << "\n"; - ostr << "\t.p2align\t1\n"; - ostr << "\t.type\t" << func->ir_func->name << ",@function\n"; - ostr << func->ir_func->name << ":" << endl; + ostr << fmt::format( + "\t.globl\t{0}\n" + "\t.p2align\t1\n" + "\t.type\t{0},@function\n" + "{0}:", + func->ir_func->name + ) + << endl; // entry code // First push callee-saved regs if (!func->regs_to_save.empty()) { diff --git a/src/mc_codegen.cpp b/src/mc_codegen.cpp index c622434..1cfe1e4 100644 --- a/src/mc_codegen.cpp +++ b/src/mc_codegen.cpp @@ -22,9 +22,9 @@ static auto gen_imm(int imm, sptr(MBasicBlock) mc_bb, bool force_reg = false) { 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()); + inst_move = MInstMove::New(mc_bb->inst_list.back(), InsertPos::Before); else - inst_move = MInstMove::New(mc_bb); + inst_move = MInstMove::New(mc_bb, InsertPos::Tail); inst_move->src = operand; inst_move->dst = vr; return vr; @@ -50,7 +50,7 @@ static MOperand value2moperand( // according to RV call conv, we can have a0-a7 for params if (fparam_ndx < 8) { // copy param as an vr in func entry - auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), true); + auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), InsertPos::Head); inst_move->src = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx)); inst_move->dst = vr; } @@ -59,9 +59,6 @@ static MOperand value2moperand( // this need to be further re-located since sp may have changed // FramePtr won't get used here, for perf reason. Ref: // https://stackoverflow.com/questions/13006371/does-omitting-the-frame-pointers-really-have-a-positive-effect-on-performance-an - // TODO Trivial Compiler(THU2020) use an addition move, ~but I am not sure why, deleted temporally~ - // In-case the stack is too large that exceeds limit of imm field, but We first skip this - // auto vr_tmp = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++); int width = 0; if (shared_cast(fparam->type)) width = 4; @@ -70,10 +67,10 @@ static MOperand value2moperand( 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); + inst_load = MInstLoad::New(mc_bb->inst_list.back(), width, InsertPos::Before); else - inst_load = MInstLoad::New(mc_bb, width); - // auto inst_move = MInstMove::New(inst_load); // lui vr_t, + inst_load = MInstLoad::New(mc_bb, width, InsertPos::Tail); + // TODO offset immediate may exceed range inst_load->addr = MOperand::PreClrReg(RV64Reg::sp); inst_load->offset = MOperand::Imm((fparam_ndx - 8) * XLEN); inst_load->dst = vr; @@ -94,7 +91,7 @@ static MOperand value2moperand( // return vr; auto op_glob = MOperand::Glob(glob); if (force_reg) { - auto inst_la = MInstMove::New(mc_bb); + auto inst_la = MInstMove::New(mc_bb, InsertPos::Tail); auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++); // val2mop.insert({ir_value, vr}); inst_la->dst = vr; @@ -173,7 +170,7 @@ void MCModule::IR2MC(const Module &ir_module) { // width is important when load/store to an array address, so be careful int width = XLEN; if (shared_cast(ld->type)) width = 4; - auto mc_li = MInstLoad::New(mc_bb, width); + auto mc_li = MInstLoad::New(mc_bb, width, InsertPos::Tail); mc_li->addr = addr; mc_li->dst = value2moperand(ld, mc_bb, mp_val2op); mc_li->offset = MOperand::Imm(0); @@ -184,7 +181,7 @@ 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_st = MInstStore::New(mc_bb, width); + auto mc_st = MInstStore::New(mc_bb, width, InsertPos::Tail); mc_st->addr = addr; mc_st->data = data; mc_st->offset = MOperand::Imm(0); @@ -208,7 +205,7 @@ void MCModule::IR2MC(const Module &ir_module) { if ((inst->operand_list.size() < 3 && !index0.value) || (inst->operand_list.size() == 3 && index1.is_imm() && !index1.value)) { // a shortcut for zero gep - auto inst_mv = MInstMove::New(mc_bb); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail); inst_mv->dst = dst; inst_mv->src = ptr; VLOG(6) << "trivial gep"; @@ -277,11 +274,11 @@ void MCModule::IR2MC(const Module &ir_module) { if (auto ret = shared_cast(inst)) { if (ret->operand_list.size()) { auto retval = value2moperand(ret->operand_list[0], mc_bb, mp_val2op); - auto inst_mv = MInstMove::New(mc_bb); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail); inst_mv->src = retval; inst_mv->dst = MOperand::PreClrReg(RV64Reg::a0); } - MInstReturn::New(mc_bb); + MInstReturn::New(mc_bb, InsertPos::Tail); continue; } if (auto cal = shared_cast(inst)) { @@ -290,14 +287,14 @@ void MCModule::IR2MC(const Module &ir_module) { for (int i = 1; i < cal->operand_list.size(); ++i) { auto rparam = value2moperand(cal->operand_list[i], mc_bb, mp_val2op, true); if (i <= 8) { - auto inst_move = MInstMove::New(mc_bb); + auto inst_move = MInstMove::New(mc_bb, InsertPos::Tail); inst_move->src = rparam; inst_move->dst = MOperand::PreClrReg(RV64_RegOffset(RV64Reg::a0, i - 1)); } else { int st_off = -(nparams - (i - 1)) * XLEN; auto st_off_imm = gen_imm(st_off, mc_bb); - auto inst_store = MInstStore::New(mc_bb, XLEN); + auto inst_store = MInstStore::New(mc_bb, XLEN, InsertPos::Tail); inst_store->addr = MOperand::PreClrReg(RV64Reg::sp); inst_store->offset = st_off_imm; inst_store->data = rparam; @@ -311,7 +308,7 @@ void MCModule::IR2MC(const Module &ir_module) { add_inst->op2 = gen_imm(XLEN * (nparams - 8), mc_bb); } - auto inst_call = MInstCall::New(mc_bb); + auto inst_call = MInstCall::New(mc_bb, InsertPos::Tail); inst_call->ir_func = strict_shared_cast(cal->operand_list[0]); if (nparams > 8) { @@ -324,7 +321,7 @@ void MCModule::IR2MC(const Module &ir_module) { // handle return value, if exist if (shared_cast(cal->type)) { auto dst = value2moperand(inst, mc_bb, mp_val2op); - auto inst_mv = MInstMove::New(mc_bb); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail); inst_mv->src = MOperand::PreClrReg(RV64Reg::a0); inst_mv->dst = dst; } @@ -412,7 +409,7 @@ void MCModule::IR2MC(const Module &ir_module) { } auto src_imm = gen_imm(res, mc_bb); auto dst = value2moperand(inst, mc_bb, mp_val2op); - auto inst_mv = MInstMove::New(mc_bb); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail); inst_mv->dst = dst; inst_mv->src = src_imm; continue; @@ -503,7 +500,7 @@ void MCModule::IR2MC(const Module &ir_module) { // trivial move auto src = value2moperand(zxt->operand_list[0], mc_bb, mp_val2op); auto dst = value2moperand(inst, mc_bb, mp_val2op); - auto inst_mv = MInstMove::New(mc_bb); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Tail); inst_mv->src = src; inst_mv->dst = dst; continue; @@ -544,7 +541,7 @@ void MCModule::IR2MC(const Module &ir_module) { } for (auto &pmv : par_mv_cur) { - auto inst_mv = MInstMove::New(mc_bb, true); + auto inst_mv = MInstMove::New(mc_bb, InsertPos::Head); inst_mv->src = pmv.src; inst_mv->dst = pmv.dst; } @@ -552,7 +549,7 @@ void MCModule::IR2MC(const Module &ir_module) { 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()); + auto inst_mv = MInstMove::New(pmv_pair.first->inst_list.back(), InsertPos::Before); inst_mv->src = pmv_pair.second.src; inst_mv->dst = pmv_pair.second.dst; } @@ -560,39 +557,4 @@ 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 br = shared_cast(inst)) { - use.push_back(&br->op1); - use.push_back(&br->op2); - return; - } - // if (auto sym = shared_cast(inst)) { - // def.push_back(&sym->dst); - // return; - // } -} - } // namespace CompSysY \ No newline at end of file diff --git a/src/mc_inst.cpp b/src/mc_inst.cpp index 3839ea2..8709020 100644 --- a/src/mc_inst.cpp +++ b/src/mc_inst.cpp @@ -20,36 +20,30 @@ std::string MOperand::to_string() const { return ret; } +#pragma region DEFUSE_UTILS + std::vector MInstBinary::get_def() const { return {dst}; } -std::vector MInstJump::get_def() const { - return {}; -} - -std::vector MInstBranch::get_def() const { - return {}; +std::vector MInstBinary::get_def_ptr() { + return {&dst}; } std::vector MInstLoad::get_def() const { return {dst}; } -std::vector MInstStore::get_def() const { - return {}; +std::vector MInstLoad::get_def_ptr() { + return {&dst}; } std::vector MInstMove::get_def() const { return {dst}; } -std::vector MInstReturn::get_def() const { - return {}; -} - -std::vector MInstComment::get_def() const { - return {}; +std::vector MInstMove::get_def_ptr() { + return {&dst}; } std::vector MInstCall::get_def() const { @@ -74,40 +68,73 @@ std::vector MInstCall::get_def() const { }; } +std::vector MInstCall::get_def_ptr() { + // there is nothing to replace since they are all precolored + return {}; +} + 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() const { - return {}; + +std::vector MInstBinary::get_use_ptr() { + std::vector use; + if (op1.is_reg()) use.push_back(&op1); + if (op2.is_reg()) use.push_back(&op2); + return use; } + 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 MInstBranch::get_use_ptr() { + 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() const { // addr must be reg, offset must not be reg return {addr}; } + +std::vector MInstLoad::get_use_ptr() { + return {&addr}; +} + std::vector MInstStore::get_use() const { // both addr and data must be reg, offset must not be reg return {addr, data}; } + +std::vector MInstStore::get_use_ptr() { + return {&addr, &data}; +} + std::vector MInstMove::get_use() const { std::vector use; if (src.is_reg()) use.push_back(src); return use; } + +std::vector MInstMove::get_use_ptr() { + std::vector use; + if (src.is_reg()) use.push_back(&src); + return use; +} + std::vector MInstReturn::get_use() const { return {MOperand::PreClrReg(RV64Reg::a0)}; } -std::vector MInstComment::get_use() const { - return {}; -} + std::vector MInstCall::get_use() const { // arg-occupied regs get implicitly used here std::vector use; @@ -117,18 +144,25 @@ std::vector MInstCall::get_use() const { return use; } -void MInst::PostNew(sptr(MInst) inst, sptr(MBasicBlock) parent_bb, InsType ins_ty) { +#pragma endregion + +void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_ty) { + inst->inst_tag = tag; + inst->parent_bb = parent_bb; 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; + case InsertPos::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break; + case InsertPos::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) { +void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MInst) rel_inst, InsertPos ins_ty) { + inst->inst_tag = tag; + auto parent_bb = rel_inst->parent_bb; + inst->parent_bb = parent_bb; switch (ins_ty) { - case InsType::Before: - case InsType::After: + case InsertPos::Before: inst->itr = parent_bb->inst_list.insert(rel_inst->itr, inst); break; + case InsertPos::After: inst->itr = parent_bb->inst_list.insert(std::next(rel_inst->itr), inst); break; default: sysy_assert(0); } } diff --git a/src/pass_reg_alloc.cpp b/src/pass_reg_alloc.cpp index 2cc54d1..a9ffc51 100644 --- a/src/pass_reg_alloc.cpp +++ b/src/pass_reg_alloc.cpp @@ -26,17 +26,17 @@ 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) { +static void liveness_analysis(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); + if (!INSET(bb->def, u)) bb->use.insert(u); } for (auto &d : inst->get_def()) { - if (!ASSOC_FOUND(bb->use, d)) bb->def.insert(d); + if (!INSET(bb->use, d)) bb->def.insert(d); } } } @@ -66,49 +66,8 @@ 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; -#if 0 - using std::cout, std::endl; - LOG(TRACE) << "SLA info in " << func->ir_func->name; - for (auto bb : func->bb_list) { - cout << "BB " << bb->ir_bb->name << endl; - cout << " def: "; - for (auto def : bb->def) { - cout << def.to_string() << ", "; - } - cout << "\n"; - cout << " use: "; - for (auto use : bb->use) { - cout << use.to_string() << ", "; - } - cout << "\n"; - cout << " livein: "; - for (auto livein : bb->livein) { - cout << livein.to_string() << ", "; - } - cout << "\n"; - cout << " liveout: "; - for (auto liveout : bb->liveout) { - cout << liveout.to_string() << ", "; - } - cout << "\n"; - } -#endif } void PassRegAlloc::add_edge(const MOperand &u, const MOperand &v) { @@ -136,7 +95,7 @@ void PassRegAlloc::add_edge(const MOperand &u, const MOperand &v) { 然后move_list是将操作数node映射到对应的mv指令上,在这里就加进去了 然后worklist_move是"有可能合并的move指令的集合",这里初始默认认为所有的move都可能合并 */ -void PassRegAlloc::build(sptr(MFunction) func) { +void PassRegAlloc::build(MFunction *func) { for (auto bb : func->bb_list) { // let live = liveout(b) auto live = bb->liveout; @@ -181,7 +140,7 @@ void PassRegAlloc::build(sptr(MFunction) func) { /* 主要就是把待染色的virt_reg分类 */ -void PassRegAlloc::make_work_list(sptr(MFunction) func) { +void PassRegAlloc::make_work_list(MFunction *func) { /* forall n in initial initial <- initial - {n} @@ -212,7 +171,7 @@ std::set PassRegAlloc::node_moves(const MOpera auto ret = move_list[n]; for (auto itr = ret.begin(); itr != ret.end();) { // not found in either set, then remove from movelist - if (!ASSOC_FOUND(active_moves, *itr) && !ASSOC_FOUND(worklist_moves, *itr)) + if (!INSET(active_moves, *itr) && !INSET(worklist_moves, *itr)) itr = ret.erase(itr); else ++itr; @@ -224,7 +183,7 @@ std::set PassRegAlloc::node_moves(const MOpera std::set PassRegAlloc::adjacent(const MOperand &n) { auto ret = adj_list[n]; for (auto itr = ret.begin(); itr != ret.end();) { - if (STD_FOUND(select_stack, *itr) || ASSOC_FOUND(coalesced_nodes, *itr)) + if (STD_FOUND(select_stack, *itr) || INSET(coalesced_nodes, *itr)) itr = ret.erase(itr); else ++itr; @@ -239,7 +198,7 @@ bool PassRegAlloc::move_related(const MOperand &n) { void PassRegAlloc::enable_moves(const MOperand &n) { auto node_moves_n = node_moves(n); for (auto &m : node_moves_n) { - if (ASSOC_FOUND(active_moves, m)) { + if (INSET(active_moves, m)) { active_moves.erase(m); worklist_moves.insert(m); } @@ -301,7 +260,7 @@ void PassRegAlloc::coalesce() { coalesced_moves.insert(m); add_work_list(u); } - else if (v.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(u, v))) { + else if (v.is_precolored() || INSET(adj_set, std::make_pair(u, v))) { constrained_moves.insert(m); add_work_list(u); add_work_list(v); @@ -327,7 +286,7 @@ void PassRegAlloc::add_work_list(const MOperand &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.is_precolored() || ASSOC_FOUND(adj_set, std::make_pair(t, r)); + return degree[t] < K || t.is_precolored() || INSET(adj_set, std::make_pair(t, r)); } /* @@ -336,7 +295,7 @@ if n in coalescedNodes then else n */ MOperand PassRegAlloc::get_alias(const MOperand &n) { - if (ASSOC_FOUND(coalesced_nodes, n)) return get_alias(alias[n]); + if (INSET(coalesced_nodes, n)) return get_alias(alias[n]); return n; } @@ -349,7 +308,7 @@ bool PassRegAlloc::conservative(const std::set &nodes) { } void PassRegAlloc::combine(const MOperand &u, const MOperand &v) { - if (ASSOC_FOUND(freeze_worklist, v)) + if (INSET(freeze_worklist, v)) freeze_worklist.erase(v); else spill_worklist.erase(v); @@ -360,13 +319,12 @@ void PassRegAlloc::combine(const MOperand &u, const MOperand &v) { for (auto mv : move_list.at(v)) { move_list[u].insert(mv); } - // TODO: TrivialCompiler skipped the enablemoves below enable_moves(v); for (auto t : adjacent(v)) { add_edge(t, u); decrement_degree(t); } - if (degree.at(u) >= K && ASSOC_FOUND(freeze_worklist, u)) { + if (degree.at(u) >= K && INSET(freeze_worklist, u)) { freeze_worklist.erase(u); spill_worklist.insert(u); } @@ -409,7 +367,7 @@ void PassRegAlloc::select_spill() { freeze_moves(m); } -void PassRegAlloc::assign_colors(sptr(MFunction) func) { +void PassRegAlloc::assign_colors(MFunction *func) { while (!select_stack.empty()) { auto n = select_stack.back(); select_stack.pop_back(); @@ -420,7 +378,7 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) { if (alias.op_type == MOpTag::PreColor) { ok_colors.erase(alias.value); } - else if (ASSOC_FOUND(colored_nodes, alias)) { + else if (INSET(colored_nodes, alias)) { auto color_alias = color.at(alias); ok_colors.erase(color_alias.value); } @@ -442,84 +400,24 @@ void PassRegAlloc::assign_colors(sptr(MFunction) func) { } } -void PassRegAlloc::rewrite_program(sptr(MFunction) func) { +void PassRegAlloc::rewrite_program(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) { - sptr(MInst) firstuse = nullptr; - sptr(MInst) lastdef = nullptr; - int vr = -1; - 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; - if (vr < 0) vr = gen_tmp_reg(); - d->value = vr; - lastdef = inst; - } - for (auto u : use) { - if (*u != v) continue; - if (vr < 0) vr = gen_tmp_reg(); - u->value = vr; - if (!lastdef && !firstuse) firstuse = inst; - } - // TODO: TrivialCompiler count bb size and add intermediate load/store - } - 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(gen_tmp_reg()); - return inst_mv->dst; - } - }; - if (firstuse) { - auto inst_ld = MInstLoad::New(firstuse, XLEN); - inst_ld->addr = MOperand::PreClrReg(RV64Reg::sp); - inst_ld->dst = MOperand::VirtReg(vr); - inst_ld->offset = gen_off(inst_ld); - } - if (lastdef) { - auto inst_st = MInstStore::New(lastdef, XLEN, true); - inst_st->addr = MOperand::PreClrReg(RV64Reg::sp); - inst_st->data = MOperand::VirtReg(vr); - inst_st->offset = gen_off(inst_st); - } - } - 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); + auto def = inst->get_def_ptr(); + auto use = inst->get_use_ptr(); + // TODO offset immediate may exceed range 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); + auto inst_st = MInstStore::New(inst, XLEN, InsertPos::After); 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); + auto cmt = MInstComment::New(inst_st, InsertPos::Before); cmt->comment = fmt::format("spill def {} to stack", d->to_string()); d->value = vr.value; } @@ -527,11 +425,11 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) { if (*u != v) continue; auto vr = MOperand::VirtReg(func->virt_reg_cnt++); new_temps.insert(vr); - auto inst_ld = MInstLoad::New(inst, XLEN); + auto inst_ld = MInstLoad::New(inst, XLEN, InsertPos::Before); 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); + auto cmt = MInstComment::New(inst_ld, InsertPos::Before); cmt->comment = fmt::format("load from spilled use {}", u->to_string()); u->value = vr.value; } @@ -539,7 +437,7 @@ void PassRegAlloc::rewrite_program(sptr(MFunction) func) { } func->stack_size += XLEN; } -#endif + spilled_nodes.clear(); initial = colored_nodes; initial.insert(coalesced_nodes.begin(), coalesced_nodes.end()); @@ -571,7 +469,6 @@ 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}); @@ -590,38 +487,74 @@ if !spilledNodes.empty() then RewriteProgram Main() */ -void emit_function(std::ostream &ostr, sptr(MFunction) func); -void PassRegAlloc::reg_alloc(sptr(MFunction) func) { +void PassRegAlloc::apply_coalesced(MFunction *func) { + for (auto bb : func->bb_list) { + for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end(); ) { + auto inst = *itr; + auto defs = inst->get_def_ptr(); + auto uses = inst->get_use_ptr(); + for (auto def : defs) { + if (!INSET(coalesced_nodes, *def)) continue; + *def = get_alias(*def); + } + for (auto use : uses) { + if (!INSET(coalesced_nodes, *use)) continue; + *use = get_alias(*use); + } + if (auto mv = shared_cast(inst)) { + if (mv->src == mv->dst) { + itr = mv->parent_bb->inst_list.erase(mv->itr); + continue; + } + } + ++ itr; + } + } +} + +void PassRegAlloc::reg_alloc(MFunction *func) { clear(); liveness_analysis(func); - // std::ofstream dbg("dbgfunc.asm", std::ios::app); - // emit_function(dbg, func); - // dbg.close(); + LOG(TRACE) << "[RegAlloc] LiveAnalysis done"; build(func); + LOG(TRACE) << "[RegAlloc] ConflictGraph built"; make_work_list(func); - LOG(TRACE) << "Simplify start for " << func->ir_func->name; - bool flag = true; - do { - flag = false; + LOG(TRACE) << "[RegAlloc] Start Simplify"; + bool first_coalesce = false, first_freeze = false, first_selectspill = false; + while (true) { if (!simplify_worklist.empty()) { simplify(); - flag = true; } else if (!worklist_moves.empty()) { + if (!first_coalesce) { + LOG(TRACE) << "[RegAlloc] Start coalesce"; + first_coalesce = true; + } coalesce(); - flag = true; } else if (!freeze_worklist.empty()) { + if (!first_freeze) { + LOG(TRACE) << "[RegAlloc] Start freeze"; + first_freeze = true; + } freeze(); - flag = true; } else if (!spill_worklist.empty()) { + if (!first_selectspill) { + LOG(TRACE) << "[RegAlloc] Start select spill"; + first_selectspill = true; + apply_coalesced(func); // 2m47s(on)/3m6s(off) for 8.*\.sy + // For a faster algorithm, keep all the coalesces found before the first call to Select-Spill and rewrite the + // program to eliminate the coalesced move instructions and temporaries. + } select_spill(); - flag = true; } - } while (flag); - LOG(TRACE) << "Simplify done for " << func->ir_func->name; + else { + break; + } + } + LOG(TRACE) << "[RegAlloc] Start Coloring"; assign_colors(func); if (!spilled_nodes.empty()) { rewrite_program(func); @@ -629,6 +562,21 @@ void PassRegAlloc::reg_alloc(sptr(MFunction) func) { } } +void PassRegAlloc::set_color(MFunction *func) { + for (auto bb : func->bb_list) { + for (auto inst : bb->inst_list) { + auto def = inst->get_def_ptr(); + auto use = inst->get_use_ptr(); + for (auto d : def) { + if (INSET(color, *d)) *d = color.at(*d); + } + for (auto u : use) { + if (INSET(color, *u)) *u = color.at(*u); + } + } + } +} + void PassRegAlloc::run(const MCModule &module) { for (auto func : module.function_list) { LOG(INFO) << "Run " << pass_name << " for func " << func->ir_func->name; @@ -638,21 +586,9 @@ void PassRegAlloc::run(const MCModule &module) { auto vr = MOperand::VirtReg(i); initial.insert(vr); } - reg_alloc(func); + reg_alloc(func.get()); // 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); - } - } - } + set_color(func.get()); } }