From 805d36adda17433861b6dce1dff133c0e6097ac3 Mon Sep 17 00:00:00 2001 From: lxq <877250099@qq.com> Date: Wed, 8 Feb 2023 01:16:45 +0800 Subject: [PATCH] ready to finish all the functional test! --- Reports/5-bonus/report.md | 6 ++ include/codegen/codegen.hpp | 34 ++++++--- include/codegen/liverange.hpp | 20 +++-- include/codegen/regalloc.hpp | 13 ++-- src/codegen/codegen.cpp | 136 ++++++++++++++++++---------------- src/codegen/liverange.cpp | 29 +++++--- src/codegen/regalloc.cpp | 67 +++++++++++------ 7 files changed, 187 insertions(+), 118 deletions(-) diff --git a/Reports/5-bonus/report.md b/Reports/5-bonus/report.md index c285c22..3fd5370 100644 --- a/Reports/5-bonus/report.md +++ b/Reports/5-bonus/report.md @@ -161,4 +161,10 @@ op6: <8, 8> - `tests/4-ir-opt/testcases/GVN/performance` +## 局限性 + +- GEP的取巧设计 + +- 未考虑指令寻址的立即数 + - diff --git a/include/codegen/codegen.hpp b/include/codegen/codegen.hpp index c8cbf5a..a5ae5ec 100644 --- a/include/codegen/codegen.hpp +++ b/include/codegen/codegen.hpp @@ -15,10 +15,12 @@ #include #define __PRINT_ORI__ -#define __RO_PART__ +// #define __RO_PART__ #define __PRINT_COMMENT__ // #a = 8, #t = 9, reserve $t0, $t1 for temporary -#define R_USABLE 17 - 2 +#define R_USABLE (17 - 2) +// #fa = 8, #ft=16, reserve $ft0, $ft1 for temporary +#define FR_USABLE (24 - 2) #define ARG_R 8 #include @@ -40,7 +42,12 @@ using std::vector; class CodeGen { public: - CodeGen(Module *m_) : m(m_), LRA(m_, phi_map), RA(R_USABLE, ARG_R) {} + CodeGen(Module *m_) + : cmp_zext_cnt(0) + , m(m_) + , LRA(m_, phi_map) + , RA_int(R_USABLE, false) + , RA_float(FR_USABLE, true) {} string print() { string result; @@ -77,7 +84,8 @@ class CodeGen { vector output; // register allocation LRA::LiveRangeAnalyzer LRA; - RA::RegAllocator RA; + LRA::LVITS LVITS_int, LVITS_float; + RA::RegAllocator RA_int, RA_float; // some instruction has lvalue, but is stack-allocated, // we need this variable to track the reg name which has rvalue. // this variable is maintain by gencopy() and LoadInst. @@ -147,7 +155,7 @@ class CodeGen { gencopy(lhs_reg, rhs_reg, is_float); return true; } - void gencopy(string lhs_reg, string rhs_reg, bool is_float = false) { + void gencopy(string lhs_reg, string rhs_reg, bool is_float) { if (rhs_reg != lhs_reg) { if (is_float) output.push_back("fmov.s " + lhs_reg + ", " + rhs_reg); @@ -215,7 +223,9 @@ class CodeGen { return true; if (instr->is_fcmp() or instr->is_cmp() or instr->is_zext()) return true; - if (RA.get().find(instr) != RA.get().end()) + auto regmap = (instr->get_type()->is_float_type() ? RA_float.get() + : RA_int.get()); + if (regmap.find(instr) != regmap.end()) return true; return false; @@ -225,17 +235,23 @@ class CodeGen { return (is_float ? "$ft" : "$t") + to_string(i); } - static string regname(int i, bool is_float = false) { + static string regname(uint i, bool is_float) { string name; if (is_float) { - assert(false && "not implemented!"); + // assert(false && "not implemented!"); + if (1 <= i and i <= 8) + name = "$fa" + to_string(i - 1); + else if (9 <= i and i <= FR_USABLE) + name = "$ft" + to_string(i - 9 + 2); + else + name = "WRONG_REG_" + to_string(i); } else { if (1 <= i and i <= 8) name = "$a" + to_string(i - 1); else if (9 <= i and i <= R_USABLE) name = "$t" + to_string(i - 9 + 2); else - name = "WRONG_REG" + to_string(i); + name = "WRONG_REG_" + to_string(i); } return name; } diff --git a/include/codegen/liverange.hpp b/include/codegen/liverange.hpp index bef6acf..46b379a 100644 --- a/include/codegen/liverange.hpp +++ b/include/codegen/liverange.hpp @@ -15,12 +15,14 @@ using std::string; using std::to_string; using std::vector; +#define UNINITIAL -1 + #define __LRA_PRINT__ namespace LRA { struct Interval { - Interval(int a = -1, int b = -1) : i(a), j(b) {} + Interval(int a = UNINITIAL, int b = UNINITIAL) : i(a), j(b) {} int i; // 0 means uninitialized int j; }; @@ -49,15 +51,17 @@ class LiveRangeAnalyzer { // void run(); void run(Function *); void clear(); - void print(Function *func, bool printSet = false, bool printInt = false) const; - string print_liveSet(const LiveSet &ls) const { + void print(Function *func, + bool printSet = false, + bool printInt = false) const; + static string print_liveSet(const LiveSet &ls) { string s = "[ "; for (auto k : ls) s += k->get_name() + " "; s += "]"; return s; } - string print_interval(Interval &i) const { + static string print_interval(const Interval &i) { return "<" + to_string(i.i) + ", " + to_string(i.j) + ">"; } const LVITS &get() { return liveIntervals; } @@ -91,8 +95,12 @@ class LiveRangeAnalyzer { LiveSet transferFunction(Instruction *); public: - const decltype(instr_id) &get_instr_id() { return instr_id; } - const decltype(intervalmap) &get_interval_map() { return intervalmap; } + const decltype(instr_id) &get_instr_id() const { return instr_id; } + const decltype(intervalmap) &get_interval_map() const { + return intervalmap; + } + const decltype(IN) &get_in_set() const { return IN; } + const decltype(OUT) &get_out_set() const { return OUT; } }; } // namespace LRA #endif diff --git a/include/codegen/regalloc.hpp b/include/codegen/regalloc.hpp index c67b70d..c90b062 100644 --- a/include/codegen/regalloc.hpp +++ b/include/codegen/regalloc.hpp @@ -14,24 +14,27 @@ using namespace LRA; namespace RA { #define MAXR 32 +#define ARG_MAX_R 8 struct ActiveCMP { bool operator()(LiveInterval const &lhs, LiveInterval const &rhs) const { if (lhs.first.j != rhs.first.j) return lhs.first.j < rhs.first.j; - else + else if (lhs.first.i != rhs.first.i) return lhs.first.i < rhs.first.i; + else + return lhs.second < rhs.second; } }; class RegAllocator { public: - RegAllocator(const uint R_, const uint ARG_R_) - : R(R_), ARG_MAX_R(ARG_R_), used{false} { + RegAllocator(const uint R_, bool fl) : FLOAT(fl), R(R_), used{false} { + cout << "RegAllocator initialize: R=" << R << endl; assert(R <= MAXR); } RegAllocator() = delete; - bool no_reg_alloca(Value *v) const; + static bool no_reg_alloca(Value *v); // input set is sorted by increasing start point void LinearScan(const LVITS &, Function *); const map &get() const { return regmap; } @@ -42,8 +45,8 @@ class RegAllocator { private: Function *cur_func; + const bool FLOAT; const uint R; - const uint ARG_MAX_R; bool used[MAXR + 1]; // index range: 1 ~ R map regmap; // sorted by increasing end point diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 18da1aa..7f827fb 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -8,11 +8,14 @@ #include "Type.h" #include "Value.h" #include "ast.hpp" +#include "regalloc.hpp" +#include "syntax_analyzer.h" #include #include #include #include +#include #include #include #include @@ -43,7 +46,7 @@ CodeGen::getRegName(Value *v, int i) const { bool find; string name; bool is_float = v->get_type()->is_float_type(); - auto regmap = RA.get(); + auto regmap = (is_float ? RA_float.get() : RA_int.get()); if (regmap.find(v) == regmap.end()) { name = tmpregname(i, is_float); find = false; @@ -75,7 +78,6 @@ CodeGen::getPhiMap() { void CodeGen::run() { - // TODO: implement // 以下内容生成 int main() { return 0; } 的汇编代码 getPhiMap(); output.push_back(".text"); @@ -94,14 +96,19 @@ CodeGen::run() { for (auto &func : m->get_functions()) { if (not func.is_declaration()) { LRA.run(&func); - RA.LinearScan(LRA.get(), &func); + RA_int.LinearScan(LRA.get(), &func); + RA_float.LinearScan(LRA.get(), &func); - std::cout << "register map for function: " << func.get_name() + std::cout << "integer register map for function: " + << func.get_name() << std::endl; + RA_int.print([](int i) { return regname(i, false); }); + std::cout << "float register map for function: " << func.get_name() << std::endl; - RA.print([](int i) { return regname(i); }); + RA_float.print([](int i) { return regname(i, true); }); - auto regmap = RA.get(); for (auto [_, op] : LRA.get()) { + auto regmap = op->get_type()->is_float_type() ? RA_float.get() + : RA_int.get(); if (regmap.find(op) == regmap.end()) std::cout << "no reg belongs to " << op->get_name() << std::endl; @@ -177,8 +184,6 @@ CodeGen::ptrContent2reg(Value *ptr, string dest_reg) { assert(false && "unknown type"); } -void IR2assem(ZextInst *); - string CodeGen::value2reg(Value *v, int i, string recommend) { bool is_float = v->get_type()->is_float_type(); @@ -193,7 +198,6 @@ CodeGen::value2reg(Value *v, int i, string recommend) { if (v == CONST_0) return "$zero"; auto constant = static_cast(v); -#ifdef __RO_PART__ if (ROdata.find(constant) == ROdata.end()) ROdata[constant] = ".LC" + to_string(ROdata.size()); string instr_ir, addr = ROdata[constant]; @@ -206,34 +210,6 @@ CodeGen::value2reg(Value *v, int i, string recommend) { // bug here: maybe output.push_back("la.local " + tmp_ireg + ", " + addr); output.push_back(instr_ir + " " + reg_name + ", " + tmp_ireg + ", 0"); -#else - - if (dynamic_cast(constant)) { - int k = static_cast(constant)->get_value(); - if ((k & 0xfff) != k) { - output.push_back("lu12i.w " + reg_name + ", " + - to_string(k >> 12)); - output.push_back("ori " + reg_name + ", " + reg_name + ", " + - to_string(k & 0xfff)); - } else - output.push_back("ori " + reg_name + ", $r0, " + to_string(k)); - } else if (dynamic_cast(constant)) { - // move the binary code to int-reg, then use movgr2fr to move the - // value to float-reg - float k = static_cast(constant)->get_value(); - int hex_int = *(uint32_t *)&k; - if ((hex_int & 0xfff) != hex_int) - output.push_back("lu12i.w " + tmp_ireg + ", " + - to_string(hex_int >> 12)); - if (hex_int & 0xfff) - output.push_back("ori " + tmp_ireg + ", " + tmp_ireg + ", " + - to_string(hex_int & 0xfff)); - output.push_back("movgr2fr.w " + reg_name + ", " + tmp_ireg); - // output.push_back("ffint.s.w " + reg_name + ", " + reg_name); - - } else - assert(false && "wait for completion"); -#endif } else if (dynamic_cast(v)) { output.push_back("la.local " + reg_name + ", " + v->get_name()); } else if (dynamic_cast(v)) { @@ -250,7 +226,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) { if (*iter == v) break; if (id <= ARG_R) - return regname(ARG_R); + return regname(ARG_R, is_float); else { string instr_ir = is_float ? "fld" : "ld"; auto suff = suffix(v->get_type()); @@ -270,7 +246,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) { makeSureInRange(instr_ir + suff, reg_name, FP, - off.at(v), + -off.at(v), instr_ir + "x" + suff, 12, reg_name); @@ -356,9 +332,10 @@ CodeGen::IR2assem(FpToSiInst *instr) { assert(instr->get_operand(0)->get_type() == m->get_float_type()); assert(instr->get_dest_type() == m->get_int32_type()); string f_reg = value2reg(instr->get_operand(0)); + string f_treg = "$ft0"; auto [i_reg, _] = getRegName(instr); - output.push_back("ftintrz.w.s " + f_reg + ", " + f_reg); - output.push_back("movfr2gr.s " + i_reg + ", " + f_reg); + output.push_back("ftintrz.w.s " + f_treg + ", " + f_reg); + output.push_back("movfr2gr.s " + i_reg + ", " + f_treg); gencopy(instr, i_reg); } void @@ -394,7 +371,7 @@ CodeGen::bool2branch(Instruction *instr) { ->is_zext()) { // something like: // %op0 = icmp slt i32 1, 2 # deepest - // %op1 = zext i1 %op0 to i32 + // %op1 = zext i1 %op0 to i32 # this zext has no register // %op2 = icmp ne i32 %op1, 0 // br i1 %op2, label %label3, label %label5 auto deepest = static_cast( @@ -547,13 +524,16 @@ CodeGen::pass_arguments(CallInst *instr) { string t0_contained; for (auto arg_id : order) { auto arg_value = instr->get_operand(arg_id); - auto t_reg = arg_value->get_type()->is_float_type() ? "$ft0" : "$t0"; + auto arg_is_float = arg_value->get_type()->is_float_type(); + auto arg_reg_aid = regname(arg_id, arg_is_float); + auto t_reg = arg_is_float ? "$ft0" : "$t0"; + // the value is actually in v_reg, and the arg corresponds to + // arg_reg_aid(only right when arg_id <= 8) v_reg = value2reg(arg_value, 1); - if (backup[arg_id]) { // still relied by some argument due to cycle - auto a_id = regname(arg_id); - assert(not wroten[a_id]); - gencopy(t_reg, a_id); - t0_contained = a_id; + if (backup[arg_id]) { // a_id still relied by some argument due to cycle + assert(not wroten[arg_reg_aid]); + gencopy(t_reg, arg_reg_aid, arg_is_float); + t0_contained = arg_reg_aid; } // in case that the src register has been wroten if (wroten[v_reg]) { @@ -562,7 +542,7 @@ CodeGen::pass_arguments(CallInst *instr) { } if (arg_id <= ARG_R) { // pass by register - gencopy(regname(arg_id), v_reg); + gencopy(arg_reg_aid, v_reg, arg_is_float); } else { // pass by stack instr_ir = (arg_value->get_type()->is_float_type() ? "fst" : "st"); suff = suffix(arg_value->get_type()); @@ -575,7 +555,7 @@ CodeGen::pass_arguments(CallInst *instr) { * $sp, " + to_string(func_arg_off.at(func).at(arg_id))); */ } - wroten[regname(arg_id)] = true; + wroten[arg_reg_aid] = true; } } @@ -585,24 +565,47 @@ CodeGen::IR2assem(CallInst *instr) { auto func_argN = func_arg_N.at(func); // analyze the registers that need to be stored int cur_i = LRA.get_instr_id().at(instr); - auto regmap = RA.get(); + auto regmap_int = RA_int.get(); + auto regmap_float = RA_float.get(); // int storeN = 0; vector> store_record; for (auto [op, interval] : LRA.get_interval_map()) { - if (RA.no_reg_alloca(op)) + if (RA::RegAllocator::no_reg_alloca(op)) continue; - if (not instr->get_function_type() - ->get_return_type() - ->is_void_type() and - regmap.find(instr) != regmap.end() and regmap.at(instr) == 1) + auto [name, find] = getRegName(op); + if (not find) continue; - if (interval.i < cur_i and cur_i <= interval.j) { + auto op_type = op->get_type(); + auto op_is_float = op_type->is_float_type(); + if (not instr->get_function_type()->get_return_type()->is_void_type()) { + // if the called function return a value, and the mapped register is + // just $a0/$fa0, there is no need for restore + bool ret_float = + instr->get_function_type()->get_return_type()->is_float_type(); + auto ®map_ret = (ret_float ? regmap_float : regmap_int); + if (regmap_ret.find(instr) != regmap_ret.end() and + regmap_ret.at(instr) == 1) + if (name == (ret_float ? "$fa0" : "a0")) + continue; + } + bool restore = false; + if (interval.i == interval.j) + ; + else if (interval.i < cur_i and cur_i < interval.j) + restore = true; + else if (interval.i == cur_i) { + auto inset = LRA.get_in_set().at(cur_i); + restore = inset.find(op) != inset.end(); + } else + ; + if (restore) { cout << "At point " << cur_i << ", restore for " << op->get_name() << ", interval " << LRA.print_interval(interval) << endl; - int tplen = typeLen(op->get_type()); + int tplen = typeLen(op_type); storeN = ALIGN(storeN, tplen) + tplen; - auto name = regname(regmap.at(op), op->get_type()->is_float_type()); + auto name = regname( + (op_is_float ? regmap_float : regmap_int).at(op), op_is_float); store_record.push_back({op, name, storeN}); } } @@ -717,7 +720,7 @@ CodeGen::IR2assem(ReturnInst *instr) { void CodeGen::IR2assem(ZextInst *instr) { - if (RA.no_reg_alloca(instr)) + if (RA::RegAllocator::no_reg_alloca(instr)) return; assert(instr->get_num_operand() == 1); auto cmp_instr = instr->get_operand(0); @@ -726,8 +729,6 @@ CodeGen::IR2assem(ZextInst *instr) { assert(icmp_instr or fcmp_instr); auto [dest_reg, _] = getRegName(instr); - auto reg1 = value2reg(icmp_instr->get_operand(0), 0); - auto reg2 = value2reg(icmp_instr->get_operand(1), 1); string instr_ir; bool reverse = false, flip = false, check = false; @@ -758,6 +759,8 @@ CodeGen::IR2assem(ZextInst *instr) { flip = true; break; } + auto reg1 = value2reg(icmp_instr->get_operand(0), 0); + auto reg2 = value2reg(icmp_instr->get_operand(1), 1); output.push_back( instr_ir + " " + dest_reg + ", " + (reverse ? (reg2 + ", " + reg1) : (reg1 + ", " + reg2))); @@ -776,7 +779,7 @@ CodeGen::IR2assem(ZextInst *instr) { instr_ir = "fcmp.ceq.s"; break; case FCmpInst::NE: - instr_ir = "fcmp.cun.s"; + instr_ir = "fcmp.cne.s"; break; case FCmpInst::GT: instr_ir = "fcmp.cle.s"; @@ -793,11 +796,14 @@ CodeGen::IR2assem(ZextInst *instr) { instr_ir = "fcmp.cle.s"; break; } + auto reg1 = value2reg(fcmp_instr->get_operand(0), 0); + auto reg2 = value2reg(fcmp_instr->get_operand(1), 1); string cmp_reg = "$fcc0"; - auto label = "cmp_zext_" + to_string(++cmp_zext_cnt) + ":"; + auto label = "cmp_zext_" + to_string(++cmp_zext_cnt); output.push_back(instr_ir + " " + cmp_reg + ", " + reg1 + ", " + reg2); output.push_back("or " + dest_reg + ", $zero, $zero"); - output.push_back("bceqz " + cmp_reg + ", " + label); + output.push_back((reverse ? "bcnez " : "bceqz ") + cmp_reg + ", " + + label); output.push_back("addi.w " + dest_reg + ", $zero, 1"); output.push_back(label + ":"); } diff --git a/src/codegen/liverange.cpp b/src/codegen/liverange.cpp index df28edf..1ba7f11 100644 --- a/src/codegen/liverange.cpp +++ b/src/codegen/liverange.cpp @@ -125,31 +125,34 @@ LiveRangeAnalyzer::run(Function *func) { } } // argument should be in the IN-set of Entry + assert(IN.find(0) == IN.end() and OUT.find(0) == OUT.end() && + "no instr_id will be mapped to 0"); + IN[0] = OUT[0] = {}; for (auto arg : func->get_args()) - IN[1].insert(arg); + IN[0].insert(arg); make_interval(func); #ifdef __LRA_PRINT__ - print(func, true, true); + print(func, false, true); #endif } void LiveRangeAnalyzer::make_interval(Function *) { - for (int time = 1; time <= ir_cnt; ++time) { + for (int time = 0; time <= ir_cnt; ++time) { for (auto op : IN.at(time)) { auto &interval = intervalmap[op]; - if (interval.i == -1) // uninitialized - interval.i = time - 1; + if (interval.i == UNINITIAL) // uninitialized + interval.i = interval.j = time; else - interval.j = time - 1; + interval.j = time; } for (auto op : OUT.at(time)) { auto &interval = intervalmap[op]; - if (interval.i == -1) // uninitialized - interval.i = time; + if (interval.i == UNINITIAL) // uninitialized + interval.i = interval.j = time + 1; else - interval.j = time; + interval.j = time + 1; } } for (auto &[op, interval] : intervalmap) @@ -197,6 +200,11 @@ LiveRangeAnalyzer::print(Function *func, bool printSet, bool printInt) const { // for debug cout << "Function " << func->get_name() << endl; + cout << "0. Entry" << endl; + if (printSet) { + cout << "\tin-set: " + print_liveSet(IN.at(0)) << "\n"; + cout << "\tout-set: " + print_liveSet(OUT.at(0)) << "\n"; + } for (auto &bb : func->get_basic_blocks()) { for (auto &instr : bb.get_instructions()) { if (instr.is_phi()) // ignore phi @@ -220,8 +228,7 @@ LiveRangeAnalyzer::print(Function *func, } } // normal ir - cout << instr_id.at(&instr) << ". " << instr.print() << " # " - << &instr << endl; + cout << instr_id.at(&instr) << ". " << instr.print() << endl; if (not printSet) continue; auto idx = instr_id.at(&instr); diff --git a/src/codegen/regalloc.cpp b/src/codegen/regalloc.cpp index a8b4696..f56840c 100644 --- a/src/codegen/regalloc.cpp +++ b/src/codegen/regalloc.cpp @@ -10,6 +10,9 @@ using std::for_each; using namespace RA; +#define ASSERT_CMPINST_USED_ONCE(cmpinst) \ + (assert(cmpinst->get_use_list().size() == 1)) + int get_arg_id(Argument *arg) { auto args = arg->get_parent()->get_args(); @@ -23,7 +26,7 @@ get_arg_id(Argument *arg) { } bool -RegAllocator::no_reg_alloca(Value *v) const { +RegAllocator::no_reg_alloca(Value *v) { auto instr = dynamic_cast(v); auto arg = dynamic_cast(v); if (instr) { @@ -31,21 +34,26 @@ RegAllocator::no_reg_alloca(Value *v) const { if (instr->is_alloca() or instr->is_cmp() or instr->is_fcmp()) return true; else if (instr->is_zext()) { // only alloca for true use - for (auto use : instr->get_use_list()) - if (not dynamic_cast(use.val_)->is_br()) { - auto instr = static_cast(use.val_); - if (instr->is_cmp()) { // special case for cmp again - auto cmp = static_cast(instr); - assert(cmp->get_cmp_op() == CmpInst::NE); - auto uses = instr->get_use_list(); - assert(uses.size() == 1 and - dynamic_cast(uses.begin()->val_) - ->is_br()); + bool alloc; + ASSERT_CMPINST_USED_ONCE(instr); + auto use_ins = dynamic_cast( + instr->get_use_list().begin()->val_); + // assert(use_ins != nullptr && "should only be instruction?"); + if (use_ins->is_cmp() and + static_cast(use_ins)->get_cmp_op() == CmpInst::NE) { + // this case: + // %op0 = icmp slt i32 1, 2 + // %op1 = zext i1 %op0 to i32 + // %op2 = icmp ne i32 %op1, 0 # <- if judges to here + // br i1 %op2, label %label3, label %label5 + ASSERT_CMPINST_USED_ONCE(use_ins); + auto use2_ins = dynamic_cast( + use_ins->get_use_list().begin()->val_); + alloc = not(use2_ins->is_br()); + } else + alloc = true; - } else - return false; - } - return true; + return not(alloc); } else // then always allocate return false; } @@ -64,19 +72,22 @@ RegAllocator::reset(Function *func) { } int -RegAllocator::ReserveForArg(const LVITS &Liveints) { +RegAllocator::ReserveForArg(const LVITS &liveints) { auto args = cur_func->get_args(); - auto it_int = Liveints.begin(); + auto it_int = liveints.begin(); auto it_arg = args.begin(); int reg; for (reg = 1; reg <= args.size() and reg <= ARG_MAX_R; ++reg) { auto arg = *it_arg; - auto liveint = *it_int; - assert(arg == liveint.second && "arg should be in order in liveints"); + if (not(FLOAT ^ arg->get_type()->is_float_type())) { + auto liveint = *it_int; + assert(arg == liveint.second && + "arg should be in order in liveints"); - used[reg] = true; - regmap[arg] = reg; - active.insert(liveint); + used[reg] = true; + regmap[arg] = reg; + active.insert(liveint); + } ++it_arg, ++it_int; } return reg; @@ -88,6 +99,8 @@ RegAllocator::LinearScan(const LVITS &liveints, Function *func) { ReserveForArg(liveints); int reg; for (auto liveint : liveints) { + if (FLOAT ^ liveint.second->get_type()->is_float_type()) + continue; if (dynamic_cast(liveint.second)) { continue; } @@ -99,6 +112,13 @@ RegAllocator::LinearScan(const LVITS &liveints, Function *func) { else { for (reg = 1; reg <= R and used[reg]; ++reg) ; + if (reg == 16) { + for (auto [interval, v] : active) { + cout << "already allocated: " << v->get_name() << " ~ " + << regmap.at(v) << endl; + } + assert(false); + } used[reg] = true; regmap[liveint.second] = reg; active.insert(liveint); @@ -108,10 +128,12 @@ RegAllocator::LinearScan(const LVITS &liveints, Function *func) { void RegAllocator::ExpireOldIntervals(LiveInterval liveint) { + auto it = active.begin(); for (; it != active.end() and it->first.j < liveint.first.i; ++it) used[regmap.at(it->second)] = false; active.erase(active.begin(), it); + } void @@ -122,6 +144,7 @@ RegAllocator::SpillAtInterval(LiveInterval liveint) { if (spill.first.j > liveint.first.j) { // cancel reg allocation for spill regmap[liveint.second] = regmap.at(spill.second); + active.insert(liveint); active.erase(spill); regmap.erase(spill.second); -- GitLab