diff --git a/Reports/5-bonus/report.md b/Reports/5-bonus/report.md index 315de4650e0e5c6d4017dbd13b98373c4743dd55..c285c223a2c01f81e832f5b6ab1188e032e84ad9 100644 --- a/Reports/5-bonus/report.md +++ b/Reports/5-bonus/report.md @@ -132,6 +132,8 @@ op6: <8, 8> 这实际是指令选择部分的内容: 因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。 + + 一个例外是隐式的类型转化,将比较的结果`i1`隐式转换为`i32`,此时是`zext`指令与`cmp`捆绑,特殊为`zext`指令分配寄存器。 - `call`指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖`call`指令的程序点。 diff --git a/include/codegen/codegen.hpp b/include/codegen/codegen.hpp index 73ea351ac392b254a5973f46d8c3a967228e85f3..c8cbf5a1a565453410c506545e5da67615957eec 100644 --- a/include/codegen/codegen.hpp +++ b/include/codegen/codegen.hpp @@ -11,10 +11,12 @@ #include "liverange.hpp" #include "regalloc.hpp" +#include #include #define __PRINT_ORI__ #define __RO_PART__ +#define __PRINT_COMMENT__ // #a = 8, #t = 9, reserve $t0, $t1 for temporary #define R_USABLE 17 - 2 #define ARG_R 8 @@ -27,6 +29,11 @@ // #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16) #define STACK_ALIGN(x) ALIGN(x, 16) +#define CONST_0 ConstantInt::get(0, m) +#define FP "$fp" +#define SP "$sp" +#define RA_reg "$ra" + using std::map; using std::string; using std::vector; @@ -38,6 +45,10 @@ class CodeGen { string print() { string result; for (auto line : output) { +#ifndef __PRINT_COMMENT__ + if (line.find("#") != string::npos) + continue; +#endif if (line.find(":") == string::npos and line != "") result += "\t"; // 添加缩进 result += line + "\n"; @@ -58,6 +69,7 @@ class CodeGen { std::map>> phi_map; std::map ROdata; unsigned int stackN; // function local vars and so on + uint cmp_zext_cnt; Function *cur_func; @@ -79,11 +91,16 @@ class CodeGen { // In the case of register allocation, this function will return the // allocated register for that value, if the value possesses no register, // choose from from $t0 or $t1 based on id, or the input string(not "") - __attribute__((warn_unused_result)) string value2reg(Value *, int i = 0, string = ""); + __attribute__((warn_unused_result)) string value2reg(Value *, + int i = 0, + string = ""); // load the content in ptr to specified register. void ptrContent2reg(Value *, string); + + void pass_arguments(CallInst *); void compute_arg_info(Function *); string bool2branch(Instruction *); + void getPhiMap(); void copystmt(BasicBlock *bb) { // all the phi instruction is transformed to copy-stmt @@ -97,6 +114,26 @@ class CodeGen { } } + // this is a decorated version of push_back, it checks intermediat number in + // the instruction, make sure imm will not overflow + void makeSureInRange(string instr_ir, + string reg1, + string reg2, + int imm, + string tinstr, + int bits = 12, + string treg = "$t0", + bool u = false) { + auto [l, h] = immRange(bits, u); + if (l <= imm and imm <= h) + output.push_back(instr_ir + " " + reg1 + ", " + reg2 + ", " + + to_string(imm)); + else { + assert(value2reg(ConstantInt::get(imm, m), 0, treg) == treg); + output.push_back(tinstr + " " + reg1 + ", " + reg2 + ", " + treg); + } + } + // if reg-allocation, store to the specific register // or is stack-allocation, set last_reg for back2stack() bool gencopy(Value *lhs, string rhs_reg) { @@ -122,7 +159,7 @@ class CodeGen { string label_in_assem(BasicBlock *bb) const { return cur_func->get_name() + bb->get_name().substr(5); } - int typeLen(Type *type) const { + static int typeLen(Type *type) { if (type->is_float_type()) return 4; else if (type->is_integer_type()) { @@ -149,11 +186,16 @@ class CodeGen { string instr_ir = type->is_float_type() ? "fst" : "st"; string suff = suffix(type); // string reg = type->is_float_type() ? "$fa0" : "$a0"; - string addr = "$fp, -" + std::to_string(off.at(instr)); - output.push_back(instr_ir + suff + " " + last_reg + ", " + addr); + makeSureInRange(instr_ir + suff, + last_reg, + FP, + -off.at(instr), + instr_ir + "x" + suff); + // string addr = "$fp, -" + std::to_string(off.at(instr)); + // output.push_back(instr_ir + suff + " " + last_reg + ", " + addr); } - string suffix(Type *type) const { + static string suffix(Type *type) { int len = typeLen(type); switch (len) { case 1: @@ -198,6 +240,20 @@ class CodeGen { return name; } + static pair immRange(int bit, bool u) { + pair res; + if (u) { + res.first = 0; + res.second = (1 << bit) - 1; + } else { + bit--; + res.first = -(1 << bit); + res.second = (1 << bit) - 1; + } + + return res; + }; + pair getRegName(Value *, int = 0) const; void IR2assem(Instruction &, BasicBlock &); @@ -211,12 +267,12 @@ class CodeGen { void IR2assem(FpToSiInst *); void IR2assem(SiToFpInst *); void IR2assem(PhiInst *) {} + void IR2assem(ZextInst *); // The Instructions below will do nothing void IR2assem(AllocaInst *) {} - // integration with BranchInst + // integration with BranchInst and ZextInst void IR2assem(CmpInst *) {} void IR2assem(FCmpInst *) {} - void IR2assem(ZextInst *) {} }; #endif diff --git a/include/codegen/liverange.hpp b/include/codegen/liverange.hpp index 9a6f562830c54c69e5d2f596cf6421ff51f58a64..bef6acf4d3336aa8e3439124bf946e7338f63330 100644 --- a/include/codegen/liverange.hpp +++ b/include/codegen/liverange.hpp @@ -20,7 +20,7 @@ using std::vector; namespace LRA { struct Interval { - Interval(int a = 0, int b = 0) : i(a), j(b) {} + Interval(int a = -1, int b = -1) : i(a), j(b) {} int i; // 0 means uninitialized int j; }; diff --git a/src/cminusfc/cminusfc.cpp b/src/cminusfc/cminusfc.cpp index cda9a19a6ae44d9b3bbdbe854729c5668736e9fa..bb3df2b2da341c29e240d8cc452b409e79490e3b 100644 --- a/src/cminusfc/cminusfc.cpp +++ b/src/cminusfc/cminusfc.cpp @@ -34,13 +34,15 @@ main(int argc, char **argv) { bool gvn = false; bool dump_json = false; bool emit = false; - bool assembly = true; + bool assembly = false; for (int i = 1; i < argc; ++i) { if (argv[i] == "-h"s || argv[i] == "--help"s) { print_help(argv[0]); return 0; } else if (argv[i] == "-o"s || argv[i] == "-S"s) { + if (argv[i] == "-S"s) + assembly = true; if (target_path.empty() && i + 1 < argc) { target_path = argv[i + 1]; if (target_path.rfind(".") != std::string::npos) @@ -54,8 +56,6 @@ main(int argc, char **argv) { emit = true; } else if (argv[i] == "-mem2reg"s) { mem2reg = true; - } else if (argv[i] == "-S"s) { - assembly = true; } else if (argv[i] == "-gvn"s) { gvn = true; } else if (argv[i] == "-dump-json"s) { @@ -123,6 +123,7 @@ main(int argc, char **argv) { auto IR = m->print(); if (assembly) { + CodeGen codegen(m.get()); codegen.run(); std::ofstream target_file(target_path + ".s"); diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index a7fa6d582f2487772d7faaeb1a8228c3b90645de..18da1aa4f32fe39e757dede2b0fe835579cc26b9 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -12,16 +12,16 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include -#define CONST_0 ConstantInt::get(0, m) - // $r0 $zero constant 0 // $r1 $ra return address // $r2 $tp thread pointer @@ -33,6 +33,7 @@ // $r22 $fp frame pointer // $r23 - $r31 $s0 - $s8 static +using std::deque; using std::to_string; using std::operator""s; @@ -145,38 +146,39 @@ CodeGen::run() { } void -CodeGen::ptrContent2reg(Value *ptr, string reg_name) { +CodeGen::ptrContent2reg(Value *ptr, string dest_reg) { auto ele_tp = ptr->get_type()->get_pointer_element_type(); assert(ele_tp); bool is_float = ele_tp->is_float_type(); string instr_ir = (is_float ? "fld" : "ld"); string suff = suffix(ele_tp); - auto [addr_reg, find] = getRegName(ptr, 1); - /* if (not find) - * addr_reg = "$t1"; */ + auto [addr_reg, find] = getRegName(ptr, 0); if (dynamic_cast(ptr)) { output.push_back("la.local " + addr_reg + ", " + ptr->get_name()); - output.push_back(instr_ir + suff + " " + reg_name + ", " + addr_reg + + output.push_back(instr_ir + suff + " " + dest_reg + ", " + addr_reg + ", 0"); } else if (dynamic_cast(ptr)) { - /* auto alloc_instr = static_cast(ptr); - * string suff = suffix(alloc_instr->get_alloca_type()); */ - output.push_back(instr_ir + suff + " " + reg_name + ", $fp, -" + - to_string(off.at(ptr))); + makeSureInRange( + instr_ir + suff, dest_reg, FP, -off.at(ptr), instr_ir + "x" + suff); + /* output.push_back(instr_ir + suff + " " + reg_name + ", $fp, -" + + * to_string(off.at(ptr))); */ } else if (dynamic_cast(ptr)) { // auto GEP_instr = static_cast(ptr); if (not find) { - output.push_back("ld.d " + addr_reg + ", $fp, -" + - to_string(off.at(ptr))); + makeSureInRange("ld.d", addr_reg, FP, -off.at(ptr), "ldx.d"); + /* output.push_back("ld.d " + addr_reg + ", $fp, -" + + * to_string(off.at(ptr))); */ } - output.push_back(instr_ir + suff + " " + reg_name + ", " + addr_reg + + output.push_back(instr_ir + suff + " " + dest_reg + ", " + addr_reg + ", 0"); } else 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(); @@ -237,8 +239,10 @@ CodeGen::value2reg(Value *v, int i, string recommend) { } else if (dynamic_cast(v)) { // auto alloc_instr = dynamic_cast(v); // give the stack address - output.push_back("addi.d " + reg_name + ", $fp, -" + - to_string(off.at(v))); + makeSureInRange( + "addi.d", reg_name, FP, -off.at(v), "add.d", 12, reg_name); + /* output.push_back("addi.d " + reg_name + ", $fp, -" + + * to_string(off.at(v))); */ } else if (dynamic_cast(v)) { auto args = cur_func->get_args(); int id = 1; @@ -249,14 +253,29 @@ CodeGen::value2reg(Value *v, int i, string recommend) { return regname(ARG_R); else { string instr_ir = is_float ? "fld" : "ld"; - output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name + - ", $fp, " + - to_string(func_arg_off.at(cur_func).at(id))); + auto suff = suffix(v->get_type()); + makeSureInRange(instr_ir + suff, + reg_name, + FP, + func_arg_off.at(cur_func).at(id), + instr_ir + "x" + suff, + 12, + reg_name); + /* output.push_back(instr_ir + suff + " " + reg_name + ", $fp, " + + * to_string(func_arg_off.at(cur_func).at(id))); */ } } else { string instr_ir = is_float ? "fld" : "ld"; - output.push_back(instr_ir + suffix(v->get_type()) + " " + reg_name + - ", $fp, -" + to_string(off.at(v))); + auto suff = suffix(v->get_type()); + makeSureInRange(instr_ir + suff, + reg_name, + FP, + off.at(v), + instr_ir + "x" + suff, + 12, + reg_name); + /* output.push_back(instr_ir + suff + " " + reg_name + + * ", $fp, -" + to_string(off.at(v))); */ } return reg_name; } @@ -307,10 +326,14 @@ CodeGen::stackMemAlloc() { } stackN = STACK_ALIGN(stackN); output.push_back("# prolog"); - output.push_back("addi.d $sp, $sp, -" + to_string(stackN)); - output.push_back("st.d $ra, $sp," + to_string(stackN - 8)); - output.push_back("st.d $fp, $sp, " + to_string(stackN - 16)); - output.push_back("addi.d $fp, $sp, " + to_string(stackN)); + makeSureInRange("addi.d", SP, SP, -stackN, "add.d"); + makeSureInRange("st.d", RA_reg, SP, stackN - 8, "stx.d"); + makeSureInRange("st.d", FP, SP, stackN - 16, "stx.d"); + makeSureInRange("addi.d", FP, SP, stackN, "add.d"); + /* output.push_back("addi.d $sp, $sp, -" + to_string(stackN)); + * output.push_back("st.d $ra, $sp," + to_string(stackN - 8)); + * output.push_back("st.d $fp, $sp, " + to_string(stackN - 16)); + * output.push_back("addi.d $fp, $sp, " + to_string(stackN)); */ } void @@ -318,11 +341,13 @@ CodeGen::stackMemDealloc() { // 7: return value should be determined already! output.push_back(cur_func->get_name() + "_end:"); output.push_back("# epilog"); - output.push_back("ld.d $ra, $sp, " + to_string(stackN - 8)); - output.push_back("ld.d $fp, $sp, " + to_string(stackN - 16)); - /* output.push_back("ld.d $ra, $fp, -8"); - * output.push_back("ld.d $fp, $fp, -16"); */ - output.push_back("addi.d $sp, $sp, " + to_string(stackN)); + + makeSureInRange("ld.d", RA_reg, SP, stackN - 8, "ldx.d"); + makeSureInRange("ld.d", FP, SP, stackN - 16, "ldx.d"); + makeSureInRange("addi.d", SP, SP, stackN, "add.d"); + /* output.push_back("ld.d $ra, $sp, " + to_string(stackN - 8)); + * output.push_back("ld.d $fp, $sp, " + to_string(stackN - 16)); + * output.push_back("addi.d $sp, $sp, " + to_string(stackN)); */ output.push_back("jr $ra"); } @@ -364,6 +389,7 @@ CodeGen::bool2branch(Instruction *instr) { case CmpInst::NE: { instr_ir = "bne"; if (instr->get_operand(1) == CONST_0 and + dynamic_cast(instr->get_operand(0)) and dynamic_cast(instr->get_operand(0)) ->is_zext()) { // something like: @@ -397,7 +423,6 @@ CodeGen::bool2branch(Instruction *instr) { return instr_ir + " " + (reverse ? (reg2 + ", " + reg1) : (reg1 + ", " + reg2)) + ","; } else { - assert(false && "not implemented"); switch (fcmp_instr->get_cmp_op()) { case FCmpInst::EQ: instr_ir = "fcmp.ceq.s $fcc0"; @@ -443,6 +468,117 @@ CodeGen::IR2assem(BranchInst *instr) { } } +void +CodeGen::pass_arguments(CallInst *instr) { + /* cannot use the arg order simply, example leading to error: + * a0<-..., a1<-a0 + * so we need an suitable order and use at most 1 tmp reg to pass arguments + */ + // ASSERT: use index start from 1 + const int N = 8; + auto func = static_cast(instr->get_operand(0)); + string v_reg, instr_ir, suff; + // 1. get rely graph for $a regs + // for example, $a1 is need by needby[1], which is a set + vector needby[N + 1]; + for (int arg_id = 1; arg_id < instr->get_num_operand(); arg_id++) { + auto arg_value = instr->get_operand(arg_id); + v_reg = getRegName(arg_value).first; + if (v_reg.substr(0, 2) != "$a") + continue; + else { + int v_id = std::stoi(to_string(v_reg[2])) - 47; + if (v_id != arg_id) + needby[v_id].push_back(arg_id); + } + } + + // 2. get traverse order: an enhanced topological order + // key: if there is a cycle, should give out an order rather than endless + // loop, and the order should statisfy: + vector order; + deque queue; + bool vis[N + 1]{false}; + map backup; + for (int arg_id = 1; arg_id < instr->get_num_operand(); arg_id++) + queue.push_back(arg_id); // initialize + while (not queue.empty()) { + int i = queue.front(); + queue.pop_front(); + if (find(order.begin(), order.end(), i) != order.end()) + continue; // already has order + bool assign; + if (needby[i].size() == 0) { + // there is no argument relying on $a_i or is self rely + assign = true; + } else if (vis[i]) { // cycle detected + backup[i] = true; + assign = true; + } else + assign = false; + + if (assign) { + order.push_back(i); + for (int j = 1; j <= N; ++j) { // remove $a_i 's rely + auto &need_vec = needby[j]; + auto iter = find(need_vec.begin(), need_vec.end(), i); + if (iter != + need_vec.end()) { // $a_i has at most one rely on $a_ + need_vec.erase(iter); + if (needby[j].size() == 0) { + queue.push_front(j); + } + break; + } + } + } else + queue.push_back(i); + vis[i] = true; + } + + order.clear(); + for (int arg_id = 1; arg_id < instr->get_num_operand(); arg_id++) + order.push_back(arg_id); // initialize + + // 3. pass arguments' value + assert(order.size() == func->get_num_of_args()); + map wroten; + // bool assigned[8] = {false}; + 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"; + 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; + } + // in case that the src register has been wroten + if (wroten[v_reg]) { + assert(t0_contained == v_reg); + v_reg = arg_value->get_type()->is_float_type() ? "$ft0" : "$t0"; + } + + if (arg_id <= ARG_R) { // pass by register + gencopy(regname(arg_id), v_reg); + } else { // pass by stack + instr_ir = (arg_value->get_type()->is_float_type() ? "fst" : "st"); + suff = suffix(arg_value->get_type()); + makeSureInRange(instr_ir + suff, + v_reg, + SP, + func_arg_off.at(func).at(arg_id), + instr_ir + "x" + suff); + /* output.push_back(instr_ir + suff + " " + v_reg + ", + * $sp, " + to_string(func_arg_off.at(func).at(arg_id))); + */ + } + wroten[regname(arg_id)] = true; + } +} + void CodeGen::IR2assem(CallInst *instr) { auto func = static_cast(instr->get_operand(0)); @@ -454,9 +590,16 @@ CodeGen::IR2assem(CallInst *instr) { int storeN = 0; vector> store_record; for (auto [op, interval] : LRA.get_interval_map()) { - if (RA.no_reg_alloca(op) or regmap.at(op) == 1) + if (RA.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) continue; - if (interval.i <= cur_i and cur_i <= interval.j) { + if (interval.i < cur_i and cur_i <= interval.j) { + cout << "At point " << cur_i << ", restore for " << op->get_name() + << ", interval " << LRA.print_interval(interval) << endl; int tplen = typeLen(op->get_type()); storeN = ALIGN(storeN, tplen) + tplen; auto name = regname(regmap.at(op), op->get_type()->is_float_type()); @@ -464,31 +607,23 @@ CodeGen::IR2assem(CallInst *instr) { } } int totalN = STACK_ALIGN(ALIGN(storeN, 8) + func_argN); - // cout << "debug: " << STACK_ALIGN(12) << endl; // stack space allocation - if (totalN) - output.push_back("addi.d $sp, $sp, -" + to_string(totalN)); + if (totalN) { + makeSureInRange("addi.d", SP, SP, -totalN, "add.d"); + // output.push_back("addi.d $sp, $sp, -" + to_string(totalN)); + } string instr_ir, suff, v_reg; // place the reserved regs for (auto [op, reg, off] : store_record) { instr_ir = (op->get_type()->is_float_type() ? "fst" : "st"); suff = suffix(op->get_type()); - output.push_back(instr_ir + suff + " " + reg + ", $sp, " + - to_string(totalN - off)); + makeSureInRange( + instr_ir + suff, reg, SP, totalN - off, instr_ir + "x" + suff); + /* output.push_back(instr_ir + suff + " " + reg + ", $sp, " + + * to_string(totalN - off)); */ } // pass arguments - for (int arg_i = 1; arg_i < instr->get_num_operand(); arg_i++) { - auto arg_value = instr->get_operand(arg_i); - v_reg = value2reg(arg_value); - if (arg_i <= ARG_R) { // pass by register - gencopy(regname(arg_i), v_reg); - } else { // pass by stack - instr_ir = (arg_value->get_type()->is_float_type() ? "fst" : "st"); - suff = suffix(arg_value->get_type()); - output.push_back(instr_ir + suff + " " + v_reg + ", $sp, " + - to_string(func_arg_off.at(func).at(arg_i))); - } - } + pass_arguments(instr); output.push_back("bl " + func->get_name()); // bug here: maybe gencopy(instr, instr->get_type()->is_float_type() ? "$fa0" : "$a0"); @@ -496,11 +631,15 @@ CodeGen::IR2assem(CallInst *instr) { for (auto [op, reg, off] : store_record) { instr_ir = (op->get_type()->is_float_type() ? "fld" : "ld"); suff = suffix(op->get_type()); - output.push_back(instr_ir + suff + " " + reg + ", $sp, " + - to_string(totalN - off)); + makeSureInRange( + instr_ir + suff, reg, SP, totalN - off, instr_ir + "x" + suff); + /* output.push_back(instr_ir + suff + " " + reg + ", $sp, " + + * to_string(totalN - off)); */ + } + if (totalN) { + makeSureInRange("addi.d", SP, SP, totalN, "add.d"); + // output.push_back("addi.d $sp, $sp, " + to_string(totalN)); } - if (totalN) - output.push_back("addi.d $sp, $sp, " + to_string(totalN)); } void @@ -529,7 +668,8 @@ CodeGen::IR2assem(GetElementPtrInst *instr) { return; } if (instr->get_num_operand() == 3) { - // %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32 %op41 + // %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32 + // %op41 assert(instr->get_operand(1) == CONST_0); } else { // %op38 = getelementptr i32, i32* %arg1, i32 %op34 } @@ -547,8 +687,7 @@ void CodeGen::IR2assem(LoadInst *instr) { auto [reg, find] = getRegName(instr); ptrContent2reg(instr->get_lval(), reg); - if (not find) // this if is just for logically clear - last_reg = reg; + gencopy(instr, reg); } void @@ -576,6 +715,95 @@ CodeGen::IR2assem(ReturnInst *instr) { output.push_back("b " + cur_func->get_name() + "_end"); } +void +CodeGen::IR2assem(ZextInst *instr) { + if (RA.no_reg_alloca(instr)) + return; + assert(instr->get_num_operand() == 1); + auto cmp_instr = instr->get_operand(0); + auto icmp_instr = dynamic_cast(cmp_instr); + auto fcmp_instr = dynamic_cast(cmp_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; + if (icmp_instr) { + switch (icmp_instr->get_cmp_op()) { + case CmpInst::EQ: + instr_ir = "xor"; + check = flip = true; + break; + case CmpInst::NE: + instr_ir = "xor"; + check = true; + break; + case CmpInst::GT: + instr_ir = "slt"; + reverse = true; + break; + case CmpInst::GE: + instr_ir = "slt"; + flip = true; + break; + case CmpInst::LT: + instr_ir = "slt"; + break; + case CmpInst::LE: + instr_ir = "slt"; + reverse = true; + flip = true; + break; + } + output.push_back( + instr_ir + " " + dest_reg + ", " + + (reverse ? (reg2 + ", " + reg1) : (reg1 + ", " + reg2))); + if (check) { + if (flip) + output.push_back("sltui " + dest_reg + ", " + dest_reg + ", 1"); + else + output.push_back("sltu " + dest_reg + ", $zero, " + dest_reg); + } else if (flip) // check && flip can be solved in a single + // instruction + output.push_back("sltui " + dest_reg + ", " + dest_reg + ", 1"); + + } else { + switch (fcmp_instr->get_cmp_op()) { + case FCmpInst::EQ: + instr_ir = "fcmp.ceq.s"; + break; + case FCmpInst::NE: + instr_ir = "fcmp.cun.s"; + break; + case FCmpInst::GT: + instr_ir = "fcmp.cle.s"; + reverse = true; + break; + case FCmpInst::GE: + instr_ir = "fcmp.clt.s"; + reverse = true; + break; + case FCmpInst::LT: + instr_ir = "fcmp.clt.s"; + break; + case FCmpInst::LE: + instr_ir = "fcmp.cle.s"; + break; + } + string cmp_reg = "$fcc0"; + 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("addi.w " + dest_reg + ", $zero, 1"); + output.push_back(label + ":"); + } + gencopy(instr, dest_reg); +} + void CodeGen::IR2assem(Instruction &instr, BasicBlock &bb) { if (instr.is_br() or instr.is_ret()) diff --git a/src/codegen/liverange.cpp b/src/codegen/liverange.cpp index 5ae3c99f01a1f503a30f6941629cf3219868a40d..df28edf24cdf88190de01ae6c8cdce6b334c89b7 100644 --- a/src/codegen/liverange.cpp +++ b/src/codegen/liverange.cpp @@ -124,10 +124,13 @@ LiveRangeAnalyzer::run(Function *func) { } } } + // argument should be in the IN-set of Entry + for (auto arg : func->get_args()) + IN[1].insert(arg); make_interval(func); #ifdef __LRA_PRINT__ - print(func, false, true); + print(func, true, true); #endif } @@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) { for (int time = 1; time <= ir_cnt; ++time) { for (auto op : IN.at(time)) { auto &interval = intervalmap[op]; - if (interval.i == 0) // uninitialized + if (interval.i == -1) // uninitialized interval.i = time - 1; else interval.j = time - 1; } for (auto op : OUT.at(time)) { auto &interval = intervalmap[op]; - if (interval.i == 0) // uninitialized + if (interval.i == -1) // uninitialized interval.i = time; else interval.j = time; } } - for (auto [op, interval] : intervalmap) + for (auto &[op, interval] : intervalmap) liveIntervals.insert({interval, op}); } diff --git a/src/codegen/regalloc.cpp b/src/codegen/regalloc.cpp index 40a043e830ee4e07752ee2a47563571a2dd35e82..a8b4696f94d15626b261f0c5d719090917fcd462 100644 --- a/src/codegen/regalloc.cpp +++ b/src/codegen/regalloc.cpp @@ -26,10 +26,30 @@ bool RegAllocator::no_reg_alloca(Value *v) const { auto instr = dynamic_cast(v); auto arg = dynamic_cast(v); - if (instr) - return instr->is_alloca() or instr->is_cmp() or instr->is_fcmp() or - instr->is_zext(); - if (arg) { + if (instr) { + // never allocate register + 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()); + + } else + return false; + } + return true; + } else // then always allocate + return false; + } + if (arg) { // only allocate for the first 8 args return get_arg_id(arg) > ARG_MAX_R; } else assert(false && "only instruction and argument's LiveInterval exits");