diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index 477fe42..ae1beb6 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -121,6 +121,8 @@ std::string RISCv64CodeGen::function_gen(Function* func) { // if (DEBUG) { // std::cout << ss_after_isel.str(); // } + // DEBUG = 0; + // DEEPDEBUG = 0; // DEBUG = 1; // DEEPDEBUG = 1; if (DEBUG) { @@ -143,8 +145,8 @@ std::string RISCv64CodeGen::function_gen(Function* func) { // PreRA_Scheduler scheduler; // scheduler.runOnMachineFunction(mfunc.get()); - DEBUG = 0; - DEEPDEBUG = 0; + // DEBUG = 0; + // DEEPDEBUG = 0; // 阶段 3: 物理寄存器分配 (Register Allocation) RISCv64RegAlloc reg_alloc(mfunc.get()); reg_alloc.run(); diff --git a/src/backend/RISCv64/RISCv64RegAlloc.cpp b/src/backend/RISCv64/RISCv64RegAlloc.cpp index 234bccf..763f401 100644 --- a/src/backend/RISCv64/RISCv64RegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64RegAlloc.cpp @@ -255,20 +255,20 @@ void RISCv64RegAlloc::build() { RISCv64AsmPrinter printer_inside_build(MFunc); printer_inside_build.setStream(std::cerr); + // 1. 收集所有待分配的(既非物理也非预着色)虚拟寄存器到 initial 集合 for (const auto& mbb_ptr : MFunc->getBlocks()) { for (const auto& instr_ptr : mbb_ptr->getInstructions()) { const MachineInstr* instr = instr_ptr.get(); VRegSet use, def; getInstrUseDef_Liveness(instr, use, def); - // 调试输出 use 和 def + // 调试输出 use 和 def (保留您的调试逻辑) if (DEEPDEBUG) { std::cerr << "Instr:"; printer_inside_build.printInstruction(instr_ptr.get(), true); - // 修改 lambda 以捕获 this 指针,从而可以调用成员函数 auto print_set = [this](const VRegSet& s, const std::string& name) { std::cerr << " " << name << ": { "; - for(unsigned v : s) std::cerr << regIdToString(v) << " "; // 使用新函数 + for(unsigned v : s) std::cerr << regIdToString(v) << " "; std::cerr << "}\n"; }; print_set(def, "Def "); @@ -276,17 +276,26 @@ void RISCv64RegAlloc::build() { } for (unsigned v : use) { - if (!coloredNodes.count(v)) { + if (!coloredNodes.count(v) && !precolored.count(v)) { initial.insert(v); } else if (DEEPDEBUG) { - std::cerr << "Skipping %vreg" << v << " because it is in coloredNodes.\n"; + // 这里的调试信息可以更精确 + if (precolored.count(v)) { + std::cerr << "Skipping " << regIdToString(v) << " because it is a physical register.\n"; + } else { + std::cerr << "Skipping " << regIdToString(v) << " because it is a pre-colored virtual register.\n"; + } } } for (unsigned v : def) { - if (!coloredNodes.count(v)) { + if (!coloredNodes.count(v) && !precolored.count(v)) { initial.insert(v); } else if (DEEPDEBUG) { - std::cerr << "Skipping %vreg" << v << " because it is in coloredNodes.\n"; + if (precolored.count(v)) { + std::cerr << "Skipping " << regIdToString(v) << " because it is a physical register.\n"; + } else { + std::cerr << "Skipping " << regIdToString(v) << " because it is a pre-colored virtual register.\n"; + } } } } @@ -294,17 +303,25 @@ void RISCv64RegAlloc::build() { if (DEEPDEBUG) { std::cerr << "Initial set after build: { "; - for (unsigned v : initial) std::cerr << "%vreg" << v << " "; + for (unsigned v : initial) std::cerr << regIdToString(v) << " "; std::cerr << "}\n"; } - for(unsigned vreg : initial) { + // 2. 为所有参与图构建的虚拟寄存器(initial + coloredNodes)初始化数据结构 + VRegSet all_participating_vregs = initial; + all_participating_vregs.insert(coloredNodes.begin(), coloredNodes.end()); + + for (unsigned vreg : all_participating_vregs) { + // 物理寄存器ID不应作为key,此检查是安全的双重保障 + const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); + if (vreg >= offset) { + continue; + } adjList[vreg] = {}; degree[vreg] = 0; - moveList[vreg] = {}; - // alias[vreg] = vreg; } + // 3. 构建冲突图 for (const auto& mbb_ptr : MFunc->getBlocks()) { if (DEEPDEBUG) std::cerr << "\n--- Building Graph for Basic Block: " << mbb_ptr->getName() << " ---\n"; for (const auto& instr_ptr : mbb_ptr->getInstructions()) { @@ -313,8 +330,8 @@ void RISCv64RegAlloc::build() { getInstrUseDef_Liveness(instr, use, def); const VRegSet& live_out = live_out_map.at(instr); + // 保留您的指令级调试输出 if (DEEPDEBUG) { - // 使用临时的 AsmPrinter 打印当前指令,便于观察 RISCv64AsmPrinter temp_printer(MFunc); temp_printer.setStream(std::cerr); std::cerr << "Instr: "; @@ -322,7 +339,7 @@ void RISCv64RegAlloc::build() { auto print_set = [this](const VRegSet& s, const std::string& name) { std::cerr << " " << name << ": { "; - for(unsigned v : s) std::cerr << regIdToString(v) << " "; // 使用新函数 + for(unsigned v : s) std::cerr << regIdToString(v) << " "; std::cerr << "}\n"; }; print_set(def, "Def "); @@ -333,46 +350,54 @@ void RISCv64RegAlloc::build() { bool is_move = instr->getOpcode() == RVOpcodes::MV; + // 保留您处理 moveList 的逻辑 if (is_move) { worklistMoves.insert(instr); VRegSet move_vregs; - for(const auto& op : instr->getOperands()) { + for(const auto& op : instr->getOperands()) { if (op->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(op.get()); - if(reg_op->isVirtual()) move_vregs.insert(reg_op->getVRegNum()); + auto reg_op = static_cast(op.get()); + if(reg_op->isVirtual()) move_vregs.insert(reg_op->getVRegNum()); } } for (unsigned vreg : move_vregs) { + // 使用 operator[] 是安全的,如果vreg不存在会默认构造 moveList[vreg].insert(instr); } } - // --- 规则 1: Def 与 Live_Out 变量干扰 --- VRegSet live = live_out; if (is_move) { - for (unsigned u : use) { - live.erase(u); - } - } - for (unsigned d : def) { - for (unsigned l : live) { - addEdge(d, l); + for (unsigned u_op : use) { + live.erase(u_op); } } - // --- [新增的关键逻辑] 规则 2: 对于非move指令,强制def和use互相干扰 --- - // 这可以防止指令内部的源寄存器被目标寄存器错误地覆盖 - if (!is_move) { - for (unsigned d : def) { - for (unsigned u : use) { - addEdge(d, u); + // --- 规则 1 & 2: Def 与 Live/Use 变量干扰 --- + for (unsigned d : def) { + // [关键修正] Def必须是虚拟寄存器 + if (precolored.count(d)) continue; + + for (unsigned l : live) { + addEdge(d, l); + } + + if (!is_move) { + for (unsigned u_op : use) { + addEdge(d, u_op); } } } + + // --- 规则 3: Live_Out 集合内部的【虚拟寄存器】形成完全图 --- + // [优化与修正] 使用更高效的遍历,避免重复调用 addEdge(A,B) 和 addEdge(B,A) + for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) { + unsigned l1 = *it1; + // [关键修正] 只为虚拟寄存器 l1 添加边 + if (precolored.count(l1)) continue; - // --- 规则 3: Live_Out 集合内部形成完全图 --- - for (unsigned l1 : live_out) { - for (unsigned l2 : live_out) { + for (auto it2 = std::next(it1); it2 != live_out.end(); ++it2) { + unsigned l2 = *it2; addEdge(l1, l2); } } @@ -552,6 +577,8 @@ void RISCv64RegAlloc::selectSpill() { void RISCv64RegAlloc::assignColors() { if (DEEPDEBUG) std::cerr << "[AssignColors] Starting...\n"; + + // 步骤 1: 完整处理 selectStack while (!selectStack.empty()) { unsigned n = selectStack.back(); selectStack.pop_back(); @@ -559,12 +586,8 @@ void RISCv64RegAlloc::assignColors() { const auto& available_regs = is_fp ? allocable_fp_regs : allocable_int_regs; std::set ok_colors(available_regs.begin(), available_regs.end()); - // 遍历 n 的所有邻居 w for (unsigned w : adjList.at(n)) { unsigned w_alias = getAlias(w); - - // [关键修正] 邻居 w 可能是一个已着色的虚拟寄存器, - // 或者它本身就是一个物理寄存器。两种情况都要处理! bool is_colored_vreg = coloredNodes.count(w_alias); bool is_physical_reg = precolored.count(w_alias); const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); @@ -572,10 +595,8 @@ void RISCv64RegAlloc::assignColors() { if (is_colored_vreg || is_physical_reg) { PhysicalReg neighbor_color; if (is_colored_vreg) { - // 如果是已着色的vreg,从 color_map 获取它的颜色 neighbor_color = color_map.at(w_alias); } else { - // 如果是物理寄存器,它的ID就是它的颜色 neighbor_color = static_cast(w_alias - offset); } ok_colors.erase(neighbor_color); @@ -589,18 +610,28 @@ void RISCv64RegAlloc::assignColors() { PhysicalReg c = *ok_colors.begin(); coloredNodes.insert(n); color_map[n] = c; - if (DEEPDEBUG) std::cerr << " -> Colored %vreg" << n << " with " << regToString(c) << " (ID: " << static_cast(c) << ").\n"; + if (DEEPDEBUG) std::cerr << " -> Colored %vreg" << n << " with " << regToString(c) << ".\n"; } } - // 为合并的节点上色(这部分逻辑是正确的) + // 步骤 2: 独立、完整地处理 coalescedNodes for (unsigned n : coalescedNodes) { unsigned root_alias = getAlias(n); - if (color_map.count(root_alias)) { + + // 情况 1: 别名是物理寄存器,直接获得该颜色 + if (precolored.count(root_alias)) { + const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); + color_map[n] = static_cast(root_alias - offset); + if (DEEPDEBUG) std::cerr << " -> Coalesced " << regIdToString(n) << " gets color from physical alias " << regIdToString(root_alias) << ".\n"; + } + // 情况 2: 别名是虚拟寄存器,且在步骤1中已被成功着色 + else if (color_map.count(root_alias)) { color_map[n] = color_map.at(root_alias); - if (DEEPDEBUG) std::cerr << " -> Coalesced " << regIdToString(n) << " gets color of alias " << regIdToString(root_alias) << ".\n"; - } else { - if (DEEPDEBUG) std::cerr << " -> No color for alias of %vreg" << n << ". Spilling.\n"; + if (DEEPDEBUG) std::cerr << " -> Coalesced " << regIdToString(n) << " gets color of virtual alias " << regIdToString(root_alias) << ".\n"; + } + // 情况 3: 别名是虚拟寄存器,但在步骤1中未能着色(即被溢出) + else { + if (DEEPDEBUG) std::cerr << " -> Alias " << regIdToString(root_alias) << " of %vreg" << n << " was spilled. Spilling.\n"; spilledNodes.insert(n); } } @@ -798,14 +829,16 @@ void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VR } /** - * @brief [新增] 获取一条指令完整的、包含物理寄存器的Use/Def集合 + * @brief [已修复] 获取一条指令完整的、包含物理寄存器的Use/Def集合 * 这个新函数将专门服务于活跃性分析。 */ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) { auto opcode = instr->getOpcode(); const auto& operands = instr->getOperands(); + // 映射表:指令操作码 -> {Def操作数索引列表, Use操作数索引列表} static const std::map, std::vector>> op_info = { + // ===== 已有指令定义 (保留) ===== {RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}}, {RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}}, {RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}}, @@ -820,14 +853,42 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet {RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}}, {RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}}, {RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}}, - {RVOpcodes::RET, {{}, {static_cast(PhysicalReg::A0), static_cast(PhysicalReg::F10)}}}, - {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}}, {RVOpcodes::FMUL_S, {{0}, {1, 2}}}, - {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}}, {RVOpcodes::FLT_S, {{0}, {1, 2}}}, - {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}}, {RVOpcodes::FCVT_W_S, {{0}, {1}}}, - {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}}, {RVOpcodes::FMV_X_W, {{0}, {1}}}, - {RVOpcodes::FNEG_S, {{0}, {1}}} + {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}}, + {RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}}, + {RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}}, + {RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}}, + {RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}}, + + // ===== 新增的指令定义开始 ===== + + // --- 逻辑指令 --- + {RVOpcodes::XOR, {{0}, {1, 2}}}, + {RVOpcodes::OR, {{0}, {1, 2}}}, + {RVOpcodes::AND, {{0}, {1, 2}}}, + {RVOpcodes::ORI, {{0}, {1}}}, + {RVOpcodes::ANDI, {{0}, {1}}}, + + // --- 移位指令 --- + {RVOpcodes::SLL, {{0}, {1, 2}}}, {RVOpcodes::SLLI, {{0}, {1}}}, + {RVOpcodes::SLLW, {{0}, {1, 2}}}, {RVOpcodes::SLLIW, {{0}, {1}}}, + {RVOpcodes::SRL, {{0}, {1, 2}}}, {RVOpcodes::SRLI, {{0}, {1}}}, + {RVOpcodes::SRLW, {{0}, {1, 2}}}, {RVOpcodes::SRLIW, {{0}, {1}}}, + {RVOpcodes::SRA, {{0}, {1, 2}}}, {RVOpcodes::SRAI, {{0}, {1}}}, + {RVOpcodes::SRAW, {{0}, {1, 2}}}, {RVOpcodes::SRAIW, {{0}, {1}}}, + + // --- 控制流指令 (补全) --- + {RVOpcodes::BLTU, {{}, {0, 1}}}, + {RVOpcodes::BGEU, {{}, {0, 1}}}, + // J 没有寄存器操作数,JAL 由CALL指令类似的特殊逻辑处理 + + // --- 伪指令 (补全) --- + {RVOpcodes::NEG, {{0}, {1}}}, + {RVOpcodes::NEGW, {{0}, {1}}}, + + // ===== 新增的指令定义结束 ===== }; + // 该lambda表达式用于获取操作数的寄存器ID(虚拟或物理),逻辑正确,保持不变 const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); auto get_any_reg_id = [&](const MachineOperand* op) -> unsigned { if (op->getKind() == MachineOperand::KIND_REG) { @@ -843,39 +904,78 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet if (op_info.count(opcode)) { const auto& info = op_info.at(opcode); - for (int idx : info.first) if (idx < operands.size()) def.insert(get_any_reg_id(operands[idx].get())); - for (int idx : info.second) if (idx < operands.size()) use.insert(get_any_reg_id(operands[idx].get())); - for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) use.insert(get_any_reg_id(op.get())); - } else if (opcode == RVOpcodes::CALL) { - if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) def.insert(get_any_reg_id(operands[0].get())); - for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) use.insert(get_any_reg_id(operands[i].get())); - for (auto preg : getCallerSavedIntRegs()) def.insert(static_cast(preg)); - for (auto preg : getCallerSavedFpRegs()) def.insert(static_cast(preg)); - def.insert(static_cast(PhysicalReg::RA)); + for (int idx : info.first) if (idx < operands.size()) { + unsigned reg_id = get_any_reg_id(operands[idx].get()); + if (reg_id != (unsigned)-1) def.insert(reg_id); + } + for (int idx : info.second) if (idx < operands.size()) { + unsigned reg_id = get_any_reg_id(operands[idx].get()); + if (reg_id != (unsigned)-1) use.insert(reg_id); + } + // 不要忘记内存操作数中的基址寄存器永远是use + for (const auto& op : operands) { + if (op->getKind() == MachineOperand::KIND_MEM) { + unsigned reg_id = get_any_reg_id(op.get()); + if (reg_id != (unsigned)-1) use.insert(reg_id); + } + } + } + // CALL 和 RET 的特殊处理逻辑,保持不变 + else if (opcode == RVOpcodes::CALL) { + // 返回值是Def + if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) { + def.insert(get_any_reg_id(operands[0].get())); + } + // 函数名后的所有寄存器参数都是Use + for (size_t i = 1; i < operands.size(); ++i) { + if (operands[i]->getKind() == MachineOperand::KIND_REG) { + use.insert(get_any_reg_id(operands[i].get())); + } + } + // 所有调用者保存寄存器(caller-saved)被隐式定义(因为它们的值被破坏了) + for (auto preg : getCallerSavedIntRegs()) def.insert(offset + static_cast(preg)); + for (auto preg : getCallerSavedFpRegs()) def.insert(offset + static_cast(preg)); + // 返回地址寄存器RA也被隐式定义 + def.insert(offset + static_cast(PhysicalReg::RA)); + } + else if (opcode == RVOpcodes::RET) { + // 遵循调用约定,a0(整数/指针)和fa0(浮点)被隐式使用 + use.insert(offset + static_cast(PhysicalReg::A0)); + use.insert(offset + static_cast(PhysicalReg::F10)); // F10 is fa0 } } void RISCv64RegAlloc::addEdge(unsigned u, unsigned v) { if (u == v) return; - // 关键修正:只为虚拟寄存器(非预着色)更新邻接表和度数 - // 如果 u 是虚拟寄存器 - if (!precolored.count(u)) { - // 并且 u 和 v 之间还没有边 - if (adjList.at(u).find(v) == adjList.at(u).end()) { - adjList.at(u).insert(v); - degree.at(u)++; + // 检查两个节点是否都是虚拟寄存器 + if (!precolored.count(u) && !precolored.count(v)) { + // 只有当两个都是虚拟寄存器时,才为它们双方添加边和更新度数 + // 使用 operator[] 是安全的,如果键不存在,它会默认构造一个空的set + if (adjList[u].find(v) == adjList[u].end()) { + adjList[u].insert(v); + adjList[v].insert(u); + degree[u]++; + degree[v]++; } } - - // 对称地,如果 v 是虚拟寄存器 - if (!precolored.count(v)) { - // 并且 v 和 u 之间还没有边 - if (adjList.at(v).find(u) == adjList.at(v).end()) { - adjList.at(v).insert(u); - degree.at(v)++; + // 检查是否为 "虚拟-物理" 对 + else if (!precolored.count(u) && precolored.count(v)) { + // u是虚拟寄存器,v是物理寄存器,只更新u的邻接表和度数 + if (adjList[u].find(v) == adjList[u].end()) { + adjList[u].insert(v); + degree[u]++; } } + // 检查是否为 "物理-虚拟" 对 + else if (precolored.count(u) && !precolored.count(v)) { + // u是物理寄存器,v是虚拟寄存器,只更新v的邻接表和度数 + if (adjList[v].find(u) == adjList[v].end()) { + adjList[v].insert(u); + degree[v]++; + } + } + // 如果两个都是物理寄存器,则什么都不做,直接返回。 } RISCv64RegAlloc::VRegSet RISCv64RegAlloc::adjacent(unsigned n) { @@ -1112,10 +1212,13 @@ void RISCv64RegAlloc::combine(unsigned u, unsigned v) { addEdge(t, u); decrementDegree(t); } - int K = isFPVReg(u) ? K_fp : K_int; - if (degree.at(u) >= K && freezeWorklist.count(u)) { - freezeWorklist.erase(u); - spillWorklist.insert(u); + + if (!precolored.count(u)) { + int K = isFPVReg(u) ? K_fp : K_int; + if (degree.at(u) >= K && freezeWorklist.count(u)) { + freezeWorklist.erase(u); + spillWorklist.insert(u); + } } }