#include "RISCv64LinearScan.h" #include "RISCv64LLIR.h" #include "RISCv64ISel.h" #include "RISCv64Info.h" #include "RISCv64AsmPrinter.h" #include #include #include #include #include // 外部调试级别控制变量 extern int DEBUG; extern int DEEPDEBUG; extern int DEEPERDEBUG; namespace sysy { // --- 调试辅助函数 --- // These helpers are self-contained and only used for logging. static std::string pregToString(PhysicalReg preg) { // This map is a copy from AsmPrinter to avoid dependency issues. static const std::map preg_names = { {PhysicalReg::ZERO, "zero"}, {PhysicalReg::RA, "ra"}, {PhysicalReg::SP, "sp"}, {PhysicalReg::GP, "gp"}, {PhysicalReg::TP, "tp"}, {PhysicalReg::T0, "t0"}, {PhysicalReg::T1, "t1"}, {PhysicalReg::T2, "t2"}, {PhysicalReg::T3, "t3"}, {PhysicalReg::T4, "t4"}, {PhysicalReg::T5, "t5"}, {PhysicalReg::T6, "t6"}, {PhysicalReg::S0, "s0"}, {PhysicalReg::S1, "s1"}, {PhysicalReg::S2, "s2"}, {PhysicalReg::S3, "s3"}, {PhysicalReg::S4, "s4"}, {PhysicalReg::S5, "s5"}, {PhysicalReg::S6, "s6"}, {PhysicalReg::S7, "s7"}, {PhysicalReg::S8, "s8"}, {PhysicalReg::S9, "s9"}, {PhysicalReg::S10, "s10"}, {PhysicalReg::S11, "s11"}, {PhysicalReg::A0, "a0"}, {PhysicalReg::A1, "a1"}, {PhysicalReg::A2, "a2"}, {PhysicalReg::A3, "a3"}, {PhysicalReg::A4, "a4"}, {PhysicalReg::A5, "a5"}, {PhysicalReg::A6, "a6"}, {PhysicalReg::A7, "a7"}, {PhysicalReg::F0, "f0"}, {PhysicalReg::F1, "f1"}, {PhysicalReg::F2, "f2"}, {PhysicalReg::F3, "f3"}, {PhysicalReg::F4, "f4"}, {PhysicalReg::F5, "f5"}, {PhysicalReg::F6, "f6"}, {PhysicalReg::F7, "f7"}, {PhysicalReg::F8, "f8"}, {PhysicalReg::F9, "f9"}, {PhysicalReg::F10, "f10"}, {PhysicalReg::F11, "f11"}, {PhysicalReg::F12, "f12"}, {PhysicalReg::F13, "f13"}, {PhysicalReg::F14, "f14"}, {PhysicalReg::F15, "f15"}, {PhysicalReg::F16, "f16"}, {PhysicalReg::F17, "f17"}, {PhysicalReg::F18, "f18"}, {PhysicalReg::F19, "f19"}, {PhysicalReg::F20, "f20"}, {PhysicalReg::F21, "f21"}, {PhysicalReg::F22, "f22"}, {PhysicalReg::F23, "f23"}, {PhysicalReg::F24, "f24"}, {PhysicalReg::F25, "f25"}, {PhysicalReg::F26, "f26"}, {PhysicalReg::F27, "f27"}, {PhysicalReg::F28, "f28"}, {PhysicalReg::F29, "f29"}, {PhysicalReg::F30, "f30"}, {PhysicalReg::F31, "f31"}, {PhysicalReg::INVALID, "INVALID"} }; if (preg_names.count(preg)) return preg_names.at(preg); return "UnknownPreg"; } template static std::string setToString(const std::set& s, std::function formatter) { std::stringstream ss; ss << "{ "; bool first = true; for (const auto& item : s) { if (!first) ss << ", "; ss << formatter(item); first = false; } ss << " }"; return ss.str(); } static std::string vregSetToString(const std::set& s) { return setToString(s, [](unsigned v){ return "%v" + std::to_string(v); }); } static std::string pregSetToString(const std::set& s) { return setToString(s, pregToString); } // Helper function to check if a register is callee-saved. // Defined locally to avoid scope issues. static bool isCalleeSaved(PhysicalReg preg) { if (preg >= PhysicalReg::S0 && preg <= PhysicalReg::S11) return true; if (preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) return true; if (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27) return true; return false; } RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc) : MFunc(mfunc), ISel(mfunc->getISel()), vreg_type_map(ISel->getVRegTypeMap()) { allocable_int_regs = { PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T6, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7, PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11, }; allocable_fp_regs = { PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7, PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17, PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21, PhysicalReg::F22, PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25, PhysicalReg::F26, PhysicalReg::F27, PhysicalReg::F28, PhysicalReg::F29, PhysicalReg::F30, PhysicalReg::F31, }; if (MFunc->getFunc()) { int int_arg_idx = 0; int fp_arg_idx = 0; for (Argument* arg : MFunc->getFunc()->getArguments()) { unsigned arg_vreg = ISel->getVReg(arg); if (arg->getType()->isFloat()) { if (fp_arg_idx < 8) { auto preg = static_cast(static_cast(PhysicalReg::F10) + fp_arg_idx++); abi_vreg_map[arg_vreg] = preg; } } else { if (int_arg_idx < 8) { auto preg = static_cast(static_cast(PhysicalReg::A0) + int_arg_idx++); abi_vreg_map[arg_vreg] = preg; } } } } } bool RISCv64LinearScan::run() { if (DEBUG) std::cerr << "===== [LSRA] Running for function: " << MFunc->getName() << " =====\n"; const int MAX_ITERATIONS = 3; for (int iteration = 1; ; ++iteration) { if (DEBUG && iteration > 1) { std::cerr << "\n----- [LSRA] Re-running iteration " << iteration << " -----\n"; } linearizeBlocks(); computeLiveIntervals(); bool needs_spill = linearScan(); // 如果当前这轮线性扫描不需要溢出,说明分配成功,直接跳出循环。 if (!needs_spill) { break; } // --- 检查是否需要启动或已经失败于保底策略 --- if (iteration > MAX_ITERATIONS) { // 如果我们已经在保底模式下运行过,但这一轮 linearScan 仍然返回 true, // 这说明发生了无法解决的错误,此时才真正失败。 if (conservative_spill_mode) { std::cerr << "\n!!!!!! [LSRA-FATAL] Allocation failed to converge even in Conservative Spill Mode. Triggering final fallback. !!!!!!\n\n"; return false; // 返回失败,而不是exit } // 这是第一次达到最大迭代次数,触发保底策略。 std::cerr << "\n!!!!!! [LSRA-WARN] Convergence failed after " << MAX_ITERATIONS << " iterations. Entering Conservative Spill Mode for the next attempt. !!!!!!\n\n"; conservative_spill_mode = true; // 开启保守溢出模式,将在下一次循环生效 } // 只要需要溢出,就重写程序 if (DEBUG) std::cerr << "[LSRA] Spilling detected, will rewrite program.\n"; rewriteProgram(); } if (DEBUG) std::cerr << "[LSRA] Applying final allocation.\n"; applyAllocation(); MFunc->getFrameInfo().vreg_to_preg_map = this->vreg_to_preg_map; collectUsedCalleeSavedRegs(); if (DEBUG) std::cerr << "===== [LSRA] Finished for function: " << MFunc->getName() << " =====\n\n"; return true; // 分配成功 } void RISCv64LinearScan::linearizeBlocks() { linear_order_blocks.clear(); for (auto& mbb : MFunc->getBlocks()) { linear_order_blocks.push_back(mbb.get()); } } void RISCv64LinearScan::computeLiveIntervals() { if (DEBUG) std::cerr << "[LSRA-Live] Starting live interval computation.\n"; instr_numbering.clear(); live_intervals.clear(); unhandled.clear(); int num = 0; std::set call_locations; for (auto* mbb : linear_order_blocks) { for (auto& instr : mbb->getInstructions()) { instr_numbering[instr.get()] = num; if (instr->getOpcode() == RVOpcodes::CALL) call_locations.insert(num); num += 2; } } if (DEEPDEBUG) std::cerr << " [Live] Starting live variable dataflow analysis...\n"; std::map> live_in, live_out; bool changed = true; int df_iter = 0; while(changed) { changed = false; df_iter++; std::vector reversed_blocks = linear_order_blocks; std::reverse(reversed_blocks.begin(), reversed_blocks.end()); for(auto* mbb : reversed_blocks) { std::set old_live_in = live_in[mbb]; std::set current_live_out; for (auto* succ : mbb->successors) current_live_out.insert(live_in[succ].begin(), live_in[succ].end()); std::set use, def; std::set temp_live = current_live_out; auto& instrs = mbb->getInstructions(); for (auto it = instrs.rbegin(); it != instrs.rend(); ++it) { use.clear(); def.clear(); getInstrUseDef(it->get(), use, def); for (unsigned vreg : def) temp_live.erase(vreg); for (unsigned vreg : use) temp_live.insert(vreg); } if (live_in[mbb] != temp_live || live_out[mbb] != current_live_out) { changed = true; live_in[mbb] = temp_live; live_out[mbb] = current_live_out; } } } if (DEEPDEBUG) std::cerr << " [Live] Dataflow analysis converged after " << df_iter << " iterations.\n"; if (DEEPERDEBUG) { std::cerr << " [Live-Debug] Live-in sets:\n"; for (auto* mbb : linear_order_blocks) std::cerr << " " << mbb->getName() << ": " << vregSetToString(live_in[mbb]) << "\n"; std::cerr << " [Live-Debug] Live-out sets:\n"; for (auto* mbb : linear_order_blocks) std::cerr << " " << mbb->getName() << ": " << vregSetToString(live_out[mbb]) << "\n"; } if (DEEPDEBUG) std::cerr << " [Live] Building precise intervals...\n"; std::map first_def, last_use; for (auto* mbb : linear_order_blocks) { for (auto& instr_ptr : mbb->getInstructions()) { int instr_num = instr_numbering.at(instr_ptr.get()); std::set use, def; getInstrUseDef(instr_ptr.get(), use, def); for (unsigned vreg : def) if (first_def.find(vreg) == first_def.end()) first_def[vreg] = instr_num; for (unsigned vreg : use) last_use[vreg] = instr_num; } } if (DEEPERDEBUG) { std::cerr << " [Live-Debug] First def points:\n"; for (auto const& [vreg, pos] : first_def) std::cerr << " %v" << vreg << ": " << pos << "\n"; std::cerr << " [Live-Debug] Last use points:\n"; for (auto const& [vreg, pos] : last_use) std::cerr << " %v" << vreg << ": " << pos << "\n"; } for (auto const& [vreg, start] : first_def) { live_intervals.emplace(vreg, LiveInterval(vreg)); auto& interval = live_intervals.at(vreg); interval.start = start; interval.end = last_use.count(vreg) ? last_use.at(vreg) : start; } for (auto const& [mbb, live_set] : live_out) { if (mbb->getInstructions().empty()) continue; int block_end_num = instr_numbering.at(mbb->getInstructions().back().get()); for (unsigned vreg : live_set) { if (live_intervals.count(vreg)) { if (DEEPERDEBUG && live_intervals.at(vreg).end < block_end_num) { std::cerr << " [Live-Debug] Extending interval for %v" << vreg << " from " << live_intervals.at(vreg).end << " to " << block_end_num << " due to live_out of " << mbb->getName() << "\n"; } live_intervals.at(vreg).end = std::max(live_intervals.at(vreg).end, block_end_num); } } } for (auto& pair : live_intervals) { auto& interval = pair.second; auto it = call_locations.lower_bound(interval.start); if (it != call_locations.end() && *it < interval.end) interval.crosses_call = true; } for (auto& pair : live_intervals) unhandled.push_back(&pair.second); std::sort(unhandled.begin(), unhandled.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->start < b->start; }); if (DEBUG) { std::cerr << "[LSRA-Live] Finished. Total intervals: " << unhandled.size() << "\n"; if (DEEPDEBUG) { std::cerr << " [Live] Computed Intervals (vreg: [start, end]):\n"; for(const auto* interval : unhandled) { std::cerr << " %v" << interval->vreg << ": [" << interval->start << ", " << interval->end << "]" << (interval->crosses_call ? " (crosses call)" : "") << "\n"; } } } // ================== 新增的调试代码 ================== // 检查活性分析找到的vreg与指令扫描找到的vreg是否一致 if (DEEPERDEBUG) { // 修正:将 std.set 修改为 std::set std::set vregs_from_liveness; for (const auto& pair : live_intervals) { vregs_from_liveness.insert(pair.first); } std::set vregs_from_instr_scan; for (auto* mbb : linear_order_blocks) { for (auto& instr_ptr : mbb->getInstructions()) { std::set use, def; getInstrUseDef(instr_ptr.get(), use, def); vregs_from_instr_scan.insert(use.begin(), use.end()); vregs_from_instr_scan.insert(def.begin(), def.end()); } } std::cerr << " [Live-Debug] VReg Consistency Check:\n"; std::cerr << " VRegs found by Liveness Analysis: " << vregs_from_liveness.size() << "\n"; std::cerr << " VRegs found by getInstrUseDef Scan: " << vregs_from_instr_scan.size() << "\n"; // 修正:将 std.set 修改为 std::set std::set diff; std::set_difference(vregs_from_liveness.begin(), vregs_from_liveness.end(), vregs_from_instr_scan.begin(), vregs_from_instr_scan.end(), std::inserter(diff, diff.begin())); if (!diff.empty()) { std::cerr << " !!!!!! [Live-Debug] DISCREPANCY DETECTED !!!!!!\n"; std::cerr << " The following vregs were found by liveness but NOT by getInstrUseDef scan:\n"; std::cerr << " " << vregSetToString(diff) << "\n"; } else { std::cerr << " [Live-Debug] VReg sets are consistent.\n"; } } // ====================================================== } bool RISCv64LinearScan::linearScan() { // ================== 终极保底策略 (新逻辑) ================== // 当此标志位为true时,我们进入最暴力的溢出模式。 if (conservative_spill_mode) { if (DEBUG) std::cerr << "[LSRA-Scan-Panic] In Conservative Mode. Spilling all unhandled vregs.\n"; // 1. 清空溢出列表,准备重新计算 spilled_vregs.clear(); // 2. 遍历所有计算出的活性区间 for (auto& pair : live_intervals) { // 3. 如果一个vreg不是ABI规定的寄存器,就必须溢出 if (abi_vreg_map.find(pair.first) == abi_vreg_map.end()) { spilled_vregs.insert(pair.first); } } // 4. 只要有任何vreg被标记为溢出,就返回true以触发最终的rewriteProgram。 // 下一轮迭代时,由于所有vreg都已被重写,将不再有新的溢出,保证收敛。 return !spilled_vregs.empty(); } // ========================================================== // ================== 常规线性扫描逻辑 (您已有的代码) ================== // 只有在非保守模式下才会执行以下代码 if (DEBUG) std::cerr << "[LSRA-Scan] Starting main linear scan algorithm.\n"; active.clear(); spilled_vregs.clear(); vreg_to_preg_map.clear(); std::set free_caller_int_regs, free_callee_int_regs; std::set free_caller_fp_regs, free_callee_fp_regs; for (auto preg : allocable_int_regs) { if (isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg); } for (auto preg : allocable_fp_regs) { if (isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg); } if (DEEPDEBUG) { std::cerr << " [Scan] Initial free regs:\n"; std::cerr << " Caller-Saved Int: " << pregSetToString(free_caller_int_regs) << "\n"; std::cerr << " Callee-Saved Int: " << pregSetToString(free_callee_int_regs) << "\n"; } vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end()); std::vector normal_unhandled; for(LiveInterval* interval : unhandled) { if(abi_vreg_map.count(interval->vreg)) { active.push_back(interval); PhysicalReg preg = abi_vreg_map.at(interval->vreg); if (isFPVReg(interval->vreg)) { if(isCalleeSaved(preg)) free_callee_fp_regs.erase(preg); else free_caller_fp_regs.erase(preg); } else { if(isCalleeSaved(preg)) free_callee_int_regs.erase(preg); else free_caller_int_regs.erase(preg); } } else { normal_unhandled.push_back(interval); } } unhandled = normal_unhandled; std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; }); for (LiveInterval* current : unhandled) { if (DEEPDEBUG) std::cerr << "\n [Scan] Processing interval %v" << current->vreg << " [" << current->start << ", " << current->end << "]\n"; std::vector new_active; for (LiveInterval* active_interval : active) { if (active_interval->end < current->start) { PhysicalReg preg = vreg_to_preg_map.at(active_interval->vreg); if (DEEPDEBUG) std::cerr << " [Scan] Expiring interval %v" << active_interval->vreg << ", freeing " << pregToString(preg) << "\n"; if (isFPVReg(active_interval->vreg)) { if(isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg); } else { if(isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg); } } else { new_active.push_back(active_interval); } } active = new_active; bool is_fp = isFPVReg(current->vreg); auto& free_caller = is_fp ? free_caller_fp_regs : free_caller_int_regs; auto& free_callee = is_fp ? free_callee_fp_regs : free_callee_int_regs; PhysicalReg allocated_preg = PhysicalReg::INVALID; if (current->crosses_call) { if (!free_callee.empty()) { allocated_preg = *free_callee.begin(); free_callee.erase(allocated_preg); } } else { if (!free_caller.empty()) { allocated_preg = *free_caller.begin(); free_caller.erase(allocated_preg); } else if (!free_callee.empty()) { allocated_preg = *free_callee.begin(); free_callee.erase(allocated_preg); } } if (allocated_preg != PhysicalReg::INVALID) { if (DEEPDEBUG) std::cerr << " [Scan] Allocated " << pregToString(allocated_preg) << " to %v" << current->vreg << "\n"; vreg_to_preg_map[current->vreg] = allocated_preg; active.push_back(current); std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; }); } else { if (DEEPDEBUG) std::cerr << " [Scan] No free registers for %v" << current->vreg << ". Spilling...\n"; spillAtInterval(current); } } return !spilled_vregs.empty(); } void RISCv64LinearScan::spillAtInterval(LiveInterval* current) { // 保持您的原始逻辑 LiveInterval* spill_candidate = nullptr; if (!active.empty()) { spill_candidate = active.back(); } if (DEEPERDEBUG) { std::cerr << " [Spill-Debug] Spill decision for current=%v" << current->vreg << "[" << current->start << "," << current->end << "]\n"; std::cerr << " [Spill-Debug] Active intervals (sorted by end point):\n"; for (const auto* i : active) { std::cerr << " %v" << i->vreg << "[" << i->start << "," << i->end << "] in " << pregToString(vreg_to_preg_map[i->vreg]) << "\n"; } if(spill_candidate) { std::cerr << " [Spill-Debug] Candidate is %v" << spill_candidate->vreg << ". Its end is " << spill_candidate->end << ", current's end is " << current->end << "\n"; } else { std::cerr << " [Spill-Debug] No active candidate.\n"; } } if (spill_candidate && spill_candidate->end > current->end) { if (DEEPDEBUG) std::cerr << " [Spill] Decision: Spilling active %v" << spill_candidate->vreg << ".\n"; PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg); vreg_to_preg_map.erase(spill_candidate->vreg); // 确保移除旧映射 vreg_to_preg_map[current->vreg] = preg; active.pop_back(); active.push_back(current); std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; }); spilled_vregs.insert(spill_candidate->vreg); } else { if (DEEPDEBUG) std::cerr << " [Spill] Decision: Spilling current %v" << current->vreg << ".\n"; spilled_vregs.insert(current->vreg); } } void RISCv64LinearScan::rewriteProgram() { if (DEBUG) { std::cerr << "[LSRA-Rewrite] Starting program rewrite. Spilled vregs: " << vregSetToString(spilled_vregs) << "\n"; } StackFrameInfo& frame_info = MFunc->getFrameInfo(); int spill_current_offset = frame_info.locals_end_offset - frame_info.spill_size; for (unsigned vreg : spilled_vregs) { // 保持您的原始逻辑 if (frame_info.spill_offsets.count(vreg)) continue; Type* type = vreg_type_map.count(vreg) ? vreg_type_map.at(vreg) : Type::getIntType(); int size = isFPVReg(vreg) ? 4 : (type->isPointer() ? 8 : 4); spill_current_offset -= size; spill_current_offset = (spill_current_offset & ~7); frame_info.spill_offsets[vreg] = spill_current_offset; if (DEEPDEBUG) std::cerr << " [Rewrite] Assigned new stack offset " << frame_info.spill_offsets.at(vreg) << " to spilled %v" << vreg << "\n"; } frame_info.spill_size = -(spill_current_offset - frame_info.locals_end_offset); for (auto& mbb : MFunc->getBlocks()) { auto& instrs = mbb->getInstructions(); std::vector> new_instrs; if (DEEPERDEBUG) std::cerr << " [Rewrite] Processing block " << mbb->getName() << "\n"; for (auto it = instrs.begin(); it != instrs.end(); ++it) { auto& instr = *it; std::set use_vregs, def_vregs; getInstrUseDef(instr.get(), use_vregs, def_vregs); if (conservative_spill_mode) { // ================== 紧急模式重写逻辑 ================== // 直接使用物理寄存器 t4 (SPILL_TEMP_REG) 进行加载/存储 // 为调试日志准备一个指令打印机 auto printer = DEEPERDEBUG ? std::make_unique(MFunc) : nullptr; auto original_instr_str_for_log = DEEPERDEBUG ? printer->formatInstr(instr.get()) : ""; bool modified = false; for (unsigned old_vreg : use_vregs) { if (spilled_vregs.count(old_vreg)) { modified = true; Type* type = vreg_type_map.at(old_vreg); RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW); auto load = std::make_unique(load_op); // 直接加载到保留的物理寄存器 load->addOperand(std::make_unique(SPILL_TEMP_REG)); load->addOperand(std::make_unique( std::make_unique(PhysicalReg::S0), std::make_unique(frame_info.spill_offsets.at(old_vreg)))); if (DEEPERDEBUG) { std::cerr << " [Rewrite-Panic] Inserting LOAD for use of %v" << old_vreg << " into " << pregToString(SPILL_TEMP_REG) << " before: " << original_instr_str_for_log << "\n"; } new_instrs.push_back(std::move(load)); // 替换指令中的操作数 instr->replaceVRegWithPReg(old_vreg, SPILL_TEMP_REG); } } // 在处理 def 之前,先替换定义自身的 vreg for (unsigned old_vreg : def_vregs) { if (spilled_vregs.count(old_vreg)) { modified = true; instr->replaceVRegWithPReg(old_vreg, SPILL_TEMP_REG); } } // 将原始指令(可能已被修改)放入新列表 new_instrs.push_back(std::move(instr)); if (DEEPERDEBUG && modified) { std::cerr << " [Rewrite-Panic] Original: " << original_instr_str_for_log << " -> Rewritten: " << printer->formatInstr(new_instrs.back().get()) << "\n"; } for (unsigned old_vreg : def_vregs) { if (spilled_vregs.count(old_vreg)) { // 指令本身已经被修改为定义到 SPILL_TEMP_REG,现在从它存回内存 Type* type = vreg_type_map.at(old_vreg); RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW); auto store = std::make_unique(store_op); store->addOperand(std::make_unique(SPILL_TEMP_REG)); store->addOperand(std::make_unique( std::make_unique(PhysicalReg::S0), std::make_unique(frame_info.spill_offsets.at(old_vreg)))); if (DEEPERDEBUG) { std::cerr << " [Rewrite-Panic] Inserting STORE for def of %v" << old_vreg << " from " << pregToString(SPILL_TEMP_REG) << " after original instr.\n"; } new_instrs.push_back(std::move(store)); } } } else { // ================== 常规模式重写逻辑 (您的原始代码) ================== std::map use_remap, def_remap; for (unsigned old_vreg : use_vregs) { if (spilled_vregs.count(old_vreg) && use_remap.find(old_vreg) == use_remap.end()) { Type* type = vreg_type_map.at(old_vreg); unsigned new_temp_vreg = ISel->getNewVReg(type); use_remap[old_vreg] = new_temp_vreg; RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW); auto load = std::make_unique(load_op); load->addOperand(std::make_unique(new_temp_vreg)); load->addOperand(std::make_unique( std::make_unique(PhysicalReg::S0), std::make_unique(frame_info.spill_offsets.at(old_vreg)))); if (DEEPERDEBUG) { RISCv64AsmPrinter printer(MFunc); std::cerr << " [Rewrite] Inserting LOAD for use of %v" << old_vreg << " into new %v" << new_temp_vreg << " before: " << printer.formatInstr(instr.get()) << "\n"; } new_instrs.push_back(std::move(load)); } } for (unsigned old_vreg : def_vregs) { if (spilled_vregs.count(old_vreg) && def_remap.find(old_vreg) == def_remap.end()) { Type* type = vreg_type_map.at(old_vreg); unsigned new_temp_vreg = ISel->getNewVReg(type); def_remap[old_vreg] = new_temp_vreg; } } auto original_instr_str_for_log = DEEPERDEBUG ? RISCv64AsmPrinter(MFunc).formatInstr(instr.get()) : ""; instr->remapVRegs(use_remap, def_remap); new_instrs.push_back(std::move(instr)); if (DEEPERDEBUG && (!use_remap.empty() || !def_remap.empty())) std::cerr << " [Rewrite] Original: " << original_instr_str_for_log << " -> Rewritten: " << RISCv64AsmPrinter(MFunc).formatInstr(new_instrs.back().get()) << "\n"; for(const auto& pair : def_remap) { unsigned old_vreg = pair.first; unsigned new_temp_vreg = pair.second; Type* type = vreg_type_map.at(old_vreg); RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW); auto store = std::make_unique(store_op); store->addOperand(std::make_unique(new_temp_vreg)); store->addOperand(std::make_unique( std::make_unique(PhysicalReg::S0), std::make_unique(frame_info.spill_offsets.at(old_vreg)))); if (DEEPERDEBUG) std::cerr << " [Rewrite] Inserting STORE for def of %v" << old_vreg << " from new %v" << new_temp_vreg << " after original instr.\n"; new_instrs.push_back(std::move(store)); } } } instrs = std::move(new_instrs); } } void RISCv64LinearScan::applyAllocation() { if (DEBUG) std::cerr << "[LSRA-Apply] Applying final vreg->preg mapping.\n"; for (auto& mbb : MFunc->getBlocks()) { for (auto& instr_ptr : mbb->getInstructions()) { for (auto& op_ptr : instr_ptr->getOperands()) { if (op_ptr->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(op_ptr.get()); if (reg_op->isVirtual()) { unsigned vreg = reg_op->getVRegNum(); if (vreg_to_preg_map.count(vreg)) { reg_op->setPReg(vreg_to_preg_map.at(vreg)); } else { std::cerr << "ERROR: Uncolored virtual register %v" << vreg << " found during applyAllocation! in func " << MFunc->getName() << "\n"; // Forcing an error is better than silent failure. // reg_op->setPReg(PhysicalReg::T5); } } } else if (op_ptr->getKind() == MachineOperand::KIND_MEM) { auto mem_op = static_cast(op_ptr.get()); auto reg_op = mem_op->getBase(); if (reg_op->isVirtual()) { unsigned vreg = reg_op->getVRegNum(); if (vreg_to_preg_map.count(vreg)) { reg_op->setPReg(vreg_to_preg_map.at(vreg)); } else { std::cerr << "ERROR: Uncolored virtual register %v" << vreg << " in memory operand! in func " << MFunc->getName() << "\n"; // reg_op->setPReg(PhysicalReg::T5); } } } } } } } // void getInstrUseDef(const MachineInstr* instr, std::set& use, std::set& def) { // auto opcode = instr->getOpcode(); // const auto& operands = instr->getOperands(); // auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set& s) { // if (op->getKind() == MachineOperand::KIND_REG) { // auto reg_op = static_cast(op); // if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum()); // } else if (op->getKind() == MachineOperand::KIND_MEM) { // auto mem_op = static_cast(op); // auto reg_op = mem_op->getBase(); // if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum()); // } // }; // if (op_info.count(opcode)) { // const auto& info = op_info.at(opcode); // for (int idx : info.first) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), def); // for (int idx : info.second) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), use); // for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use); // } else if (opcode == RVOpcodes::CALL) { // if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def); // for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[i].get(), use); // } // } bool RISCv64LinearScan::isFPVReg(unsigned vreg) const { return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat(); } void RISCv64LinearScan::collectUsedCalleeSavedRegs() { StackFrameInfo& frame_info = MFunc->getFrameInfo(); frame_info.used_callee_saved_regs.clear(); const auto& callee_saved_int = getCalleeSavedIntRegs(); const auto& callee_saved_fp = getCalleeSavedFpRegs(); std::set callee_saved_set(callee_saved_int.begin(), callee_saved_int.end()); callee_saved_set.insert(callee_saved_fp.begin(), callee_saved_fp.end()); callee_saved_set.insert(PhysicalReg::S0); for(const auto& pair : vreg_to_preg_map) { PhysicalReg preg = pair.second; if(callee_saved_set.count(preg)) { frame_info.used_callee_saved_regs.insert(preg); } } } } // namespace sysy