[backend-IRC]修复了keepalive伪指令处理缺失的问题

This commit is contained in:
Lixuanwang
2025-08-01 12:15:03 +08:00
parent 166d0fc372
commit 8fe9867f33
4 changed files with 494 additions and 270 deletions

View File

@@ -1,6 +1,7 @@
#include "EliminateFrameIndices.h" #include "EliminateFrameIndices.h"
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include <cassert> #include <cassert>
#include <vector> // [新增] 为插入指令而包含
namespace sysy { namespace sysy {
@@ -35,6 +36,8 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
// 1. [已移除] 不再处理栈传递的参数 // 1. [已移除] 不再处理栈传递的参数
// 原先处理栈参数 (arg_idx >= 8) 的逻辑已被移除。 // 原先处理栈参数 (arg_idx >= 8) 的逻辑已被移除。
// 这项职责已完全转移到 PrologueEpilogueInsertionPass以避免逻辑冲突和错误。 // 这项职责已完全转移到 PrologueEpilogueInsertionPass以避免逻辑冲突和错误。
// [注释更新] -> 上述注释已过时。根据新方案,我们将在这里处理栈传递的参数,
// 以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量 // 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后 // 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
@@ -63,8 +66,55 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
// 记录仅由AllocaInst分配的局部变量的总大小 // 记录仅由AllocaInst分配的局部变量的总大小
frame_info.locals_size = local_var_offset - 16; frame_info.locals_size = local_var_offset - 16;
// 3. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令 // 3. [核心修改] 在函数入口为所有栈传递的参数插入load指令
// 这个步骤至关重要它在寄存器分配之前为这些参数的vreg创建了明确的“定义(def)”指令。
// 这解决了在高寄存器压力下当这些vreg被溢出时`rewriteProgram`找不到其定义点而崩溃的问题。
if (F && isel && !mfunc->getBlocks().empty()) {
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs;
int arg_idx = 0;
for (Argument* arg : F->getArguments()) {
// 根据ABI前8个整型/指针参数通过寄存器传递,这里只处理超出部分。
if (arg_idx >= 8) {
// 计算参数在调用者栈帧中的位置该位置相对于被调用者的帧指针s0是正向偏移。
// 第9个参数(arg_idx=8)位于 0(s0)第10个(arg_idx=9)位于 8(s0),以此类推。
int offset = (arg_idx - 8) * 8;
unsigned arg_vreg = isel->getVReg(arg);
Type* arg_type = arg->getType();
// 根据参数类型选择正确的加载指令
RVOpcodes load_op;
if (arg_type->isFloat()) {
load_op = RVOpcodes::FLW; // 单精度浮点
} else if (arg_type->isPointer()) {
load_op = RVOpcodes::LD; // 64位指针
} else {
load_op = RVOpcodes::LW; // 32位整数
}
// 创建加载指令: lw/ld/flw vreg, offset(s0)
auto load_instr = std::make_unique<MachineInstr>(load_op);
load_instr->addOperand(std::make_unique<RegOperand>(arg_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针
std::make_unique<ImmOperand>(offset)
));
arg_load_instrs.push_back(std::move(load_instr));
}
arg_idx++;
}
// 将所有新创建的参数加载指令一次性插入到入口块的起始位置
auto& entry_instrs = entry_block->getInstructions();
entry_instrs.insert(entry_instrs.begin(),
std::make_move_iterator(arg_load_instrs.begin()),
std::make_move_iterator(arg_load_instrs.end()));
}
// 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令
// 由于处理参数的逻辑已移除,这里的展开现在只针对局部变量,因此是正确的。 // 由于处理参数的逻辑已移除,这里的展开现在只针对局部变量,因此是正确的。
// [注释更新] -> 上述注释已过时。此部分逻辑保持不变,它正确地处理了局部变量。
for (auto& mbb : mfunc->getBlocks()) { for (auto& mbb : mfunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions; std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) { for (auto& instr_ptr : mbb->getInstructions()) {

View File

@@ -114,33 +114,9 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
prologue_instrs.push_back(std::move(save_cs_reg)); prologue_instrs.push_back(std::move(save_cs_reg));
} }
// 4.5. [核心] 加载所有通过栈传递参数 // 4.5. [核心修改] 加载栈传递参数的逻辑已从此移除
// 这些参数位于 s0 上方 (正偏移量) // 这项工作已经前移至 `EliminateFrameIndicesPass` 中完成,
if (F && isel) { // 以确保在寄存器分配前就将相关虚拟寄存器定义从而修复溢出逻辑的bug。
int arg_idx = 0;
for (Argument* arg : F->getArguments()) {
if (arg_idx >= 8) {
unsigned vreg = isel->getVReg(arg);
if (vreg_to_preg_map.count(vreg)) {
// 计算正确的正偏移量
int offset = (arg_idx - 8) * 8;
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
Type* arg_type = arg->getType();
// 根据类型生成对应的加载指令
RVOpcodes load_op = arg_type->isFloat() ? RVOpcodes::FLW : (arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW);
auto load_arg = std::make_unique<MachineInstr>(load_op);
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
load_arg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
prologue_instrs.push_back(std::move(load_arg));
}
}
arg_idx++;
}
}
// 4.6. 将所有生成的序言指令一次性插入到函数入口 // 4.6. 将所有生成的序言指令一次性插入到函数入口
entry_instrs.insert(entry_instrs.begin(), entry_instrs.insert(entry_instrs.begin(),

View File

@@ -108,9 +108,13 @@ std::string RISCv64CodeGen::module_gen() {
} }
std::string RISCv64CodeGen::function_gen(Function* func) { std::string RISCv64CodeGen::function_gen(Function* func) {
if (DEBUG) {
// === 完整的后端处理流水线 === // === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) // 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
DEEPDEBUG = 0;
RISCv64ISel isel; RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func); std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
@@ -121,10 +125,10 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
// if (DEBUG) { // if (DEBUG) {
// std::cout << ss_after_isel.str(); // std::cout << ss_after_isel.str();
// } // }
// DEBUG = 0; DEBUG = 0;
// DEEPDEBUG = 0; DEEPDEBUG = 0;
// DEBUG = 1; DEBUG = 1;
// DEEPDEBUG = 1; DEEPDEBUG = 1;
if (DEBUG) { if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str(); << ss_after_isel.str();
@@ -139,6 +143,10 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
if (DEBUG) { if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n"; std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr); mfunc->dumpStackFrameInfo(std::cerr);
// std::stringstream ss_after_eli;
// printer_isel.run(ss_after_eli, true);
// std::cerr << "====== LLIR after eliminate frame indices ======\n"
// << ss_after_eli.str();
} }
// // 阶段 2: 指令调度 (Instruction Scheduling) // // 阶段 2: 指令调度 (Instruction Scheduling)
@@ -147,10 +155,14 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
// DEBUG = 0; // DEBUG = 0;
// DEEPDEBUG = 0; // DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation) // 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get()); RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run(); reg_alloc.run();
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1; // DEBUG = 1;
// DEEPDEBUG = 1; // DEEPDEBUG = 1;
if (DEBUG) { if (DEBUG) {
@@ -198,4 +210,118 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
return ss.str(); return ss.str();
} }
else {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
DEEPDEBUG = 0;
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
// if (DEBUG) {
// std::cout << ss_after_isel.str();
// }
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// DEBUG = 0;
// DEEPDEBUG = 0;
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
std::stringstream ss_after_eli;
printer_isel.run(ss_after_eli, true);
std::cerr << "====== LLIR after eliminate frame indices ======\n"
<< ss_after_eli.str();
}
// // 阶段 2: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
// PostRA_Scheduler local_scheduler;
// local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) {
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
<< ss_after_isel.str();
}
return ss.str();
}
}
} // namespace sysy } // namespace sysy

View File

@@ -564,6 +564,40 @@ void RISCv64RegAlloc::freeze() {
freezeMoves(u); freezeMoves(u);
} }
// // 选择溢出节点
// // in file: RISCv64RegAlloc.cpp
// void RISCv64RegAlloc::selectSpill() {
// // [核心逻辑修正] 遵从 George & Appel 论文的“乐观着色”策略。
// // 此函数不再将节点直接放入 spilledNodes。
// // 它的作用是选择一个“潜在溢出”节点,并将其移回 simplifyWorklist以打破僵局。
// // 真正的溢出决策被推迟到 AssignColors 阶段。
// // 使用启发式规则从 spillWorklist 中选择一个节点 m。
// // 论文建议使用代价函数,这里我们继续使用度数最高的简单启发式。
// auto it = std::max_element(spillWorklist.begin(), spillWorklist.end(),
// [&](unsigned a, unsigned b){ return degree.at(a) < degree.at(b); });
// // 理论上此时 spillWorklist 不应为空,但做保护性检查。
// if (it == spillWorklist.end()) {
// return;
// }
// unsigned m = *it;
// // 1. 将选中的节点 m 从溢出工作列表移动到简化工作列表。
// spillWorklist.erase(it);
// simplifyWorklist.insert(m); //
// // 2. 冻结与 m 相关的所有传送指令,因为我们已经放弃了对它的合并尝试。
// freezeMoves(m); //
// if (DEEPDEBUG) {
// std::cerr << "[Spill] Optimistically moving %vreg" << m
// << " from spillWorklist to simplifyWorklist.\n";
// }
// }
// 选择溢出节点 // 选择溢出节点
void RISCv64RegAlloc::selectSpill() { void RISCv64RegAlloc::selectSpill() {
auto it = std::max_element(spillWorklist.begin(), spillWorklist.end(), auto it = std::max_element(spillWorklist.begin(), spillWorklist.end(),
@@ -578,7 +612,7 @@ void RISCv64RegAlloc::selectSpill() {
void RISCv64RegAlloc::assignColors() { void RISCv64RegAlloc::assignColors() {
if (DEEPDEBUG) std::cerr << "[AssignColors] Starting...\n"; if (DEEPDEBUG) std::cerr << "[AssignColors] Starting...\n";
// 步骤 1: 完整处理 selectStack // 步骤 1: selectStack 中的节点分配颜色 (此部分逻辑不变)
while (!selectStack.empty()) { while (!selectStack.empty()) {
unsigned n = selectStack.back(); unsigned n = selectStack.back();
selectStack.pop_back(); selectStack.pop_back();
@@ -586,26 +620,22 @@ void RISCv64RegAlloc::assignColors() {
const auto& available_regs = is_fp ? allocable_fp_regs : allocable_int_regs; const auto& available_regs = is_fp ? allocable_fp_regs : allocable_int_regs;
std::set<PhysicalReg> ok_colors(available_regs.begin(), available_regs.end()); std::set<PhysicalReg> ok_colors(available_regs.begin(), available_regs.end());
if (adjList.count(n)) {
for (unsigned w : adjList.at(n)) { for (unsigned w : adjList.at(n)) {
unsigned w_alias = getAlias(w); unsigned w_alias = getAlias(w);
bool is_colored_vreg = coloredNodes.count(w_alias);
bool is_physical_reg = precolored.count(w_alias);
const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
if (is_colored_vreg || is_physical_reg) { if (coloredNodes.count(w_alias)) { // 邻居是已着色的vreg
PhysicalReg neighbor_color; ok_colors.erase(color_map.at(w_alias));
if (is_colored_vreg) { } else if (precolored.count(w_alias)) { // 邻居是物理寄存器
neighbor_color = color_map.at(w_alias); const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
} else { ok_colors.erase(static_cast<PhysicalReg>(w_alias - offset));
neighbor_color = static_cast<PhysicalReg>(w_alias - offset);
} }
ok_colors.erase(neighbor_color);
} }
} }
if (ok_colors.empty()) { if (ok_colors.empty()) {
if (DEEPDEBUG) std::cerr << " -> No color for %vreg" << n << ". Spilling.\n";
spilledNodes.insert(n); spilledNodes.insert(n);
if (DEEPDEBUG) std::cerr << " -> WARNING: No color for %vreg" << n << " from selectStack. Spilling.\n";
} else { } else {
PhysicalReg c = *ok_colors.begin(); PhysicalReg c = *ok_colors.begin();
coloredNodes.insert(n); coloredNodes.insert(n);
@@ -614,41 +644,41 @@ void RISCv64RegAlloc::assignColors() {
} }
} }
// 步骤 2: 独立、完整地处理 coalescedNodes // 步骤 2: [最终修正] 完整、正确地处理 coalescedNodes
for (unsigned n : coalescedNodes) { for (unsigned n : coalescedNodes) {
unsigned root_alias = getAlias(n); unsigned root_alias = getAlias(n);
// 情况 1: 别名是物理寄存器,直接获得该颜色 // --- 新的、健壮的逻辑,处理所有三种可能性 ---
// 情况 1: 别名本身就是物理寄存器 (修复当前bug)
if (precolored.count(root_alias)) { if (precolored.count(root_alias)) {
const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID); const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
color_map[n] = static_cast<PhysicalReg>(root_alias - offset); color_map[n] = static_cast<PhysicalReg>(root_alias - offset);
if (DEEPDEBUG) std::cerr << " -> Coalesced " << regIdToString(n) << " gets color from physical alias " << regIdToString(root_alias) << ".\n"; if (DEEPDEBUG) std::cerr << " -> Coalesced %vreg" << n << " gets color from PHYSICAL alias " << regIdToString(root_alias) << ".\n";
} }
// 情况 2: 别名是虚拟寄存器且在步骤1中已被成功着色 // 情况 2: 别名是被成功着色的虚拟寄存器
else if (color_map.count(root_alias)) { else if (color_map.count(root_alias)) {
color_map[n] = color_map.at(root_alias); color_map[n] = color_map.at(root_alias);
if (DEEPDEBUG) std::cerr << " -> Coalesced " << regIdToString(n) << " gets color of virtual alias " << regIdToString(root_alias) << ".\n"; if (DEEPDEBUG) std::cerr << " -> Coalesced %vreg" << n << " gets color from VIRTUAL alias " << regIdToString(root_alias) << ".\n";
} }
// 情况 3: 别名是虚拟寄存器但在步骤1中未能着色即被溢出 // 情况 3: 别名是被溢出的虚拟寄存器
else { else {
if (DEEPDEBUG) std::cerr << " -> Alias " << regIdToString(root_alias) << " of %vreg" << n << " was spilled. Spilling.\n";
spilledNodes.insert(n); spilledNodes.insert(n);
if (DEEPDEBUG) std::cerr << " -> Alias " << regIdToString(root_alias) << " of %vreg" << n << " was SPILLED. Spilling %vreg" << n << " as well.\n";
} }
} }
} }
// 重写程序,插入溢出代码 // 重写程序,插入溢出代码
void RISCv64RegAlloc::rewriteProgram() { void RISCv64RegAlloc::rewriteProgram() {
// 1. 为溢出的旧vreg在栈上分配空间 (这部分逻辑不变) // 1. 为溢出的旧vreg在栈上分配空间
StackFrameInfo& frame_info = MFunc->getFrameInfo(); StackFrameInfo& frame_info = MFunc->getFrameInfo();
// locals_size, callee_saved_size等已经由之前的步骤或上一次运行计算好
// 我们在此基础上累加溢出区大小
int spill_base_offset = frame_info.locals_size + frame_info.callee_saved_size; int spill_base_offset = frame_info.locals_size + frame_info.callee_saved_size;
for (unsigned vreg : spilledNodes) { for (unsigned vreg : spilledNodes) {
if (frame_info.spill_offsets.count(vreg)) continue; // 如果已经分配过则跳过 if (frame_info.spill_offsets.count(vreg)) continue;
int size = 4; // 默认4字节 int size = 4;
if (isFPVReg(vreg)) { if (isFPVReg(vreg)) {
size = 4; // float size = 4; // float
} else if (vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isPointer()) { } else if (vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isPointer()) {
@@ -656,33 +686,28 @@ void RISCv64RegAlloc::rewriteProgram() {
} }
spill_base_offset += size; spill_base_offset += size;
spill_base_offset = (spill_base_offset + 7) & ~7; // 8字节对齐 spill_base_offset = (spill_base_offset + 7) & ~7;
frame_info.spill_offsets[vreg] = spill_base_offset; frame_info.spill_offsets[vreg] = -spill_base_offset; // [修正] 溢出槽也使用负偏移量
} }
frame_info.spill_size = spill_base_offset - (frame_info.locals_size + frame_info.callee_saved_size); frame_info.spill_size = spill_base_offset - (frame_info.locals_size + frame_info.callee_saved_size);
// 2. 遍历所有指令,为溢出vreg的use/def插入load/store并使用新的临时虚拟寄存器 // 2. 遍历所有指令,重写代码
for (auto& mbb : MFunc->getBlocks()) { for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions; std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) { for (auto& instr_ptr : mbb->getInstructions()) {
// 对每条指令记录其使用的旧vreg到新临时vreg的映射 std::map<unsigned, unsigned> use_remap;
std::map<unsigned, unsigned> vreg_remap; std::map<unsigned, unsigned> def_remap;
// a. 为每个溢出的 use 操作数,在原指令前插入 load 指令
VRegSet use, def; VRegSet use, def;
getInstrUseDef_Liveness(instr_ptr.get(), use, def); // 假设此函数能正确处理operands getInstrUseDef_Liveness(instr_ptr.get(), use, def);
for(auto& op : instr_ptr->getOperands()) { // a. 为每个溢出的 use 操作数创建新vreg并插入 load
if (op->getKind() == MachineOperand::KIND_REG) { for (unsigned old_vreg : use) {
auto reg_op = static_cast<RegOperand*>(op.get()); if (spilledNodes.count(old_vreg)) {
if (reg_op->isVirtual() && spilledNodes.count(reg_op->getVRegNum()) && use.count(reg_op->getVRegNum())) {
unsigned old_vreg = reg_op->getVRegNum();
// 仅当还未为此vreg创建临时替身时才创建
if (vreg_remap.find(old_vreg) == vreg_remap.end()) {
Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType(); Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType();
unsigned new_temp_vreg = ISel->getNewVReg(type); unsigned new_temp_vreg = ISel->getNewVReg(type);
vreg_remap[old_vreg] = new_temp_vreg; use_remap[old_vreg] = new_temp_vreg;
RVOpcodes load_op; RVOpcodes load_op;
if (isFPVReg(old_vreg)) load_op = RVOpcodes::FLW; if (isFPVReg(old_vreg)) load_op = RVOpcodes::FLW;
@@ -693,63 +718,68 @@ void RISCv64RegAlloc::rewriteProgram() {
load->addOperand(std::make_unique<RegOperand>(new_temp_vreg)); load->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
load->addOperand(std::make_unique<MemOperand>( load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(-frame_info.spill_offsets.at(old_vreg)) // 偏移是相对于S0的负值 std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
)); ));
new_instructions.push_back(std::move(load)); new_instructions.push_back(std::move(load));
} }
} }
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto reg_op = static_cast<MemOperand*>(op.get())->getBase(); // b. 为每个溢出的 def 操作数创建新vreg
if (reg_op->isVirtual() && spilledNodes.count(reg_op->getVRegNum())) { for (unsigned old_vreg : def) {
unsigned old_vreg = reg_op->getVRegNum(); if (spilledNodes.count(old_vreg)) {
if (vreg_remap.find(old_vreg) == vreg_remap.end()) {
Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType(); Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType();
unsigned new_temp_vreg = ISel->getNewVReg(type); unsigned new_temp_vreg = ISel->getNewVReg(type);
vreg_remap[old_vreg] = new_temp_vreg; def_remap[old_vreg] = new_temp_vreg;
}
}
RVOpcodes load_op = (type->isPointer()) ? RVOpcodes::LD : RVOpcodes::LW; // c. [核心修正] 创建一条全新的指令用新vreg替换旧vreg
auto load = std::make_unique<MachineInstr>(load_op); auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
load->addOperand(std::make_unique<RegOperand>(new_temp_vreg)); for (const auto& op : instr_ptr->getOperands()) {
load->addOperand(std::make_unique<MemOperand>( if (op->getKind() == MachineOperand::KIND_REG) {
std::make_unique<RegOperand>(PhysicalReg::S0), auto reg_op = static_cast<RegOperand*>(op.get());
std::make_unique<ImmOperand>(-frame_info.spill_offsets.at(old_vreg)) if (reg_op->isVirtual()) {
unsigned old_vreg = reg_op->getVRegNum();
if (use.count(old_vreg) && use_remap.count(old_vreg)) {
new_instr->addOperand(std::make_unique<RegOperand>(use_remap.at(old_vreg)));
} else if (def.count(old_vreg) && def_remap.count(old_vreg)) {
new_instr->addOperand(std::make_unique<RegOperand>(def_remap.at(old_vreg)));
} else {
new_instr->addOperand(std::make_unique<RegOperand>(old_vreg));
}
} else {
new_instr->addOperand(std::make_unique<RegOperand>(reg_op->getPReg()));
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op.get());
auto base_reg = mem_op->getBase();
unsigned old_vreg = base_reg->isVirtual() ? base_reg->getVRegNum() : -1;
if (base_reg->isVirtual() && use_remap.count(old_vreg)) {
new_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(use_remap.at(old_vreg)),
std::make_unique<ImmOperand>(mem_op->getOffset()->getValue())
)); ));
new_instructions.push_back(std::move(load)); } else {
} new_instr->addOperand(std::make_unique<MemOperand>(
} std::make_unique<RegOperand>(*base_reg),
std::make_unique<ImmOperand>(mem_op->getOffset()->getValue())
));
}
} else { // 立即数、标签等直接复制
if(op->getKind() == MachineOperand::KIND_IMM)
new_instr->addOperand(std::make_unique<ImmOperand>(*static_cast<ImmOperand*>(op.get())));
else if (op->getKind() == MachineOperand::KIND_LABEL)
new_instr->addOperand(std::make_unique<LabelOperand>(*static_cast<LabelOperand*>(op.get())));
} }
} }
new_instructions.push_back(std::move(new_instr));
// b. 替换原指令中的操作数,并将其加入新指令列表 // d. 为每个溢出的 def 操作数,在原指令后插入 store 指令
for(auto& op : instr_ptr->getOperands()) { for (const auto& pair : def_remap) {
if (op->getKind() == MachineOperand::KIND_REG) { unsigned old_vreg = pair.first;
auto reg_op = static_cast<RegOperand*>(op.get()); unsigned new_temp_vreg = pair.second;
if (reg_op->isVirtual() && vreg_remap.count(reg_op->getVRegNum())) {
reg_op->setVRegNum(vreg_remap.at(reg_op->getVRegNum()));
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto reg_op = static_cast<MemOperand*>(op.get())->getBase();
if (reg_op->isVirtual() && vreg_remap.count(reg_op->getVRegNum())) {
reg_op->setVRegNum(vreg_remap.at(reg_op->getVRegNum()));
}
}
}
new_instructions.push_back(std::move(instr_ptr));
// c. 为每个溢出的 def 操作数,在原指令后插入 store 指令
vreg_remap.clear(); // 清空映射为def创建新的临时vreg
for(auto& op : new_instructions.back()->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op.get());
if (reg_op->isVirtual() && spilledNodes.count(reg_op->getVRegNum()) && def.count(reg_op->getVRegNum())) {
unsigned old_vreg = reg_op->getVRegNum();
if (vreg_remap.find(old_vreg) == vreg_remap.end()) {
Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType(); Type* type = vreg_type_map.count(old_vreg) ? vreg_type_map.at(old_vreg) : Type::getIntType();
unsigned new_temp_vreg = ISel->getNewVReg(type);
vreg_remap[old_vreg] = new_temp_vreg; // 记录从old到new的映射
// 再次修改指令将def的vreg也换成新的临时vreg
reg_op->setVRegNum(new_temp_vreg);
RVOpcodes store_op; RVOpcodes store_op;
if (isFPVReg(old_vreg)) store_op = RVOpcodes::FSW; if (isFPVReg(old_vreg)) store_op = RVOpcodes::FSW;
@@ -757,18 +787,14 @@ void RISCv64RegAlloc::rewriteProgram() {
else store_op = RVOpcodes::SW; else store_op = RVOpcodes::SW;
auto store = std::make_unique<MachineInstr>(store_op); auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(new_temp_vreg)); // 从新的临时vreg中存值 store->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
store->addOperand(std::make_unique<MemOperand>( store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(-frame_info.spill_offsets.at(old_vreg)) std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
)); ));
// 在原指令之后插入store
new_instructions.push_back(std::move(store)); new_instructions.push_back(std::move(store));
} }
} }
}
}
}
mbb->getInstructions() = std::move(new_instructions); mbb->getInstructions() = std::move(new_instructions);
} }
@@ -828,9 +854,11 @@ void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VR
} }
} }
// in file: RISCv64RegAlloc.cpp
/** /**
* @brief [修复] 获取一条指令完整的、包含物理寄存器的Use/Def集合 * @brief [最终修复] 获取一条指令完整的、包含物理寄存器的Use/Def集合
* 这个函数专门服务于活跃性分析。 * 这个函数专门服务于活跃性分析,现已补全所有指令(包括伪指令)的逻辑
*/ */
void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) { void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) {
auto opcode = instr->getOpcode(); auto opcode = instr->getOpcode();
@@ -838,37 +866,17 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
// 映射表:指令操作码 -> {Def操作数索引列表, Use操作数索引列表} // 映射表:指令操作码 -> {Def操作数索引列表, Use操作数索引列表}
static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = { static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = {
// ===== 已有指令定义 (保留) ===== // ===== 整数算术与逻辑指令 (R-type & I-type) =====
{RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}}, {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::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}}}, {RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}},
{RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}}, {RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}},
{RVOpcodes::XOR, {{0}, {1, 2}}}, {RVOpcodes::OR, {{0}, {1, 2}}}, {RVOpcodes::AND, {{0}, {1, 2}}},
{RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}}, {RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}},
{RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}}, {RVOpcodes::ORI, {{0}, {1}}}, {RVOpcodes::ANDI, {{0}, {1}}},
{RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}}, {RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}},
{RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
{RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}},
{RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
{RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}},
{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::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::SLL, {{0}, {1, 2}}}, {RVOpcodes::SLLI, {{0}, {1}}},
{RVOpcodes::SLLW, {{0}, {1, 2}}}, {RVOpcodes::SLLIW, {{0}, {1}}}, {RVOpcodes::SLLW, {{0}, {1, 2}}}, {RVOpcodes::SLLIW, {{0}, {1}}},
{RVOpcodes::SRL, {{0}, {1, 2}}}, {RVOpcodes::SRLI, {{0}, {1}}}, {RVOpcodes::SRL, {{0}, {1, 2}}}, {RVOpcodes::SRLI, {{0}, {1}}},
@@ -876,19 +884,34 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
{RVOpcodes::SRA, {{0}, {1, 2}}}, {RVOpcodes::SRAI, {{0}, {1}}}, {RVOpcodes::SRA, {{0}, {1, 2}}}, {RVOpcodes::SRAI, {{0}, {1}}},
{RVOpcodes::SRAW, {{0}, {1, 2}}}, {RVOpcodes::SRAIW, {{0}, {1}}}, {RVOpcodes::SRAW, {{0}, {1, 2}}}, {RVOpcodes::SRAIW, {{0}, {1}}},
// --- 控制流指令 (补全) --- // ===== 内存加载指令 (Def: 0, Use: MemBase) =====
{RVOpcodes::BLTU, {{}, {0, 1}}}, {RVOpcodes::LB, {{0}, {}}}, {RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}},
{RVOpcodes::BGEU, {{}, {0, 1}}}, {RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
// J 没有寄存器操作数JAL 由CALL指令类似的特殊逻辑处理 {RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}},
// --- 伪指令 (补全) --- // ===== 内存存储指令 (Def: None, Use: ValToStore, MemBase) =====
{RVOpcodes::NEG, {{0}, {1}}}, {RVOpcodes::SB, {{}, {0, 1}}}, {RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
{RVOpcodes::NEGW, {{0}, {1}}}, {RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}},
// ===== 新增的指令定义结束 ===== // ===== 控制流指令 =====
{RVOpcodes::BEQ, {{}, {0, 1}}}, {RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}},
{RVOpcodes::BGE, {{}, {0, 1}}}, {RVOpcodes::BLTU, {{}, {0, 1}}}, {RVOpcodes::BGEU, {{}, {0, 1}}},
{RVOpcodes::JALR, {{0}, {1}}}, // def: ra (implicit) and op0, use: op1
// ===== 浮点指令 =====
{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::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}},
{RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}},
{RVOpcodes::NEG, {{0}, {1}}}, {RVOpcodes::NEGW, {{0}, {1}}},
}; };
// lambda表达式用于获取操作数的寄存器ID虚拟或物理,逻辑正确,保持不变 // lambda表达式用于获取操作数的寄存器ID虚拟或物理
const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID); const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
auto get_any_reg_id = [&](const MachineOperand* op) -> unsigned { auto get_any_reg_id = [&](const MachineOperand* op) -> unsigned {
if (op->getKind() == MachineOperand::KIND_REG) { if (op->getKind() == MachineOperand::KIND_REG) {
@@ -902,6 +925,7 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
return (unsigned)-1; return (unsigned)-1;
}; };
// --- 主要处理逻辑 ---
if (op_info.count(opcode)) { if (op_info.count(opcode)) {
const auto& info = op_info.at(opcode); const auto& info = op_info.at(opcode);
for (int idx : info.first) if (idx < operands.size()) { for (int idx : info.first) if (idx < operands.size()) {
@@ -912,7 +936,7 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
unsigned reg_id = get_any_reg_id(operands[idx].get()); unsigned reg_id = get_any_reg_id(operands[idx].get());
if (reg_id != (unsigned)-1) use.insert(reg_id); if (reg_id != (unsigned)-1) use.insert(reg_id);
} }
// 不要忘记内存操作数中的基址寄存器永远是use // 对于所有内存操作基址寄存器都必须是 use
for (const auto& op : operands) { for (const auto& op : operands) {
if (op->getKind() == MachineOperand::KIND_MEM) { if (op->getKind() == MachineOperand::KIND_MEM) {
unsigned reg_id = get_any_reg_id(op.get()); unsigned reg_id = get_any_reg_id(op.get());
@@ -920,7 +944,7 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
} }
} }
} }
// CALL 和 RET 的特殊处理逻辑,保持不变 // --- 特殊指令处理逻辑 ---
else if (opcode == RVOpcodes::CALL) { else if (opcode == RVOpcodes::CALL) {
// 返回值是Def // 返回值是Def
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) { if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) {
@@ -943,6 +967,16 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
use.insert(offset + static_cast<unsigned>(PhysicalReg::A0)); use.insert(offset + static_cast<unsigned>(PhysicalReg::A0));
use.insert(offset + static_cast<unsigned>(PhysicalReg::F10)); // F10 is fa0 use.insert(offset + static_cast<unsigned>(PhysicalReg::F10)); // F10 is fa0
} }
// [关键Bug修复] 添加对 PSEUDO_KEEPALIVE 的处理
else if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) {
// keepalive的所有操作数都是use以确保它们的生命周期延续到该点
for (const auto& op : operands) {
if (op->getKind() == MachineOperand::KIND_REG) {
unsigned reg_id = get_any_reg_id(op.get());
if (reg_id != (unsigned)-1) use.insert(reg_id);
}
}
}
} }
void RISCv64RegAlloc::addEdge(unsigned u, unsigned v) { void RISCv64RegAlloc::addEdge(unsigned u, unsigned v) {
@@ -1197,6 +1231,44 @@ bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u); return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u);
} }
// void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
// // 1. 从相应的工作列表中移除即将被合并的节点 v
// if (freezeWorklist.count(v)) {
// freezeWorklist.erase(v);
// } else {
// spillWorklist.erase(v);
// }
// // 2. 将 v 加入 coalescedNodes 集合,并设置其别名
// coalescedNodes.insert(v);
// alias[v] = u;
// // 3. 将 v 的传送指令列表合并到 u
// if (moveList.count(u) && moveList.count(v)) {
// moveList.at(u).insert(moveList.at(v).begin(), moveList.at(v).end());
// } else if (moveList.count(v)) {
// moveList[u] = moveList.at(v);
// }
// // [Bug修复] 移除了论文伪代码中不存在的 enableMoves({v}) 调用。
// // 4. [核心Bug修复] 遍历 v 的“当前有效”邻居 t (使用 adjacent(v) 而非 adjList.at(v))
// // 将它们与 u 连接,并更新它们的度数。
// for (unsigned t : adjacent(v)) {
// addEdge(t, u);
// decrementDegree(t);
// }
// // 5. 检查合并后的节点 u 的状态,如果其度数变高,可能需要将其移到 spillWorklist
// 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);
// }
// }
// }
void RISCv64RegAlloc::combine(unsigned u, unsigned v) { void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
freezeWorklist.erase(v); freezeWorklist.erase(v);
spillWorklist.erase(v); spillWorklist.erase(v);