diff --git a/include/codegen/codegen.hpp b/include/codegen/codegen.hpp index a5ae5ec11ff69612985e55bb7ca8034887765b12..69110c0d51421b271d627360786ee7dfd54ba528 100644 --- a/include/codegen/codegen.hpp +++ b/include/codegen/codegen.hpp @@ -129,15 +129,23 @@ class CodeGen { string reg2, int imm, string tinstr, + int tid = 0, int bits = 12, - string treg = "$t0", bool u = false) { + /* this function will tranfser + * `addi.d $a0, $fp, imm` to `add.d $a0, $fp, tmp_ireg` if imm + * overfloats for `addi.d`. During the time we move `imm` to `tmp_ireg`, + * another tmp ireg will be used, they can be same, but we must specify + * it. + */ + auto treg = tmpregname(tid, false); + assert(treg != reg2 && "it's possible to write tid before reg2's use"); 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); + assert(value2reg(ConstantInt::get(imm, m), tid, treg) == treg); output.push_back(tinstr + " " + reg1 + ", " + reg2 + ", " + treg); } } diff --git a/include/optimization/GVN.h b/include/optimization/GVN.h index c0e678c2fec82d876025747caedc4fa754f4ba1a..fb9efde6219a9ef30b8ef686675859a5aa9d33f7 100644 --- a/include/optimization/GVN.h +++ b/include/optimization/GVN.h @@ -450,6 +450,7 @@ class GVN : public Pass { std::unique_ptr func_info_; std::unique_ptr folder_; std::unique_ptr dce_; + std::vector BB_DFS_Order; // self add member // std::uint64_t start_number_; @@ -463,6 +464,7 @@ class GVN : public Pass { // // self add function // + void get_dfs_order(Function *func); void add_map_(); std::uint64_t new_number() { return next_value_number_++; } void deal_with_entry(BasicBlock *Entry); diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index e7111e29422b36dd046a3b361032ba97eea1b521..e077449eba9912ac54aa2ef730cdfb894247ca7d 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -215,8 +215,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) { } else if (dynamic_cast(v)) { // auto alloc_instr = dynamic_cast(v); // give the stack address - makeSureInRange( - "addi.d", reg_name, FP, -off.at(v), "add.d", 12, reg_name); + makeSureInRange("addi.d", reg_name, FP, -off.at(v), "add.d", i); /* output.push_back("addi.d " + reg_name + ", $fp, -" + * to_string(off.at(v))); */ } else if (dynamic_cast(v)) { @@ -235,8 +234,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) { FP, func_arg_off.at(cur_func).at(id), instr_ir + "x" + suff, - 12, - reg_name); + i); /* output.push_back(instr_ir + suff + " " + reg_name + ", $fp, " + * to_string(func_arg_off.at(cur_func).at(id))); */ } @@ -248,8 +246,7 @@ CodeGen::value2reg(Value *v, int i, string recommend) { FP, -off.at(v), instr_ir + "x" + suff, - 12, - reg_name); + i); /* output.push_back(instr_ir + suff + " " + reg_name + * ", $fp, -" + to_string(off.at(v))); */ } @@ -350,10 +347,10 @@ CodeGen::IR2assem(SiToFpInst *instr) { } string -CodeGen::bool2branch(Instruction *instr) { - assert(instr->get_type() == m->get_int1_type()); - auto icmp_instr = dynamic_cast(instr); - auto fcmp_instr = dynamic_cast(instr); +CodeGen::bool2branch(Instruction *cond) { + assert(cond->get_type() == m->get_int1_type()); + auto icmp_instr = dynamic_cast(cond); + auto fcmp_instr = dynamic_cast(cond); assert(icmp_instr or fcmp_instr); string instr_ir; @@ -365,9 +362,9 @@ CodeGen::bool2branch(Instruction *instr) { break; 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)) + if (cond->get_operand(1) == CONST_0 and + dynamic_cast(cond->get_operand(0)) and + dynamic_cast(cond->get_operand(0)) ->is_zext()) { // something like: // %op0 = icmp slt i32 1, 2 # deepest @@ -375,7 +372,7 @@ CodeGen::bool2branch(Instruction *instr) { // %op2 = icmp ne i32 %op1, 0 // br i1 %op2, label %label3, label %label5 auto deepest = static_cast( - static_cast(instr->get_operand(0)) + static_cast(cond->get_operand(0)) ->get_operand(0)); return bool2branch(deepest); } @@ -395,11 +392,11 @@ CodeGen::bool2branch(Instruction *instr) { reverse = true; break; } - auto reg1 = value2reg(instr->get_operand(0), 0); - auto reg2 = value2reg(instr->get_operand(1), 1); + auto reg1 = value2reg(cond->get_operand(0), 0); + auto reg2 = value2reg(cond->get_operand(1), 1); return instr_ir + " " + (reverse ? (reg2 + ", " + reg1) : (reg1 + ", " + reg2)) + ","; - } else { + } else if (fcmp_instr) { switch (fcmp_instr->get_cmp_op()) { case FCmpInst::EQ: instr_ir = "fcmp.ceq.s $fcc0"; @@ -422,11 +419,12 @@ CodeGen::bool2branch(Instruction *instr) { instr_ir = "fcmp.cle.s $fcc0"; break; } - auto reg1 = value2reg(instr->get_operand(0), 0); - auto reg2 = value2reg(instr->get_operand(1), 1); + auto reg1 = value2reg(cond->get_operand(0), 0); + auto reg2 = value2reg(cond->get_operand(1), 1); output.push_back(instr_ir + ", " + reg1 + ", " + reg2); return (reverse ? "bceqz $fcc0," : "bcnez $fcc0,"); - } + } else + assert(false); } void @@ -435,10 +433,20 @@ CodeGen::IR2assem(BranchInst *instr) { auto TBB = static_cast(instr->get_operand(1)); auto FBB = static_cast(instr->get_operand(2)); // value2reg(instr->get_operand(0)); - string instr_ir = - bool2branch(static_cast(instr->get_operand(0))); - output.push_back(instr_ir + " " + label_in_assem(TBB)); - output.push_back("b " + label_in_assem(FBB)); + auto cond = instr->get_operand(0); + if (dynamic_cast(cond)) { + auto const_bool = static_cast(cond); + assert(const_bool->get_type()->is_integer_type() and + static_cast(const_bool->get_type()) + ->get_num_bits() == 1); + bool cond_value = const_bool->get_value(); + output.push_back("b " + label_in_assem(cond_value ? TBB : FBB)); + } else { + string instr_ir = + bool2branch(static_cast(instr->get_operand(0))); + output.push_back(instr_ir + " " + label_in_assem(TBB)); + output.push_back("b " + label_in_assem(FBB)); + } } else { auto bb = static_cast(instr->get_operand(0)); output.push_back("b " + label_in_assem(bb)); @@ -513,16 +521,15 @@ CodeGen::pass_arguments(CallInst *instr) { 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; + int passed = 0; + // assert(order.size() >= func->get_num_of_args()); + map changed; // bool assigned[8] = {false}; string t0_contained; for (auto arg_id : order) { + if (arg_id > func->get_num_of_args()) + continue; auto arg_value = instr->get_operand(arg_id); auto arg_is_float = arg_value->get_type()->is_float_type(); auto arg_reg_aid = regname(arg_id, arg_is_float); @@ -531,12 +538,12 @@ CodeGen::pass_arguments(CallInst *instr) { // arg_reg_aid(only right when arg_id <= 8) v_reg = value2reg(arg_value, 1); if (backup[arg_id]) { // a_id still relied by some argument due to cycle - assert(not wroten[arg_reg_aid]); + assert(not changed[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]) { + if (changed[v_reg]) { assert(t0_contained == v_reg); v_reg = arg_value->get_type()->is_float_type() ? "$ft0" : "$t0"; } @@ -555,8 +562,12 @@ CodeGen::pass_arguments(CallInst *instr) { * $sp, " + to_string(func_arg_off.at(func).at(arg_id))); */ } - wroten[arg_reg_aid] = true; + if (arg_reg_aid != v_reg) { + changed[arg_reg_aid] = true; + } + passed++; } + assert(passed == func->get_num_of_args()); } void diff --git a/src/optimization/GVN.cpp b/src/optimization/GVN.cpp index c183bc7ce8dc424b9791a850b049b8a75d544679..548db818696743c1c0a22bceb695306f96683149 100644 --- a/src/optimization/GVN.cpp +++ b/src/optimization/GVN.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -386,8 +387,10 @@ GVN::detectEquivalences() { #ifdef __DEBUG__ std::cout << ++times << "th iteration" << std::endl; #endif - for (auto &_bb : func_->get_basic_blocks()) { - auto bb = &_bb; + /* for (auto &_bb : func_->get_basic_blocks()) { + * std::cout << _bb.get_name() << std::endl; + * auto bb = &_bb; */ + for (auto &bb : BB_DFS_Order) { if (bb == Entry) continue; // get PIN of bb from predecessor(s) @@ -922,6 +925,7 @@ GVN::run() { for (auto &f : m_->get_functions()) { if (f.get_basic_blocks().empty()) continue; + get_dfs_order(&f); func_ = &f; initPerFunction(); LOG_INFO << "Processing " << f.get_name(); @@ -953,6 +957,26 @@ GVN::run() { gvn_json << "]"; } +void +GVN::get_dfs_order(Function *func) { + std::map vis; + std::deque Q; + + BB_DFS_Order.clear(); + Q.push_back(func->get_entry_block()); + + while (not Q.empty()) { + auto bb = Q.front(); + Q.pop_front(); + if (vis[bb]) + continue; + vis[bb] = true; + BB_DFS_Order.push_back(bb); + for (auto succ : bb->get_succ_basic_blocks()) + Q.push_front(succ); + } +} + void GVN::dump_tmp(Function &f) { std::string gvn_json;