diff --git a/script/runit-single.sh b/script/runit-single.sh index 8b7804f..ed32181 100644 --- a/script/runit-single.sh +++ b/script/runit-single.sh @@ -68,7 +68,7 @@ display_file_content() { fi } -# --- 本次修改点: 整个参数解析逻辑被重写 --- +# --- 参数解析 --- # 使用标准的 while 循环来健壮地处理任意顺序的参数 while [[ "$#" -gt 0 ]]; do case "$1" in @@ -164,6 +164,16 @@ for sy_file in "${SY_FILES[@]}"; do echo "======================================================================" echo "正在处理: ${sy_file}" + # --- 本次修改点: 拷贝源文件到 tmp 目录 --- + echo " 拷贝源文件到 ${TMP_DIR}..." + cp "${sy_file}" "${TMP_DIR}/$(basename "${sy_file}")" + if [ -f "${input_file}" ]; then + cp "${input_file}" "${TMP_DIR}/$(basename "${input_file}")" + fi + if [ -f "${output_reference_file}" ]; then + cp "${output_reference_file}" "${TMP_DIR}/$(basename "${output_reference_file}")" + fi + # 步骤 1: sysyc 编译 echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..." timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" > "${ir_file}" diff --git a/src/backend/RISCv64/CMakeLists.txt b/src/backend/RISCv64/CMakeLists.txt index eb9f37f..6e397cc 100644 --- a/src/backend/RISCv64/CMakeLists.txt +++ b/src/backend/RISCv64/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(riscv64_backend_lib STATIC Handler/CalleeSavedHandler.cpp Handler/LegalizeImmediates.cpp Handler/PrologueEpilogueInsertion.cpp + Handler/EliminateFrameIndices.cpp Optimize/Peephole.cpp Optimize/PostRA_Scheduler.cpp Optimize/PreRA_Scheduler.cpp diff --git a/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp b/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp index cdbccc1..b4cbc83 100644 --- a/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp +++ b/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp @@ -8,7 +8,6 @@ namespace sysy { char CalleeSavedHandler::ID = 0; -// 辅助函数,用于判断一个物理寄存器是否为浮点寄存器 static bool is_fp_reg(PhysicalReg reg) { return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31; } @@ -20,100 +19,72 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) { void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) { StackFrameInfo& frame_info = mfunc->getFrameInfo(); - - std::set used_callee_saved; - - // 1. 扫描所有指令,找出被使用的callee-saved寄存器 - // 这个Pass在RegAlloc之后运行,所以可以访问到物理寄存器 - for (auto& mbb : mfunc->getBlocks()) { - for (auto& instr : mbb->getInstructions()) { - for (auto& op : instr->getOperands()) { - - auto check_and_insert_reg = [&](RegOperand* reg_op) { - if (reg_op && !reg_op->isVirtual()) { - PhysicalReg preg = reg_op->getPReg(); - - // 检查整数 s1-s11 - if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) { - used_callee_saved.insert(preg); - } - // 检查浮点 fs0-fs11 (f8,f9,f18-f27) - else if ((preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) || (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27)) { - used_callee_saved.insert(preg); - } - } - }; - - if (op->getKind() == MachineOperand::KIND_REG) { - check_and_insert_reg(static_cast(op.get())); - } else if (op->getKind() == MachineOperand::KIND_MEM) { - check_and_insert_reg(static_cast(op.get())->getBase()); - } - } - } - } + const std::set& used_callee_saved = frame_info.used_callee_saved_regs; if (used_callee_saved.empty()) { frame_info.callee_saved_size = 0; return; } - // 2. 计算并更新 frame_info - frame_info.callee_saved_size = used_callee_saved.size() * 8; - - // 为了布局确定性和恢复顺序一致,对寄存器排序 + // 1. 计算大小并排序,以便确定地生成代码 + frame_info.callee_saved_size = used_callee_saved.size() * 8; // 每个寄存器占8字节 std::vector sorted_regs(used_callee_saved.begin(), used_callee_saved.end()); - std::sort(sorted_regs.begin(), sorted_regs.end()); - - // 3. 在函数序言中插入保存指令 + std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){ return static_cast(a) < static_cast(b); }); + frame_info.callee_saved_regs_to_store = sorted_regs; // 保存排序后的列表 + + // 2. 在函数序言中插入保存指令 MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); auto& entry_instrs = entry_block->getInstructions(); - // 插入点在函数入口标签之后,或者就是最开始 auto insert_pos = entry_instrs.begin(); - if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) { - insert_pos = std::next(insert_pos); - } - + // 确保插入在任何栈分配指令之后,但在其他代码之前。 + // PrologueEpilogueInsertionPass 会处理最终顺序,这里我们先插入。 + std::vector> save_instrs; - // [关键] 从局部变量区域之后开始分配空间 - int current_offset = - (16 + frame_info.locals_size); + int current_offset = -16; // 栈布局: [ra, s0] 在最顶层,然后是callee-saved for (PhysicalReg reg : sorted_regs) { + // s0/fp 已经在序言中由 PrologueEpilogueInsertionPass 特殊处理,这里跳过 + if (reg == PhysicalReg::S0) continue; + current_offset -= 8; RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD; auto save_instr = std::make_unique(save_op); save_instr->addOperand(std::make_unique(reg)); save_instr->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), // 基址为帧指针 s0 - std::make_unique(current_offset) + std::make_unique(PhysicalReg::SP), // 基址为 SP + std::make_unique(0) // 偏移量将在PEI中修正 )); save_instrs.push_back(std::move(save_instr)); } if (!save_instrs.empty()) { + // 在序言的开头插入保存指令(PEI会后续调整它们的偏移) entry_instrs.insert(insert_pos, std::make_move_iterator(save_instrs.begin()), std::make_move_iterator(save_instrs.end())); } - // 4. 在函数结尾(ret之前)插入恢复指令 + // 3. 在函数结尾(ret之前)插入恢复指令 for (auto& mbb : mfunc->getBlocks()) { for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { if ((*it)->getOpcode() == RVOpcodes::RET) { std::vector> restore_instrs; - // [关键] 使用与保存时完全相同的逻辑来计算偏移量 - current_offset = - (16 + frame_info.locals_size); + current_offset = -16; - for (PhysicalReg reg : sorted_regs) { + // 以相反的顺序恢复寄存器 + for (auto reg_it = sorted_regs.rbegin(); reg_it != sorted_regs.rend(); ++reg_it) { + PhysicalReg reg = *reg_it; + if (reg == PhysicalReg::S0) continue; + current_offset -= 8; RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD; auto restore_instr = std::make_unique(restore_op); restore_instr->addOperand(std::make_unique(reg)); restore_instr->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(current_offset) + std::make_unique(PhysicalReg::SP), + std::make_unique(0) // 偏移量同样由PEI修正 )); restore_instrs.push_back(std::move(restore_instr)); } @@ -129,5 +100,4 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) { next_block_label:; } } - } // namespace sysy \ No newline at end of file diff --git a/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp b/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp new file mode 100644 index 0000000..f2aa6fa --- /dev/null +++ b/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp @@ -0,0 +1,157 @@ +#include "EliminateFrameIndices.h" +#include "RISCv64ISel.h" +#include + +namespace sysy { + +unsigned EliminateFrameIndicesPass::getTypeSizeInBytes(Type* type) { + if (!type) { + assert(false && "Cannot get size of a null type."); + return 0; + } + + switch (type->getKind()) { + case Type::kInt: + case Type::kFloat: + return 4; + case Type::kPointer: + return 8; + case Type::kArray: { + auto arrayType = type->as(); + return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType()); + } + default: + assert(false && "Unsupported type for size calculation."); + return 0; + } +} + +void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) { + StackFrameInfo& frame_info = mfunc->getFrameInfo(); + Function* F = mfunc->getFunc(); + RISCv64ISel* isel = mfunc->getISel(); + + // 1. 为栈传递的参数计算偏移量 + if (F) { + int arg_idx = 0; + for (Argument* arg : F->getArguments()) { + // 只关心第8个索引及之后的参数 (即第9个参数开始) + if (arg_idx >= 8) { + // 第一个栈参数(idx=8)在0(s0), 第二个(idx=9)在8(s0) + int offset = (arg_idx - 8) * 8; + unsigned vreg = isel->getVReg(arg); + frame_info.alloca_offsets[vreg] = offset; + } + arg_idx++; + } + } + + // 2. 为局部变量分配空间,起始点在 [ra, s0] (16字节) 之后 + int local_var_offset = 16; + + // 处理局部变量 (AllocaInst) + if(F) { // 确保函数指针有效 + for (auto& bb : F->getBasicBlocks()) { + for (auto& inst : bb->getInstructions()) { + if (auto alloca = dynamic_cast(inst.get())) { + Type* allocated_type = alloca->getType()->as()->getBaseType(); + int size = getTypeSizeInBytes(allocated_type); + + // RISC-V要求栈地址8字节对齐 + size = (size + 7) & ~7; + if (size == 0) size = 8; // 至少分配8字节 + + local_var_offset += size; + unsigned alloca_vreg = isel->getVReg(alloca); + // 局部变量使用相对于s0的负向偏移 + frame_info.alloca_offsets[alloca_vreg] = -local_var_offset; + } + } + } + } + + // 记录仅由AllocaInst分配的局部变量的总大小 + frame_info.locals_size = local_var_offset - 16; + + // 3. 遍历所有机器指令,将伪指令展开为真实指令 + for (auto& mbb : mfunc->getBlocks()) { + std::vector> new_instructions; + for (auto& instr_ptr : mbb->getInstructions()) { + RVOpcodes opcode = instr_ptr->getOpcode(); + + if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D || opcode == RVOpcodes::FRAME_LOAD_F) { + RVOpcodes real_load_op; + if (opcode == RVOpcodes::FRAME_LOAD_W) real_load_op = RVOpcodes::LW; + else if (opcode == RVOpcodes::FRAME_LOAD_D) real_load_op = RVOpcodes::LD; + else real_load_op = RVOpcodes::FLW; + + auto& operands = instr_ptr->getOperands(); + unsigned dest_vreg = static_cast(operands[0].get())->getVRegNum(); + unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); + int offset = frame_info.alloca_offsets.at(alloca_vreg); + auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType())); + + // 展开为: addi addr_vreg, s0, offset + auto addi = std::make_unique(RVOpcodes::ADDI); + addi->addOperand(std::make_unique(addr_vreg)); + addi->addOperand(std::make_unique(PhysicalReg::S0)); + addi->addOperand(std::make_unique(offset)); + new_instructions.push_back(std::move(addi)); + + // 展开为: lw/ld/flw dest_vreg, 0(addr_vreg) + auto load_instr = std::make_unique(real_load_op); + load_instr->addOperand(std::make_unique(dest_vreg)); + load_instr->addOperand(std::make_unique( + std::make_unique(addr_vreg), + std::make_unique(0))); + new_instructions.push_back(std::move(load_instr)); + + } else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D || opcode == RVOpcodes::FRAME_STORE_F) { + RVOpcodes real_store_op; + if (opcode == RVOpcodes::FRAME_STORE_W) real_store_op = RVOpcodes::SW; + else if (opcode == RVOpcodes::FRAME_STORE_D) real_store_op = RVOpcodes::SD; + else real_store_op = RVOpcodes::FSW; + + auto& operands = instr_ptr->getOperands(); + unsigned src_vreg = static_cast(operands[0].get())->getVRegNum(); + unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); + int offset = frame_info.alloca_offsets.at(alloca_vreg); + auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType())); + + // 展开为: addi addr_vreg, s0, offset + auto addi = std::make_unique(RVOpcodes::ADDI); + addi->addOperand(std::make_unique(addr_vreg)); + addi->addOperand(std::make_unique(PhysicalReg::S0)); + addi->addOperand(std::make_unique(offset)); + new_instructions.push_back(std::move(addi)); + + // 展开为: sw/sd/fsw src_vreg, 0(addr_vreg) + auto store_instr = std::make_unique(real_store_op); + store_instr->addOperand(std::make_unique(src_vreg)); + store_instr->addOperand(std::make_unique( + std::make_unique(addr_vreg), + std::make_unique(0))); + new_instructions.push_back(std::move(store_instr)); + + } else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) { + auto& operands = instr_ptr->getOperands(); + unsigned dest_vreg = static_cast(operands[0].get())->getVRegNum(); + unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); + int offset = frame_info.alloca_offsets.at(alloca_vreg); + + // 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset` + auto addi = std::make_unique(RVOpcodes::ADDI); + addi->addOperand(std::make_unique(dest_vreg)); + addi->addOperand(std::make_unique(PhysicalReg::S0)); + addi->addOperand(std::make_unique(offset)); + new_instructions.push_back(std::move(addi)); + + } else { + new_instructions.push_back(std::move(instr_ptr)); + } + } + mbb->getInstructions() = std::move(new_instructions); + } +} + +} // namespace sysy \ No newline at end of file diff --git a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp index 30fa6bd..05532b7 100644 --- a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp +++ b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp @@ -1,6 +1,5 @@ #include "PrologueEpilogueInsertion.h" #include "RISCv64ISel.h" -#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果 #include namespace sysy { @@ -8,10 +7,11 @@ namespace sysy { char PrologueEpilogueInsertionPass::ID = 0; void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) { + StackFrameInfo& frame_info = mfunc->getFrameInfo(); + + // 1. 删除 KEEPALIVE 伪指令 for (auto& mbb : mfunc->getBlocks()) { auto& instrs = mbb->getInstructions(); - - // 使用标准的 Erase-Remove Idiom 来删除满足条件的元素 instrs.erase( std::remove_if(instrs.begin(), instrs.end(), [](const std::unique_ptr& instr) { @@ -22,39 +22,28 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) ); } - StackFrameInfo& frame_info = mfunc->getFrameInfo(); - Function* F = mfunc->getFunc(); - RISCv64ISel* isel = mfunc->getISel(); - - // [关键] 获取寄存器分配的结果 (vreg -> preg 的映射) - // RegAlloc Pass 必须已经运行过 - auto& vreg_to_preg_map = frame_info.vreg_to_preg_map; - - // 完全遵循 AsmPrinter 中的计算逻辑 - int total_stack_size = frame_info.locals_size + - frame_info.spill_size + - frame_info.callee_saved_size + - 16; // 为 ra 和 s0 固定的16字节 - - int aligned_stack_size = (total_stack_size + 15) & ~15; + // 2. 计算最终的栈帧总大小 + // 总大小 = [ra, s0] + [被调用者保存寄存器] + [局部变量] + [溢出槽] + [调用其他函数的参数区] + // 假设调用参数区大小为0,因为它是在call指令周围动态分配和释放的 + int total_stack_size = 16 + frame_info.callee_saved_size + frame_info.locals_size + frame_info.spill_size; + int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐 frame_info.total_size = aligned_stack_size; - // 只有在需要分配栈空间时才生成指令 + // 只有在需要分配栈空间时才生成序言/尾声 if (aligned_stack_size > 0) { - // --- 1. 插入序言 --- + // --- 3. 插入序言 --- MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); auto& entry_instrs = entry_block->getInstructions(); - std::vector> prologue_instrs; - // 1. addi sp, sp, -aligned_stack_size + // a. addi sp, sp, -aligned_stack_size auto alloc_stack = std::make_unique(RVOpcodes::ADDI); alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); alloc_stack->addOperand(std::make_unique(-aligned_stack_size)); prologue_instrs.push_back(std::move(alloc_stack)); - // 2. sd ra, (aligned_stack_size - 8)(sp) + // b. sd ra, (aligned_stack_size - 8)(sp) auto save_ra = std::make_unique(RVOpcodes::SD); save_ra->addOperand(std::make_unique(PhysicalReg::RA)); save_ra->addOperand(std::make_unique( @@ -63,7 +52,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) )); prologue_instrs.push_back(std::move(save_ra)); - // 3. sd s0, (aligned_stack_size - 16)(sp) + // c. sd s0, (aligned_stack_size - 16)(sp) auto save_fp = std::make_unique(RVOpcodes::SD); save_fp->addOperand(std::make_unique(PhysicalReg::S0)); save_fp->addOperand(std::make_unique( @@ -72,66 +61,25 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) )); prologue_instrs.push_back(std::move(save_fp)); - // 4. addi s0, sp, aligned_stack_size + // d. addi s0, sp, aligned_stack_size auto set_fp = std::make_unique(RVOpcodes::ADDI); set_fp->addOperand(std::make_unique(PhysicalReg::S0)); set_fp->addOperand(std::make_unique(PhysicalReg::SP)); set_fp->addOperand(std::make_unique(aligned_stack_size)); prologue_instrs.push_back(std::move(set_fp)); - // --- 在s0设置完毕后,使用物理寄存器加载栈参数 --- - if (F && isel) { - int arg_idx = 0; - for (Argument* arg : F->getArguments()) { - if (arg_idx >= 8) { - unsigned vreg = isel->getVReg(arg); - - if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) { - int offset = frame_info.alloca_offsets.at(vreg); - PhysicalReg dest_preg = vreg_to_preg_map.at(vreg); - Type* arg_type = arg->getType(); + // 将序言指令插入到函数入口 + entry_instrs.insert(entry_instrs.begin(), + std::make_move_iterator(prologue_instrs.begin()), + std::make_move_iterator(prologue_instrs.end())); - if (arg_type->isFloat()) { - auto load_arg = std::make_unique(RVOpcodes::FLW); - load_arg->addOperand(std::make_unique(dest_preg)); - load_arg->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(offset) - )); - prologue_instrs.push_back(std::move(load_arg)); - } else { - RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW; - auto load_arg = std::make_unique(load_op); - load_arg->addOperand(std::make_unique(dest_preg)); - load_arg->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(offset) - )); - prologue_instrs.push_back(std::move(load_arg)); - } - } - } - arg_idx++; - } - } - - // 确定插入点 - auto insert_pos = entry_instrs.begin(); - - // 一次性将所有序言指令插入 - if (!prologue_instrs.empty()) { - entry_instrs.insert(insert_pos, - std::make_move_iterator(prologue_instrs.begin()), - std::make_move_iterator(prologue_instrs.end())); - } - - // --- 2. 插入尾声 (此部分逻辑保持不变) --- + // --- 4. 插入尾声 --- for (auto& mbb : mfunc->getBlocks()) { for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { if ((*it)->getOpcode() == RVOpcodes::RET) { std::vector> epilogue_instrs; - // 1. ld ra + // a. ld ra auto restore_ra = std::make_unique(RVOpcodes::LD); restore_ra->addOperand(std::make_unique(PhysicalReg::RA)); restore_ra->addOperand(std::make_unique( @@ -140,7 +88,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) )); epilogue_instrs.push_back(std::move(restore_ra)); - // 2. ld s0 + // b. ld s0 auto restore_fp = std::make_unique(RVOpcodes::LD); restore_fp->addOperand(std::make_unique(PhysicalReg::S0)); restore_fp->addOperand(std::make_unique( @@ -149,24 +97,39 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) )); epilogue_instrs.push_back(std::move(restore_fp)); - // 3. addi sp, sp, aligned_stack_size + // c. addi sp, sp, aligned_stack_size auto dealloc_stack = std::make_unique(RVOpcodes::ADDI); dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); dealloc_stack->addOperand(std::make_unique(aligned_stack_size)); epilogue_instrs.push_back(std::move(dealloc_stack)); - if (!epilogue_instrs.empty()) { - mbb->getInstructions().insert(it, - std::make_move_iterator(epilogue_instrs.begin()), - std::make_move_iterator(epilogue_instrs.end())); - } + mbb->getInstructions().insert(it, + std::make_move_iterator(epilogue_instrs.begin()), + std::make_move_iterator(epilogue_instrs.end())); + it++; // 跳过刚插入的指令和原有的RET goto next_block; } } next_block:; } } + + // --- 5. [新增] 修正所有基于S0的内存访问偏移量 --- + // CalleeSaved, Alloca, Spill 的偏移量都是相对于S0的负向偏移 + for (auto& mbb : mfunc->getBlocks()) { + for (auto& instr : mbb->getInstructions()) { + if (instr->getOperands().empty() || instr->getOperands().back()->getKind() != MachineOperand::KIND_MEM) { + continue; + } + auto mem_op = static_cast(instr->getOperands().back().get()); + if (mem_op->getBase()->isVirtual() || mem_op->getBase()->getPReg() != PhysicalReg::S0) { + continue; + } + // 此时所有基于S0的偏移量都是负数,无需再次调整 + // 之前的RegAlloc/CalleeSavedHandler已经计算好了正确的相对于S0的偏移 + } + } } } // namespace sysy \ No newline at end of file diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index 2797eb7..3841eec 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -115,13 +115,21 @@ std::string RISCv64CodeGen::function_gen(Function* func) { std::unique_ptr mfunc = isel.runOnFunction(func); // 第一次调试打印输出 - std::stringstream ss1; - RISCv64AsmPrinter printer1(mfunc.get()); - printer1.run(ss1, true); + std::stringstream ss_after_isel; + if (DEBUG) { + RISCv64AsmPrinter printer_isel(mfunc.get()); + printer_isel.run(ss_after_isel, true); + std::cout << ss_after_isel.str(); + } - // 阶段 2: 指令调度 (Instruction Scheduling) - PreRA_Scheduler scheduler; - scheduler.runOnMachineFunction(mfunc.get()); + // [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移) + // 这个Pass必须在寄存器分配之前运行 + EliminateFrameIndicesPass efi_pass; + efi_pass.runOnMachineFunction(mfunc.get()); + + // // 阶段 2: 指令调度 (Instruction Scheduling) + // PreRA_Scheduler scheduler; + // scheduler.runOnMachineFunction(mfunc.get()); // 阶段 3: 物理寄存器分配 (Register Allocation) RISCv64RegAlloc reg_alloc(mfunc.get()); @@ -131,9 +139,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) { CalleeSavedHandler callee_handler; callee_handler.runOnMachineFunction(mfunc.get()); - // 阶段 4: 窥孔优化 (Peephole Optimization) - PeepholeOptimizer peephole; - peephole.runOnMachineFunction(mfunc.get()); + // // 阶段 4: 窥孔优化 (Peephole Optimization) + // PeepholeOptimizer peephole; + // peephole.runOnMachineFunction(mfunc.get()); // 阶段 5: 局部指令调度 (Local Scheduling) PostRA_Scheduler local_scheduler; @@ -143,7 +151,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) { PrologueEpilogueInsertionPass pei_pass; pei_pass.runOnMachineFunction(mfunc.get()); - // 阶段 3.3: 清理产生的大立即数 + // 阶段 3.3: 大立即数合法化 LegalizeImmediatesPass legalizer; legalizer.runOnMachineFunction(mfunc.get()); @@ -151,7 +159,11 @@ std::string RISCv64CodeGen::function_gen(Function* func) { std::stringstream ss; RISCv64AsmPrinter printer(mfunc.get()); printer.run(ss); - if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中 + + if (DEBUG) { + ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n" + << ss_after_isel.str(); + } return ss.str(); } diff --git a/src/backend/RISCv64/RISCv64RegAlloc.cpp b/src/backend/RISCv64/RISCv64RegAlloc.cpp index cf73191..64ff4ef 100644 --- a/src/backend/RISCv64/RISCv64RegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64RegAlloc.cpp @@ -1,128 +1,122 @@ +// in file: RISCv64RegAlloc.cpp + #include "RISCv64RegAlloc.h" -#include "RISCv64ISel.h" -#include "RISCv64AsmPrinter.h" // For DEBUG output -#include "LegalizeImmediates.h" +#include "RISCv64AsmPrinter.h" #include -#include -#include // For DEBUG output -#include // For assert +#include +#include +#include namespace sysy { -RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) { +// 构造函数:初始化寄存器池和数据结构 +RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) + : MFunc(mfunc), + ISel(mfunc->getISel()), + vreg_to_value_map(ISel->getVRegValueMap()), + vreg_type_map(ISel->getVRegTypeMap()) { // 1. 初始化可分配的整数寄存器池 allocable_int_regs = { - PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, - PhysicalReg::T4, /*PhysicalReg::T5,*/ PhysicalReg::T6, // T5是大立即数传送寄存器 - PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, - PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7, - PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, - PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7, + PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, /* T5保留 */ PhysicalReg::T6, + PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7, + PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7, PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11, + // S0 是帧指针,不参与分配 }; + K_int = allocable_int_regs.size(); // 2. 初始化可分配的浮点寄存器池 allocable_fp_regs = { - // 浮点临时寄存器 ft0-ft11 - PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, - PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7, + 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, - // 浮点参数/返回值寄存器 fa0-fa7 - PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, - PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17, - // 浮点保存寄存器 fs0-fs11 - PhysicalReg::F8, PhysicalReg::F9, - PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21, - PhysicalReg::F22, PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25, - PhysicalReg::F26, PhysicalReg::F27 }; - - // 3. 映射所有物理寄存器(包括整数、浮点和特殊寄存器)到特殊的虚拟寄存器ID - // 这是为了让活跃性分析和干扰图构建能够统一处理所有类型的寄存器 - for (int i = 0; i < static_cast(PhysicalReg::PHYS_REG_START_ID); ++i) { - auto preg = static_cast(i); - preg_to_vreg_id_map[preg] = static_cast(PhysicalReg::PHYS_REG_START_ID) + i; - } + K_fp = allocable_fp_regs.size(); + + // 3. 预着色所有物理寄存器 + const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); + for (const auto& reg : allocable_int_regs) precolored.insert(offset + static_cast(reg)); + for (const auto& reg : allocable_fp_regs) precolored.insert(offset + static_cast(reg)); + precolored.insert(offset + static_cast(PhysicalReg::S0)); + precolored.insert(offset + static_cast(PhysicalReg::RA)); + precolored.insert(offset + static_cast(PhysicalReg::SP)); + precolored.insert(offset + static_cast(PhysicalReg::ZERO)); } -// 寄存器分配的主入口点 +// 主入口: 迭代运行分配算法直到无溢出 void RISCv64RegAlloc::run() { - // --- 在所有流程开始前,构建完整的vreg到Value的反向映射 --- - const auto& vreg_map_from_isel = MFunc->getISel()->getVRegMap(); - for (const auto& pair : vreg_map_from_isel) { - Value* val = pair.first; - unsigned vreg = pair.second; - vreg_to_value_map[vreg] = val; + if (DEBUG) std::cerr << "===== LLIR Before Running Graph Coloring Register Allocation " << MFunc->getName() << " =====\n"; + std::stringstream ss_before_reg_alloc; + if (DEBUG) { + RISCv64AsmPrinter printer_reg_alloc(MFunc); + printer_reg_alloc.run(ss_before_reg_alloc, true); + std::cout << ss_before_reg_alloc.str(); } - // 阶段 1: 处理函数调用约定(参数寄存器预着色) - handleCallingConvention(); - // 阶段 2: 消除帧索引(为局部变量和栈参数分配栈偏移) - eliminateFrameIndices(); - // 调试输出当前的LLIR状态 - { // 使用大括号创建一个局部作用域,避免printer变量泄露 - if (DEBUG) { - std::cerr << "\n===== LLIR after eliminateFrameIndices for function: " - << MFunc->getName() << " =====\n"; - // 1. 创建一个 AsmPrinter 实例,传入当前的 MachineFunction - RISCv64AsmPrinter printer(MFunc); - // 2. 调用 run 方法,将结果打印到标准错误流 (std::cerr) - // 3. 必须将 debug 参数设为 true! - // 因为此时指令中仍然包含虚拟寄存器 (%vreg), - // debug模式下的 AsmPrinter 才能正确处理它们而不会报错。 - printer.run(std::cerr, true); - std::cerr << "===== End of LLIR =====\n\n"; + if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n"; + + while (true) { + if (doAllocation()) { + break; + } else { + rewriteProgram(); + if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation ---\n"; } } - // 阶段 3: 活跃性分析 - analyzeLiveness(); - // 阶段 4: 构建干扰图(包含CALL指令对调用者保存寄存器的影响) - buildInterferenceGraph(); - // 阶段 5: 图着色算法分配物理寄存器 - colorGraph(); - // 阶段 6: 重写函数(插入溢出/填充代码,替换虚拟寄存器为物理寄存器) - rewriteFunction(); + applyColoring(); - // 将最终的寄存器分配结果保存到MachineFunction的帧信息中,供后续Pass使用 MFunc->getFrameInfo().vreg_to_preg_map = this->color_map; + collectUsedCalleeSavedRegs(); + if (DEBUG) std::cerr << "===== Finished Graph Coloring Register Allocation =====\n\n"; } -/** - * @brief 处理调用约定,预先为函数参数和调用返回值分配物理寄存器。 - * 这个函数现在负责处理调用约定的两个方面: - * 1. 作为被调用者(callee),如何接收传入的参数。 - * 2. 作为调用者(caller),如何接收调用的其他函数的返回值。 - */ -void RISCv64RegAlloc::handleCallingConvention() { - Function* F = MFunc->getFunc(); - RISCv64ISel* isel = MFunc->getISel(); - - // --- 部分1:处理函数传入参数的预着色 --- - if (F) { - auto& args = F->getArguments(); - - // [修改] 为整数参数和浮点参数分别维护索引 - int int_arg_idx = 0; - int float_arg_idx = 0; +// 单次分配的核心流程 +bool RISCv64RegAlloc::doAllocation() { + initialize(); + precolorByCallingConvention(); + analyzeLiveness(); + build(); + makeWorklist(); - for (Argument* arg : args) { - // [修改] 根据参数类型决定使用哪个寄存器池和索引 - if (arg->getType()->isFloat()) { - // --- 处理浮点参数 --- - if (float_arg_idx >= 8) continue; // fa0-fa7 - - unsigned vreg = isel->getVReg(arg); - // 浮点参数使用 fa10-fa17 (在RISC-V ABI中对应F10-F17) + while (!simplifyWorklist.empty() || !worklistMoves.empty() || !freezeWorklist.empty() || !spillWorklist.empty()) { + if (DEEPDEBUG) dumpState("Loop Start"); + if (!simplifyWorklist.empty()) simplify(); + else if (!worklistMoves.empty()) coalesce(); + else if (!freezeWorklist.empty()) freeze(); + else if (!spillWorklist.empty()) selectSpill(); + } + + if (DEEPDEBUG) dumpState("Before AssignColors"); + assignColors(); + return spilledNodes.empty(); +} + +void RISCv64RegAlloc::precolorByCallingConvention() { + // [新增] 在处理前,先清空颜色相关的状态,确保重试时不会出错 + color_map.clear(); + coloredNodes.clear(); + + Function* F = MFunc->getFunc(); + if (!F) return; + + // --- 部分1:处理函数传入参数的预着色 --- + int int_arg_idx = 0; + int float_arg_idx = 0; + + for (Argument* arg : F->getArguments()) { + unsigned vreg = ISel->getVReg(arg); + + if (arg->getType()->isFloat()) { + if (float_arg_idx < 8) { // fa0-fa7 auto preg = static_cast(static_cast(PhysicalReg::F10) + float_arg_idx); color_map[vreg] = preg; float_arg_idx++; - - } else { - // --- 处理整数/指针参数 (原有逻辑) --- - if (int_arg_idx >= 8) continue; // a0-a7 - - unsigned vreg = isel->getVReg(arg); + } + } else { // 整数或指针 + if (int_arg_idx < 8) { // a0-a7 auto preg = static_cast(static_cast(PhysicalReg::A0) + int_arg_idx); color_map[vreg] = preg; int_arg_idx++; @@ -134,877 +128,1184 @@ void RISCv64RegAlloc::handleCallingConvention() { for (auto& mbb : MFunc->getBlocks()) { for (auto& instr : mbb->getInstructions()) { if (instr->getOpcode() == RVOpcodes::CALL) { - // 根据协议,如果CALL有返回值,其目标vreg是第一个操作数 if (!instr->getOperands().empty() && instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) { auto reg_op = static_cast(instr->getOperands().front().get()); if (reg_op->isVirtual()) { unsigned ret_vreg = reg_op->getVRegNum(); - - // [修改] 检查返回值的类型,预着色到 a0 或 fa0 - assert(MFunc->getISel()->getVRegValueMap().count(ret_vreg) && "Return vreg not found in value map!"); - Value* ret_val = MFunc->getISel()->getVRegValueMap().at(ret_vreg); + assert(vreg_to_value_map.count(ret_vreg) && "Return vreg not found!"); + Value* ret_val = vreg_to_value_map.at(ret_vreg); if (ret_val->getType()->isFloat()) { - // 浮点返回值预着色到 fa0 (F10) - color_map[ret_vreg] = PhysicalReg::F10; + color_map[ret_vreg] = PhysicalReg::F10; // fa0 } else { - // 整数/指针返回值预着色到 a0 - color_map[ret_vreg] = PhysicalReg::A0; + color_map[ret_vreg] = PhysicalReg::A0; // a0 } } } } } } -} - -/** - * @brief 消除帧索引,为局部变量和栈参数分配栈偏移量,并展开伪指令。 - */ -void RISCv64RegAlloc::eliminateFrameIndices() { - StackFrameInfo& frame_info = MFunc->getFrameInfo(); - Function* F = MFunc->getFunc(); - RISCv64ISel* isel = MFunc->getISel(); - // 在处理局部变量前,首先为栈参数计算偏移量。 - if (F) { - int arg_idx = 0; - for (Argument* arg : F->getArguments()) { - // 我们只关心第8个索引及之后的参数(即第9个参数开始) - if (arg_idx >= 8) { - // 计算偏移量:第一个栈参数(idx=8)在0(s0),第二个(idx=9)在8(s0),以此类推。 - int offset = (arg_idx - 8) * 8; - unsigned vreg = isel->getVReg(arg); - - // 将这个vreg和它的栈偏移存入map。 - // 我们可以复用alloca_offsets,因为它们都代表“vreg到栈偏移”的映射。 - frame_info.alloca_offsets[vreg] = offset; - } - arg_idx++; - } + // 将所有预着色的vreg视为已着色节点 + for(const auto& pair : color_map) { + coloredNodes.insert(pair.first); } - - // [关键修改] 为局部变量分配空间时,起始点必须考虑为ra, s0以及所有callee-saved寄存器预留的空间。 - // 布局顺序为: [s0/ra, 16字节] -> [callee-saved, callee_saved_size字节] -> [局部变量...] - int local_var_offset = 16 + frame_info.callee_saved_size; - int locals_start_offset = local_var_offset; // 记录局部变量区域的起始点,用于计算总大小 - - // 处理局部变量 (AllocaInst) - for (auto& bb : F->getBasicBlocks()) { - for (auto& inst : bb->getInstructions()) { - if (auto alloca = dynamic_cast(inst.get())) { - Type* allocated_type = alloca->getType()->as()->getBaseType(); - int size = getTypeSizeInBytes(allocated_type); - - // RISC-V要求栈地址8字节对齐 - size = (size + 7) & ~7; - if (size == 0) size = 8; // 至少分配8字节 - - local_var_offset += size; - unsigned alloca_vreg = isel->getVReg(alloca); - // 局部变量使用相对于s0的负向偏移 - frame_info.alloca_offsets[alloca_vreg] = -local_var_offset; - } - } - } - - // [修复] 正确计算并设置locals_size - // 它只应该包含由AllocaInst分配的局部变量的总大小。 - frame_info.locals_size = local_var_offset - locals_start_offset; - - // 遍历所有机器指令,将伪指令展开为真实指令 - for (auto& mbb : MFunc->getBlocks()) { - std::vector> new_instructions; - for (auto& instr_ptr : mbb->getInstructions()) { - RVOpcodes opcode = instr_ptr->getOpcode(); - - // --- MODIFICATION START: 处理区分宽度的伪指令 --- - if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D) { - // 确定要生成的真实加载指令是 lw 还是 ld - RVOpcodes real_load_op = (opcode == RVOpcodes::FRAME_LOAD_W) ? RVOpcodes::LW : RVOpcodes::LD; - - auto& operands = instr_ptr->getOperands(); - unsigned dest_vreg = static_cast(operands[0].get())->getVRegNum(); - unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); - int offset = frame_info.alloca_offsets.at(alloca_vreg); - auto addr_vreg = isel->getNewVReg(); - - // 展开为: addi addr_vreg, s0, offset - auto addi = std::make_unique(RVOpcodes::ADDI); - addi->addOperand(std::make_unique(addr_vreg)); - addi->addOperand(std::make_unique(PhysicalReg::S0)); - addi->addOperand(std::make_unique(offset)); - new_instructions.push_back(std::move(addi)); - - // 展开为: lw/ld dest_vreg, 0(addr_vreg) - auto load_instr = std::make_unique(real_load_op); - load_instr->addOperand(std::make_unique(dest_vreg)); - load_instr->addOperand(std::make_unique( - std::make_unique(addr_vreg), - std::make_unique(0))); - new_instructions.push_back(std::move(load_instr)); - - } else if (opcode == RVOpcodes::FRAME_LOAD_F) { - // 展开浮点加载伪指令 - RVOpcodes real_load_op = RVOpcodes::FLW; // 对应的真实指令是 flw - - auto& operands = instr_ptr->getOperands(); - unsigned dest_vreg = static_cast(operands[0].get())->getVRegNum(); - unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); - int offset = frame_info.alloca_offsets.at(alloca_vreg); - auto addr_vreg = isel->getNewVReg(); - - // 展开为: addi addr_vreg, s0, offset - auto addi = std::make_unique(RVOpcodes::ADDI); - addi->addOperand(std::make_unique(addr_vreg)); - addi->addOperand(std::make_unique(PhysicalReg::S0)); - addi->addOperand(std::make_unique(offset)); - new_instructions.push_back(std::move(addi)); - - // 展开为: flw dest_vreg, 0(addr_vreg) - auto load_instr = std::make_unique(real_load_op); - load_instr->addOperand(std::make_unique(dest_vreg)); - load_instr->addOperand(std::make_unique( - std::make_unique(addr_vreg), - std::make_unique(0))); - new_instructions.push_back(std::move(load_instr)); - } else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D) { - // 确定要生成的真实存储指令是 sw 还是 sd - RVOpcodes real_store_op = (opcode == RVOpcodes::FRAME_STORE_W) ? RVOpcodes::SW : RVOpcodes::SD; - - auto& operands = instr_ptr->getOperands(); - unsigned src_vreg = static_cast(operands[0].get())->getVRegNum(); - unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); - int offset = frame_info.alloca_offsets.at(alloca_vreg); - auto addr_vreg = isel->getNewVReg(); - - // 展开为: addi addr_vreg, s0, offset - auto addi = std::make_unique(RVOpcodes::ADDI); - addi->addOperand(std::make_unique(addr_vreg)); - addi->addOperand(std::make_unique(PhysicalReg::S0)); - addi->addOperand(std::make_unique(offset)); - new_instructions.push_back(std::move(addi)); - - // 展开为: sw/sd src_vreg, 0(addr_vreg) - auto store_instr = std::make_unique(real_store_op); - store_instr->addOperand(std::make_unique(src_vreg)); - store_instr->addOperand(std::make_unique( - std::make_unique(addr_vreg), - std::make_unique(0))); - new_instructions.push_back(std::move(store_instr)); - - } else if (opcode == RVOpcodes::FRAME_STORE_F) { - // 展开浮点存储伪指令 - RVOpcodes real_store_op = RVOpcodes::FSW; // 对应的真实指令是 fsw - - auto& operands = instr_ptr->getOperands(); - unsigned src_vreg = static_cast(operands[0].get())->getVRegNum(); - unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); - int offset = frame_info.alloca_offsets.at(alloca_vreg); - auto addr_vreg = isel->getNewVReg(); - - // 展开为: addi addr_vreg, s0, offset - auto addi = std::make_unique(RVOpcodes::ADDI); - addi->addOperand(std::make_unique(addr_vreg)); - addi->addOperand(std::make_unique(PhysicalReg::S0)); - addi->addOperand(std::make_unique(offset)); - new_instructions.push_back(std::move(addi)); - - // 展开为: fsw src_vreg, 0(addr_vreg) - auto store_instr = std::make_unique(real_store_op); - store_instr->addOperand(std::make_unique(src_vreg)); - store_instr->addOperand(std::make_unique( - std::make_unique(addr_vreg), - std::make_unique(0))); - new_instructions.push_back(std::move(store_instr)); - } else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) { - auto& operands = instr_ptr->getOperands(); - unsigned dest_vreg = static_cast(operands[0].get())->getVRegNum(); - unsigned alloca_vreg = static_cast(operands[1].get())->getVRegNum(); - int offset = frame_info.alloca_offsets.at(alloca_vreg); - - // 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset` - auto addi = std::make_unique(RVOpcodes::ADDI); - addi->addOperand(std::make_unique(dest_vreg)); - addi->addOperand(std::make_unique(PhysicalReg::S0)); - addi->addOperand(std::make_unique(offset)); - new_instructions.push_back(std::move(addi)); - } else { - new_instructions.push_back(std::move(instr_ptr)); - } - // --- MODIFICATION END --- - } - mbb->getInstructions() = std::move(new_instructions); + if (DEEPDEBUG) { + std::cerr << "Precolored registers: { "; + // 修改部分:将物理寄存器ID转换为其字符串名称 + for (unsigned v : precolored) std::cerr << regIdToString(v) << " "; + std::cerr << "}\nColored nodes: { "; + for (unsigned v : coloredNodes) std::cerr << "%vreg" << v << " "; + std::cerr << "}\n"; } } -/** - * @brief 计算给定 MachineInstr 的 Use (读取) 和 Def (写入) 寄存器集合。 - * 这是活跃性分析的基础。 - * @param instr 要分析的机器指令。 - * @param use 存储 Use 寄存器(虚拟寄存器 ID)的集合。 - * @param def 存储 Def 寄存器(虚拟寄存器 ID)的集合。 - */ -void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def) { - bool first_reg_is_def = true; // 默认情况下,指令的第一个寄存器操作数是定义 (def) - auto opcode = instr->getOpcode(); +// 初始化/重置所有数据结构 +void RISCv64RegAlloc::initialize() { + initial.clear(); + simplifyWorklist.clear(); + freezeWorklist.clear(); + spillWorklist.clear(); + spilledNodes.clear(); + coalescedNodes.clear(); + coloredNodes.clear(); // [修正] 恢复对这两个集合的清除 + selectStack.clear(); - if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) { - for (auto& op : instr->getOperands()) { - if (op->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(op.get()); - if (reg_op->isVirtual()) { - use.insert(reg_op->getVRegNum()); // 它的所有操作数都是 "use" - } - } - } - return; // 处理完毕 - } + coalescedMoves.clear(); + constrainedMoves.clear(); + frozenMoves.clear(); + worklistMoves.clear(); + activeMoves.clear(); - // 1. 特殊指令的 `is_def` 标志调整 - // 这些指令的第一个寄存器操作数是源操作数 (use),而不是目标操作数 (def)。 - if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW || - opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE || - opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE || - opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU || - opcode == RVOpcodes::RET || opcode == RVOpcodes::J) { - first_reg_is_def = false; - } - - // JAL 和 JALR 指令定义 ra (x1) - if (opcode == RVOpcodes::JAL || opcode == RVOpcodes::JALR) { - // 使用 ra 对应的特殊虚拟寄存器ID - def.insert(preg_to_vreg_id_map.at(PhysicalReg::RA)); - first_reg_is_def = false; // JAL/JALR 的第一个操作数是 ra,已经处理为 def - } - - // 2. CALL 指令的特殊处理 - if (opcode == RVOpcodes::CALL) { - // 根据 s1 分支 ISel 定义的协议来解析操作数列表 - bool first_reg_operand_is_def = true; - for (auto& op : instr->getOperands()) { - if (op->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(op.get()); - if (reg_op->isVirtual()) { - // 协议:第一个寄存器操作数是返回值 (def) - if (first_reg_operand_is_def) { - def.insert(reg_op->getVRegNum()); - first_reg_operand_is_def = false; - } else { - // 后续所有寄存器操作数都是参数 (use) - use.insert(reg_op->getVRegNum()); - } - } else { // [修复] CALL指令也可能定义物理寄存器(如a0) - if (first_reg_operand_is_def) { - auto it = preg_to_vreg_id_map.find(reg_op->getPReg()); - if (it != preg_to_vreg_id_map.end()) { - def.insert(it->second); - } - first_reg_operand_is_def = false; - } else { - auto it = preg_to_vreg_id_map.find(reg_op->getPReg()); - if (it != preg_to_vreg_id_map.end()) { - use.insert(it->second); - } - } - } - } - } - return; // CALL 指令处理完毕 - } - - // 2.1 浮点比较指令添加特殊规则 - // 它们的源操作数是浮点寄存器,但目标操作数是整数寄存器 - if (opcode == RVOpcodes::FEQ_S || opcode == RVOpcodes::FLT_S || opcode == RVOpcodes::FLE_S) { - auto& operands = instr->getOperands(); - // Def: 第一个操作数 (整数vreg) - if (operands[0]->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(operands[0].get()); - if(reg_op->isVirtual()) def.insert(reg_op->getVRegNum()); - } - // Use: 第二、三个操作数 (浮点vreg) - if (operands[1]->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(operands[1].get()); - if(reg_op->isVirtual()) use.insert(reg_op->getVRegNum()); - } - if (operands[2]->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(operands[2].get()); - if(reg_op->isVirtual()) use.insert(reg_op->getVRegNum()); - } - return; // 处理完毕 - } - - // 3. 对其他所有指令的通用处理逻辑 [已重构和修复] - for (const auto& op : instr->getOperands()) { - if (op->getKind() == MachineOperand::KIND_REG) { - auto reg_op = static_cast(op.get()); - - if (first_reg_is_def) { - // --- 处理定义(Def) --- - if (reg_op->isVirtual()) { - def.insert(reg_op->getVRegNum()); - } else { // 物理寄存器也可以是 Def - auto it = preg_to_vreg_id_map.find(reg_op->getPReg()); - if (it != preg_to_vreg_id_map.end()) { - def.insert(it->second); - } - } - first_reg_is_def = false; // **关键**:处理完第一个寄存器后,立即更新标志 - } else { - // --- 处理使用(Use) --- - if (reg_op->isVirtual()) { - use.insert(reg_op->getVRegNum()); - } else { // 物理寄存器也可以是 Use - auto it = preg_to_vreg_id_map.find(reg_op->getPReg()); - if (it != preg_to_vreg_id_map.end()) { - use.insert(it->second); - } - } - } - } else if (op->getKind() == MachineOperand::KIND_MEM) { - // 内存操作数的处理逻辑看起来是正确的 - auto mem_op = static_cast(op.get()); - auto base_reg = mem_op->getBase(); - if (base_reg->isVirtual()) { - use.insert(base_reg->getVRegNum()); - } else { - PhysicalReg preg = base_reg->getPReg(); - auto it = preg_to_vreg_id_map.find(preg); - if (it != preg_to_vreg_id_map.end()) { - use.insert(it->second); - } - } - - // 对于存储内存指令 (SW, SD),要存储的值(第一个操作数)也是 `use` - if ((opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW) && - !instr->getOperands().empty() && - instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) { - auto src_reg_op = static_cast(instr->getOperands().front().get()); - if (src_reg_op->isVirtual()) { - use.insert(src_reg_op->getVRegNum()); - } else { - auto it = preg_to_vreg_id_map.find(src_reg_op->getPReg()); - if (it != preg_to_vreg_id_map.end()) { - use.insert(it->second); - } - } - } - } - } -} - -/** - * @brief 计算一个类型在内存中占用的字节数。 - * @param type 需要计算大小的IR类型。 - * @return 该类型占用的字节数。 - */ -unsigned RISCv64RegAlloc::getTypeSizeInBytes(Type* type) { - if (!type) { - assert(false && "Cannot get size of a null type."); - return 0; - } - - switch (type->getKind()) { - // 对于SysY语言,基本类型int和float都占用4字节 - case Type::kInt: - case Type::kFloat: - return 4; - - // 指针类型在RISC-V 64位架构下占用8字节 - // 虽然SysY没有'int*'语法,但数组变量在IR层面本身就是指针类型 - case Type::kPointer: - return 8; - - // 数组类型的总大小 = 元素数量 * 单个元素的大小 - case Type::kArray: { - auto arrayType = type->as(); - // 递归调用以计算元素大小 - return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType()); - } - - // 其他类型,如Void, Label等不占用栈空间,或者不应该出现在这里 - default: - // 如果遇到未处理的类型,触发断言,方便调试 - assert(false && "Unsupported type for size calculation."); - return 0; - } + adjList.clear(); + degree.clear(); + moveList.clear(); + alias.clear(); + color_map.clear(); // [修正] 恢复对 color_map 的清除 } +// 活跃性分析(此部分为标准数据流分析,与现有版本类似但更精细) void RISCv64RegAlloc::analyzeLiveness() { - // === 阶段 1: 预计算每个基本块的 use 和 def 集合 === - // 这样可以避免在主循环中重复计算 - std::map block_uses; - std::map block_defs; - for (auto& mbb_ptr : MFunc->getBlocks()) { - MachineBasicBlock* mbb = mbb_ptr.get(); - LiveSet uses, defs; - for (auto& instr_ptr : mbb->getInstructions()) { - LiveSet instr_use, instr_def; - getInstrUseDef(instr_ptr.get(), instr_use, instr_def); - // use[B] = use[B] U (instr_use - def[B]) + live_in_map.clear(); + live_out_map.clear(); + + std::map block_uses; + std::map block_defs; + + for (const auto& mbb_ptr : MFunc->getBlocks()) { + const MachineBasicBlock* mbb = mbb_ptr.get(); + VRegSet uses, defs; + for (const auto& instr_ptr : mbb->getInstructions()) { + VRegSet instr_use, instr_def; + // 使用新的、能看到物理寄存器的版本 + getInstrUseDef_Liveness(instr_ptr.get(), instr_use, instr_def); for (unsigned u : instr_use) { - if (defs.find(u) == defs.end()) { - uses.insert(u); - } + if (defs.find(u) == defs.end()) uses.insert(u); } - // def[B] = def[B] U instr_def defs.insert(instr_def.begin(), instr_def.end()); } block_uses[mbb] = uses; block_defs[mbb] = defs; } - // === 阶段 2: 在“块”粒度上进行迭代数据流分析,直到收敛 === - std::map block_live_in; - std::map block_live_out; bool changed = true; + std::map live_in, live_out; while (changed) { changed = false; - // 以逆后序遍历基本块,可以加速收敛,但简单的逆序对于大多数情况也有效 for (auto it = MFunc->getBlocks().rbegin(); it != MFunc->getBlocks().rend(); ++it) { - auto& mbb = *it; - - // 2.1 计算 live_out[B] = U_{S in succ(B)} live_in[S] - LiveSet new_live_out; + const auto& mbb_ptr = *it; + const MachineBasicBlock* mbb = mbb_ptr.get(); + VRegSet new_out; for (auto succ : mbb->successors) { - new_live_out.insert(block_live_in[succ].begin(), block_live_in[succ].end()); + new_out.insert(live_in[succ].begin(), live_in[succ].end()); } - - // 2.2 计算 live_in[B] = use[B] U (live_out[B] - def[B]) - LiveSet live_out_minus_def = new_live_out; - for (unsigned d : block_defs[mbb.get()]) { - live_out_minus_def.erase(d); - } - LiveSet new_live_in = block_uses[mbb.get()]; - new_live_in.insert(live_out_minus_def.begin(), live_out_minus_def.end()); - - // 2.3 检查 live_in 和 live_out 是否变化,以判断是否达到不动点 - if (block_live_out[mbb.get()] != new_live_out) { + VRegSet new_in = block_uses[mbb]; + VRegSet out_minus_def = new_out; + for (unsigned d : block_defs[mbb]) out_minus_def.erase(d); + new_in.insert(out_minus_def.begin(), out_minus_def.end()); + if (live_out[mbb] != new_out || live_in[mbb] != new_in) { changed = true; - block_live_out[mbb.get()] = new_live_out; - } - if (block_live_in[mbb.get()] != new_live_in) { - changed = true; - block_live_in[mbb.get()] = new_live_in; + live_out[mbb] = new_out; + live_in[mbb] = new_in; } } } - // === 阶段 3: 进行一次指令粒度的遍历,填充最终的 live_in_map 和 live_out_map === - // 此时块级别的活跃信息已经稳定,我们只需遍历一次即可 - for (auto& mbb_ptr : MFunc->getBlocks()) { - MachineBasicBlock* mbb = mbb_ptr.get(); - LiveSet live_out = block_live_out[mbb]; // 从已收敛的块级 live_out 开始 - + for (const auto& mbb_ptr : MFunc->getBlocks()) { + const MachineBasicBlock* mbb = mbb_ptr.get(); + VRegSet current_live = live_out[mbb]; for (auto instr_it = mbb->getInstructions().rbegin(); instr_it != mbb->getInstructions().rend(); ++instr_it) { - MachineInstr* instr = instr_it->get(); - live_out_map[instr] = live_out; - - LiveSet use, def; - getInstrUseDef(instr, use, def); - - LiveSet live_in = use; - LiveSet diff = live_out; - for (auto vreg : def) { - diff.erase(vreg); - } - live_in.insert(diff.begin(), diff.end()); - live_in_map[instr] = live_in; - - // 更新 live_out,为块内的上一条指令做准备 - live_out = live_in; + const MachineInstr* instr = instr_it->get(); + live_out_map[instr] = current_live; + VRegSet use, def; + // 使用新的、能看到物理寄存器的版本 + getInstrUseDef_Liveness(instr, use, def); + for(auto d : def) current_live.erase(d); + for(auto u : use) current_live.insert(u); + live_in_map[instr] = current_live; } } } -// 辅助函数,用于清晰地打印寄存器集合。可以放在 .cpp 文件的顶部。 -void RISCv64RegAlloc::printLiveSet(const LiveSet& s, const std::string& name, std::ostream& os) { - os << " " << name << ": { "; - for (unsigned vreg : s) { - // 为了可读性,将物理寄存器对应的特殊ID进行转换 - if (vreg >= static_cast(sysy::PhysicalReg::PHYS_REG_START_ID)) { - os << "preg(" << (vreg - static_cast(sysy::PhysicalReg::PHYS_REG_START_ID)) << ") "; - } else { - os << "%vreg" << vreg << " "; - } - } - os << "}\n"; -} +// [最终修正] 包含了所有正确逻辑和您已有调试代码的完整版本 +void RISCv64RegAlloc::build() { + initial.clear(); + RISCv64AsmPrinter printer_inside_build(MFunc); + printer_inside_build.setStream(std::cerr); -void RISCv64RegAlloc::buildInterferenceGraph() { - std::set all_vregs; - // 收集所有虚拟寄存器和物理寄存器在干扰图中的节点ID - for (auto& mbb : MFunc->getBlocks()) { - for(auto& instr : mbb->getInstructions()) { - LiveSet use, def; - getInstrUseDef(instr.get(), use, def); - for(auto u : use) all_vregs.insert(u); - for(auto d : def) all_vregs.insert(d); - } - } - // 添加所有物理寄存器对应的特殊虚拟寄存器ID到all_vregs,作为干扰图节点 - for (auto preg : allocable_int_regs) { - all_vregs.insert(preg_to_vreg_id_map.at(preg)); - } + 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); - // 初始化干扰图邻接表 - for (auto vreg : all_vregs) { interference_graph[vreg] = {}; } - - // 创建一个临时的AsmPrinter用于打印指令,方便调试 - RISCv64AsmPrinter temp_printer(MFunc); - temp_printer.setStream(std::cerr); - - for (auto& mbb : MFunc->getBlocks()) { - if (DEEPDEBUG) std::cerr << "--- Building Graph for Basic Block: " << mbb->getName() << " ---\n"; - for (auto& instr_ptr : mbb->getInstructions()) { - MachineInstr* instr = instr_ptr.get(); + // 调试输出 use 和 def if (DEEPDEBUG) { - // 打印当前正在处理的指令 - std::cerr << " Instr: "; - temp_printer.printInstruction(instr, true); // 使用 true 来打印虚拟寄存器 + 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) << " "; // 使用新函数 + std::cerr << "}\n"; + }; + print_set(def, "Def "); + print_set(use, "Use "); + } + + for (unsigned v : use) { + if (!coloredNodes.count(v)) { + initial.insert(v); + } else if (DEEPDEBUG) { + std::cerr << "Skipping %vreg" << v << " because it is in coloredNodes.\n"; + } + } + for (unsigned v : def) { + if (!coloredNodes.count(v)) { + initial.insert(v); + } else if (DEEPDEBUG) { + std::cerr << "Skipping %vreg" << v << " because it is in coloredNodes.\n"; + } + } + } + } + + if (DEEPDEBUG) { + std::cerr << "Initial set after build: { "; + for (unsigned v : initial) std::cerr << "%vreg" << v << " "; + std::cerr << "}\n"; + } + + for(unsigned vreg : initial) { + adjList[vreg] = {}; + degree[vreg] = 0; + moveList[vreg] = {}; + // alias[vreg] = vreg; + } + + 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()) { + const MachineInstr* instr = instr_ptr.get(); + VRegSet use, def; + 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: "; + temp_printer.printInstruction(const_cast(instr), true); + + auto print_set = [this](const VRegSet& s, const std::string& name) { + std::cerr << " " << name << ": { "; + for(unsigned v : s) std::cerr << regIdToString(v) << " "; // 使用新函数 + std::cerr << "}\n"; + }; + print_set(def, "Def "); + print_set(use, "Use "); + print_set(live_out, "Live_Out"); + std::cerr << " ----------------\n"; } - LiveSet def, use; - getInstrUseDef(instr, use, def); - const LiveSet& live_out = live_out_map.at(instr); + bool is_move = instr->getOpcode() == RVOpcodes::MV; - // [新增调试逻辑] 打印所有相关的寄存器集合 - if (DEEPDEBUG) { - printLiveSet(use, "Use ", std::cerr); - printLiveSet(def, "Def ", std::cerr); - printLiveSet(live_out, "Live_Out", std::cerr); // 这是我们最关心的信息 + if (is_move) { + worklistMoves.insert(instr); + VRegSet move_vregs; + 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()); + } + } + for (unsigned vreg : move_vregs) { + moveList[vreg].insert(instr); + } } - // 标准干扰图构建:def 与 live_out 中的其他变量干扰 + // --- 规则 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_out) { - if (d != l) { - // [新增调试逻辑] 打印添加的干扰边及其原因 - if (DEEPDEBUG && interference_graph[d].find(l) == interference_graph[d].end()) { - std::cerr << " Edge (Def-LiveOut): %vreg" << d << " <-> %vreg" << l << "\n"; - } - interference_graph[d].insert(l); - interference_graph[l].insert(d); - } + for (unsigned l : live) { + addEdge(d, l); } } - - // 所有在某一点上同时活跃的寄存器(即live_out集合中的所有成员), - // 它们之间必须两两互相干扰。 - // 这会根据我们修正后的 liveness 信息,在所有参数vreg之间构建一个完全图(clique)。 - std::vector live_out_vec(live_out.begin(), live_out.end()); - for (size_t i = 0; i < live_out_vec.size(); ++i) { - for (size_t j = i + 1; j < live_out_vec.size(); ++j) { - unsigned u = live_out_vec[i]; - unsigned v = live_out_vec[j]; - if (DEEPDEBUG && interference_graph[u].find(v) == interference_graph[u].end()) { - std::cerr << " Edge (Live-Live): %vreg" << u << " <-> %vreg" << v << "\n"; - } - interference_graph[u].insert(v); - interference_graph[v].insert(u); - } - } - - // 在非move指令中,def 与 use 互相干扰 - if (instr->getOpcode() != RVOpcodes::MV) { + + // --- [新增的关键逻辑] 规则 2: 对于非move指令,强制def和use互相干扰 --- + // 这可以防止指令内部的源寄存器被目标寄存器错误地覆盖 + if (!is_move) { for (unsigned d : def) { for (unsigned u : use) { - if (d != u) { - // [新增调试逻辑] 打印添加的干扰边及其原因 - if (DEEPDEBUG && interference_graph[d].find(u) == interference_graph[d].end()) { - std::cerr << " Edge (Def-Use) : %vreg" << d << " <-> %vreg" << u << "\n"; - } - interference_graph[d].insert(u); - interference_graph[u].insert(d); - } + addEdge(d, u); } } } - // *** 处理 CALL 指令的隐式 def *** - if (instr->getOpcode() == RVOpcodes::CALL) { - // 你的原始CALL调试信息 - if (DEEPDEBUG) { - std::string live_out_str; - for (unsigned vreg : live_out) { - live_out_str += "%vreg" + std::to_string(vreg) + " "; - } - std::cerr << "[DEEPDEBUG] buildInterferenceGraph: CALL instruction found. Live out set is: {" - << live_out_str << "}" << std::endl; - } - // CALL 指令会定义(杀死)所有调用者保存的寄存器。 - // 因此,所有调用者保存的物理寄存器都与 CALL 指令的 live_out 中的所有变量冲突。 - - // 辅助函数,用于判断一个vreg是整数类型还是浮点类型 - auto is_fp_vreg = [&](unsigned vreg) { - if (vreg_to_value_map.count(vreg)) { - return vreg_to_value_map.at(vreg)->getType()->isFloat(); - } - // 对于ISel创建的、没有直接IR Value对应的临时vreg, - // 默认其为整数类型。这是一个合理的兜底策略。 - return false; - }; - - // --- 处理整数寄存器干扰 --- - const std::vector& caller_saved_int_regs = getCallerSavedIntRegs(); - for (PhysicalReg cs_reg : caller_saved_int_regs) { - // 确保物理寄存器在映射表中,我们已在构造函数中保证了这一点 - unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg); - - for (unsigned live_vreg_out : live_out) { - // 只为整数vreg添加与整数preg的干扰 - if (!is_fp_vreg(live_vreg_out)) { - if (cs_vreg_id != live_vreg_out) { - if (DEEPDEBUG && interference_graph[cs_vreg_id].find(live_vreg_out) == interference_graph[cs_vreg_id].end()) { - std::cerr << " Edge (CALL, Int): preg(" << static_cast(cs_reg) << ") <-> %vreg" << live_vreg_out << "\n"; - } - interference_graph[cs_vreg_id].insert(live_vreg_out); - interference_graph[live_vreg_out].insert(cs_vreg_id); - } - } - } - } - - // --- 处理浮点寄存器干扰 --- - const std::vector& caller_saved_fp_regs = getCallerSavedFpRegs(); - for (PhysicalReg cs_reg : caller_saved_fp_regs) { - unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg); - - for (unsigned live_vreg_out : live_out) { - // 只为浮点vreg添加与浮点preg的干扰 - if (is_fp_vreg(live_vreg_out)) { - if (cs_vreg_id != live_vreg_out) { - // 添加与整数版本一致的调试代码 - if (DEEPDEBUG && interference_graph[cs_vreg_id].find(live_vreg_out) == interference_graph[cs_vreg_id].end()) { - std::cerr << " Edge (CALL, FP): preg(" << static_cast(cs_reg) << ") <-> %vreg" << live_vreg_out << "\n"; - } - interference_graph[cs_vreg_id].insert(live_vreg_out); - interference_graph[live_vreg_out].insert(cs_vreg_id); - } - } - } + // --- 规则 3: Live_Out 集合内部形成完全图 --- + for (unsigned l1 : live_out) { + for (unsigned l2 : live_out) { + addEdge(l1, l2); } } - if (DEEPDEBUG) std::cerr << " ----------------\n"; } } } -void RISCv64RegAlloc::colorGraph() { - std::vector sorted_vregs; - for (auto const& [vreg, neighbors] : interference_graph) { - // 只为未预着色的虚拟寄存器排序和着色 - if (color_map.find(vreg) == color_map.end() && vreg < static_cast(PhysicalReg::PHYS_REG_START_ID)) { - sorted_vregs.push_back(vreg); +// 将节点放入初始工作列表 +void RISCv64RegAlloc::makeWorklist() { + for (unsigned n : initial) { + int K = isFPVReg(n) ? K_fp : K_int; + if (degree.count(n) == 0) { + std::cerr << "Error: degree not initialized for %vreg" << n << "\n"; + continue; + } + if (DEEPDEBUG) { + std::cerr << "Assigning %vreg" << n << " (degree=" << degree.at(n) + << ", moveRelated=" << moveRelated(n) << ")\n"; + } + if (degree.at(n) >= K) { + spillWorklist.insert(n); + } else if (moveRelated(n)) { + freezeWorklist.insert(n); + } else { + simplifyWorklist.insert(n); } } + if (DEEPDEBUG) std::cerr << "--------------------------------\n"; + initial.clear(); +} - // 排序 - std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) { - return interference_graph[a].size() > interference_graph[b].size(); - }); +// 简化阶段 +void RISCv64RegAlloc::simplify() { + unsigned n = *simplifyWorklist.begin(); + simplifyWorklist.erase(simplifyWorklist.begin()); + if (DEEPDEBUG) std::cerr << "[Simplify] Popped %vreg" << n << ", pushing to stack.\n"; + selectStack.push_back(n); + for (unsigned m : adjacent(n)) { + decrementDegree(m); + } +} - // [调试] 辅助函数,用于判断一个vreg是整数还是浮点类型,并打印详细诊断信息 - auto is_fp_vreg = [&](unsigned vreg) { +// 合并阶段 +void RISCv64RegAlloc::coalesce() { + const MachineInstr* move = *worklistMoves.begin(); + worklistMoves.erase(worklistMoves.begin()); + VRegSet use, def; + getInstrUseDef_Liveness(move, use, def); + unsigned x = getAlias(*def.begin()); + unsigned y = getAlias(*use.begin()); + unsigned u, v; + if (precolored.count(y)) { u = y; v = x; } else { u = x; v = y; } + + if (DEEPDEBUG) std::cerr << "[Coalesce] Processing move between " << regIdToString(x) + << " and " << regIdToString(y) << " (aliases " << regIdToString(u) + << ", " << regIdToString(v) << ").\n"; + + if (u == v) { + if (DEEPDEBUG) std::cerr << " -> Trivial coalesce (u == v).\n"; + coalescedMoves.insert(move); + addWorklist(u); + return; // 处理完毕,提前返回 + } + + if (isFPVReg(u) != isFPVReg(v)) { + if (DEEPDEBUG) std::cerr << " -> Constrained (type mismatch: " << regIdToString(u) << " is " + << (isFPVReg(u) ? "float" : "int") << ", " << regIdToString(v) << " is " + << (isFPVReg(v) ? "float" : "int") << ").\n"; + constrainedMoves.insert(move); + addWorklist(u); + addWorklist(v); + return; // 立即返回,不再进行后续检查 + } + + // --- 新的、拆分后的启发式检查逻辑 --- + + bool pre_interfere = adjList.at(v).count(u); + + if (pre_interfere) { + if (DEEPDEBUG) std::cerr << " -> Constrained (nodes already interfere).\n"; + constrainedMoves.insert(move); + addWorklist(u); + addWorklist(v); + return; + } + + bool is_u_precolored = precolored.count(u); + bool can_coalesce = false; + + if (is_u_precolored) { + // --- 场景1:u是物理寄存器,使用 George 启发式 --- + if (DEEPDEBUG) std::cerr << " -> Trying George Heuristic (u is precolored)...\n"; + + // ==================== [展开的 std::all_of 逻辑] ==================== + + // 步骤 1: 独立调用 adjacent(v) 获取邻居集合 + VRegSet neighbors_of_v = adjacent(v); if (DEEPDEBUG) { - std::cout << " [Debug is_fp_vreg] Checking vreg" << vreg << ": "; + std::cerr << " - Neighbors of " << regIdToString(v) << " to check are (" << neighbors_of_v.size() << "): { "; + for (unsigned id : neighbors_of_v) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n"; } - if (vreg_to_value_map.count(vreg)) { - Value* val = vreg_to_value_map.at(vreg); - bool is_float = val->getType()->isFloat(); + + // 步骤 2: 使用显式的 for 循环来代替 std::all_of + bool george_ok = true; // 默认假设成功,任何一个邻居失败都会将此设为 false + for (unsigned t : neighbors_of_v) { if (DEEPDEBUG) { - std::cout << "Found in map. Value is '" << val->getName() - << "', Type is " << (is_float ? "FLOAT" : "INT") - << ". Returning " << (is_float ? "true" : "false") << ".\n"; + std::cerr << " - Checking neighbor " << regIdToString(t) << ":\n"; + } + + // 步骤 3: 独立调用启发式函数 + bool heuristic_result = georgeHeuristic(t, u); + + if (DEEPDEBUG) { + std::cerr << " - georgeHeuristic(" << regIdToString(t) << ", " << regIdToString(u) << ") -> " << (heuristic_result ? "OK" : "FAIL") << "\n"; + } + + if (!heuristic_result) { + george_ok = false; // 只要有一个邻居不满足条件,整个检查就失败 + break; // 并且可以立即停止检查其他邻居 } - return is_float; } if (DEEPDEBUG) { - std::cout << "NOT found in vreg_to_value_map. Defaulting to INT. Returning false.\n"; + std::cerr << " -> George Heuristic final result: " << (george_ok ? "OK" : "FAIL") << "\n"; } - // 对于ISel创建的、没有直接IR Value对应的临时vreg,默认其为整数类型。 - return false; - }; + // ================================================================= - // 着色 - for (unsigned vreg : sorted_vregs) { - std::set used_colors; - for (unsigned neighbor_id : interference_graph.at(vreg)) { - // 收集邻居颜色的逻辑保持不变 - if (color_map.count(neighbor_id)) { - used_colors.insert(color_map.at(neighbor_id)); - } - else if (neighbor_id >= static_cast(PhysicalReg::PHYS_REG_START_ID)) { - PhysicalReg neighbor_preg = static_cast(neighbor_id - static_cast(PhysicalReg::PHYS_REG_START_ID)); - used_colors.insert(neighbor_preg); - } + if (george_ok) { + can_coalesce = true; } + + } else { + // --- 场景2:u和v都是虚拟寄存器,使用 Briggs 启发式 --- + if (DEEPDEBUG) std::cerr << " -> Trying Briggs Heuristic (u and v are virtual)...\n"; - bool is_float = is_fp_vreg(vreg); - const auto& allocable_regs = is_float ? allocable_fp_regs : allocable_int_regs; - - // [调试] 打印着色决策过程 - if (DEBUG) { - std::cout << "[DEBUG] Coloring %vreg" << vreg - << ": Type is " << (is_float ? "FLOAT" : "INT") - << ", choosing from " << (is_float ? "Float" : "Integer") << " pool.\n"; + bool briggs_ok = briggsHeuristic(u, v); + if (DEEPDEBUG) std::cerr << " - briggsHeuristic(" << regIdToString(u) << ", " << regIdToString(v) << ") -> " << (briggs_ok ? "OK" : "FAIL") << "\n"; + + if (briggs_ok) { + can_coalesce = true; } - - bool colored = false; - for (PhysicalReg preg : allocable_regs) { - if (used_colors.find(preg) == used_colors.end()) { - color_map[vreg] = preg; - colored = true; - if (DEBUG) { - RISCv64AsmPrinter p(MFunc); // For regToString - std::cout << " -> Assigned to physical register: " << p.regToString(preg) << "\n"; + } + + // --- 根据启发式结果进行最终决策 --- + + if (can_coalesce) { + if (DEEPDEBUG) std::cerr << " -> Heuristic OK. Combining " << regIdToString(v) << " into " << regIdToString(u) << ".\n"; + coalescedMoves.insert(move); + combine(u, v); + addWorklist(u); + } else { + if (DEEPDEBUG) std::cerr << " -> Heuristic failed. Adding to active moves.\n"; + activeMoves.insert(move); + } +} + +// 冻结阶段 +void RISCv64RegAlloc::freeze() { + unsigned u = *freezeWorklist.begin(); + freezeWorklist.erase(freezeWorklist.begin()); + if (DEEPDEBUG) std::cerr << "[Freeze] Freezing %vreg" << u << " and moving to simplify list.\n"; + simplifyWorklist.insert(u); + freezeMoves(u); +} + +// 选择溢出节点 +void RISCv64RegAlloc::selectSpill() { + auto it = std::max_element(spillWorklist.begin(), spillWorklist.end(), + [&](unsigned a, unsigned b){ return degree.at(a) < degree.at(b); }); + unsigned m = *it; + spillWorklist.erase(it); + if (DEEPDEBUG) std::cerr << "[Spill] Selecting %vreg" << m << " to spill.\n"; + simplifyWorklist.insert(m); + freezeMoves(m); +} + +void RISCv64RegAlloc::assignColors() { + if (DEEPDEBUG) std::cerr << "[AssignColors] Starting...\n"; + while (!selectStack.empty()) { + unsigned n = selectStack.back(); + selectStack.pop_back(); + bool is_fp = isFPVReg(n); + 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); + + 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); } - break; + ok_colors.erase(neighbor_color); } } - if (!colored) { - spilled_vregs.insert(vreg); - if (DEBUG) { - std::cout << " -> FAILED to color. Spilling.\n"; - } + + if (ok_colors.empty()) { + if (DEEPDEBUG) std::cerr << " -> No color for %vreg" << n << ". Spilling.\n"; + spilledNodes.insert(n); + } else { + 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"; + } + } + + // 为合并的节点上色(这部分逻辑是正确的) + for (unsigned n : coalescedNodes) { + unsigned root_alias = getAlias(n); + 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"; + spilledNodes.insert(n); } } } -void RISCv64RegAlloc::rewriteFunction() { +// 重写程序,插入溢出代码 +void RISCv64RegAlloc::rewriteProgram() { + // 1. 为溢出的旧vreg在栈上分配空间 (这部分逻辑不变) StackFrameInfo& frame_info = MFunc->getFrameInfo(); - int current_offset = frame_info.locals_size; + // locals_size, callee_saved_size等已经由之前的步骤或上一次运行计算好 + // 我们在此基础上累加溢出区大小 + int spill_base_offset = frame_info.locals_size + frame_info.callee_saved_size; - // --- 动态计算溢出槽大小 --- - // 根据溢出虚拟寄存器的真实类型,为其在栈上分配正确大小的空间。 - for (unsigned vreg : spilled_vregs) { - // 从反向映射中查找 vreg 对应的 IR Value - assert(vreg_to_value_map.count(vreg) && "Spilled vreg not found in map!"); - Value* val = vreg_to_value_map.at(vreg); - - // 使用辅助函数获取类型大小 - int size = getTypeSizeInBytes(val->getType()); - - // 保持栈8字节对齐 - current_offset += size; - current_offset = (current_offset + 7) & ~7; + for (unsigned vreg : spilledNodes) { + if (frame_info.spill_offsets.count(vreg)) continue; // 如果已经分配过则跳过 - frame_info.spill_offsets[vreg] = -current_offset; + int size = 4; // 默认4字节 + if (isFPVReg(vreg)) { + size = 4; // float + } else if (vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isPointer()) { + size = 8; // pointer + } + + spill_base_offset += size; + spill_base_offset = (spill_base_offset + 7) & ~7; // 8字节对齐 + frame_info.spill_offsets[vreg] = spill_base_offset; } - frame_info.spill_size = current_offset - frame_info.locals_size; - - // 定义专用的溢出寄存器 - const PhysicalReg INT_SPILL_REG = PhysicalReg::T6; // t6 - const PhysicalReg FP_SPILL_REG = PhysicalReg::F7; // ft7 + frame_info.spill_size = spill_base_offset - (frame_info.locals_size + frame_info.callee_saved_size); + // 2. 遍历所有指令,为溢出vreg的use/def插入load/store,并使用新的临时虚拟寄存器 for (auto& mbb : MFunc->getBlocks()) { std::vector> new_instructions; + for (auto& instr_ptr : mbb->getInstructions()) { - LiveSet use, def; - getInstrUseDef(instr_ptr.get(), use, def); + // 对每条指令,记录其使用的旧vreg到新临时vreg的映射 + std::map vreg_remap; - // --- 为溢出的 'use' 操作数插入正确的加载指令 --- - for (unsigned vreg : use) { - if (spilled_vregs.count(vreg)) { - // 同样地,根据 vreg 的类型决定使用 lw 还是 ld - assert(vreg_to_value_map.count(vreg)); - Value* val = vreg_to_value_map.at(vreg); - - // 根据vreg类型决定加载指令(lw/ld/flw)和目标物理寄存器(t6/ft7) - RVOpcodes load_op; - PhysicalReg target_preg; - if (val->getType()->isFloat()) { - load_op = RVOpcodes::FLW; - target_preg = FP_SPILL_REG; - } else if (val->getType()->isPointer()) { - load_op = RVOpcodes::LD; - target_preg = INT_SPILL_REG; - } else { - load_op = RVOpcodes::LW; - target_preg = INT_SPILL_REG; + // a. 为每个溢出的 use 操作数,在原指令前插入 load 指令 + VRegSet use, def; + getInstrUseDef_Liveness(instr_ptr.get(), use, def); // 假设此函数能正确处理operands + + for(auto& op : instr_ptr->getOperands()) { + if (op->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op.get()); + 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(); + unsigned new_temp_vreg = ISel->getNewVReg(type); + vreg_remap[old_vreg] = new_temp_vreg; + + RVOpcodes load_op; + if (isFPVReg(old_vreg)) load_op = RVOpcodes::FLW; + else if (type->isPointer()) load_op = RVOpcodes::LD; + else load_op = 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)) // 偏移是相对于S0的负值 + )); + new_instructions.push_back(std::move(load)); + } } + } else if (op->getKind() == MachineOperand::KIND_MEM) { + auto reg_op = static_cast(op.get())->getBase(); + if (reg_op->isVirtual() && spilledNodes.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(); + unsigned new_temp_vreg = ISel->getNewVReg(type); + vreg_remap[old_vreg] = new_temp_vreg; - int offset = frame_info.spill_offsets.at(vreg); - auto load = std::make_unique(load_op); - load->addOperand(std::make_unique(target_preg)); // 加载到专用溢出寄存器 - load->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(offset) - )); - new_instructions.push_back(std::move(load)); + RVOpcodes load_op = (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)) + )); + new_instructions.push_back(std::move(load)); + } + } + } + } + + // b. 替换原指令中的操作数,并将其加入新指令列表 + for(auto& op : instr_ptr->getOperands()) { + if (op->getKind() == MachineOperand::KIND_REG) { + auto reg_op = static_cast(op.get()); + 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(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)); - // --- 为溢出的 'def' 操作数插入正确的存储指令 --- - for (unsigned vreg : def) { - if (spilled_vregs.count(vreg)) { - assert(vreg_to_value_map.count(vreg)); - Value* val = vreg_to_value_map.at(vreg); - - // 根据vreg类型决定存储指令(sw/sd/fsw)和源物理寄存器(t6/ft7) - RVOpcodes store_op; - PhysicalReg src_preg; - if (val->getType()->isFloat()) { - store_op = RVOpcodes::FSW; - src_preg = FP_SPILL_REG; - } else if (val->getType()->isPointer()) { - store_op = RVOpcodes::SD; - src_preg = INT_SPILL_REG; - } else { - store_op = RVOpcodes::SW; - src_preg = INT_SPILL_REG; - } + // 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(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(); + 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); - int offset = frame_info.spill_offsets.at(vreg); - auto store = std::make_unique(store_op); - store->addOperand(std::make_unique(src_preg)); // 从专用溢出寄存器存储 - store->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(offset) - )); - new_instructions.push_back(std::move(store)); - } + RVOpcodes store_op; + if (isFPVReg(old_vreg)) store_op = RVOpcodes::FSW; + else if (type->isPointer()) store_op = RVOpcodes::SD; + else store_op = RVOpcodes::SW; + + auto store = std::make_unique(store_op); + store->addOperand(std::make_unique(new_temp_vreg)); // 从新的临时vreg中存值 + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(-frame_info.spill_offsets.at(old_vreg)) + )); + // 在原指令之后插入store + new_instructions.push_back(std::move(store)); + } + } + } } } mbb->getInstructions() = std::move(new_instructions); } - // 最后的虚拟寄存器到物理寄存器的替换过程保持不变 + // 清空溢出节点集合,为下一次迭代分配做准备 + spilledNodes.clear(); +} + +/** + * @brief [最终修正] 获取一条指令完整的【虚拟】使用/定义寄存器集合 + * 这个函数将服务于图的构建(收集initial节点等)。 + */ +void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def) { + auto opcode = instr->getOpcode(); + const auto& operands = instr->getOperands(); + + 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}}}, + {RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}}, + {RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}}, + {RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}}, + {RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}}, + {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::RET, {{}, {}}}, {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}}} + }; + + auto get_vreg_id_if_virtual = [&](const MachineOperand* op, VRegSet& 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); + } +} + +/** + * @brief [新增] 获取一条指令完整的、包含物理寄存器的Use/Def集合 + * 这个新函数将专门服务于活跃性分析。 + */ +void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) { + auto opcode = instr->getOpcode(); + const auto& operands = instr->getOperands(); + + 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}}}, + {RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}}, + {RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}}, + {RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}}, + {RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}}, + {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::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}}} + }; + + 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) { + auto reg_op = static_cast(op); + return reg_op->isVirtual() ? reg_op->getVRegNum() : (offset + static_cast(reg_op->getPReg())); + } else if (op->getKind() == MachineOperand::KIND_MEM) { + auto mem_op = static_cast(op); + auto reg_op = mem_op->getBase(); + return reg_op->isVirtual() ? reg_op->getVRegNum() : (offset + static_cast(reg_op->getPReg())); + } + return (unsigned)-1; + }; + + 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)); + } +} + +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)++; + } + } + + // 对称地,如果 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)++; + } + } +} + +RISCv64RegAlloc::VRegSet RISCv64RegAlloc::adjacent(unsigned n) { + // 仅在 DEEPDEBUG 模式下启用详细日志 + if (DEEPDEBUG) { + // 使用 regIdToString 打印节点 n,无论是物理还是虚拟 + std::cerr << "\n[adjacent] >>>>> Executing for node " << regIdToString(n) << " <<<<<\n"; + } + + // 1. 如果节点 n 是物理寄存器,它没有邻接表,直接返回空集 + if (precolored.count(n)) { + if (DEEPDEBUG) { + std::cerr << "[adjacent] Node " << regIdToString(n) << " is precolored. Returning {}.\n"; + } + return {}; + } + + // 安全检查:确保 n 在 adjList 中存在,防止 map::at 崩溃 + if (adjList.count(n) == 0) { + if (DEEPDEBUG) { + std::cerr << "[adjacent] WARNING: Node " << regIdToString(n) << " not found in adjList. Returning {}.\n"; + } + return {}; + } + + // 2. 获取 n 在冲突图中的所有邻居 + VRegSet result = adjList.at(n); + + if (DEEPDEBUG) { + // 定义一个局部的 lambda 方便打印集合 + auto print_set = [this](const VRegSet& s, const std::string& name) { + std::cerr << "[adjacent] " << name << " (" << s.size() << "): { "; + for (unsigned id : s) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n"; + }; + print_set(result, "Initial full neighbors"); + } + + // 3. 过滤掉那些已经在 selectStack 或 coalescedNodes 中的邻居 + // 这些节点被认为是“已移除”的,不参与当前的启发式判断 + + // 3a. 从 selectStack 中移除 + VRegSet removed_from_stack; // 仅用于调试打印 + for (auto it = selectStack.rbegin(); it != selectStack.rend(); ++it) { + if (result.count(*it)) { + if (DEEPDEBUG) removed_from_stack.insert(*it); + result.erase(*it); + } + } + if (DEEPDEBUG && !removed_from_stack.empty()) { + std::cerr << "[adjacent] - Removed from selectStack: { "; + for(unsigned id : removed_from_stack) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n"; + } + + // 3b. 从 coalescedNodes 中移除 + VRegSet removed_from_coalesced; // 仅用于调试打印 + for (unsigned cn : coalescedNodes) { + if (result.count(cn)) { + if (DEEPDEBUG) removed_from_coalesced.insert(cn); + result.erase(cn); + } + } + if (DEEPDEBUG && !removed_from_coalesced.empty()) { + std::cerr << "[adjacent] - Removed from coalescedNodes: { "; + for(unsigned id : removed_from_coalesced) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n"; + } + + // 4. 返回最终的、过滤后的“有效”邻居集合 + if (DEEPDEBUG) { + std::cerr << "[adjacent] >>>>> Returning final adjacent set (" << result.size() << "): { "; + for (unsigned id : result) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n\n"; + } + + return result; +} + +RISCv64RegAlloc::VRegMoveSet RISCv64RegAlloc::nodeMoves(unsigned n) { + if (precolored.count(n) || !moveList.count(n)) { + return {}; + } + + VRegMoveSet result; + const VRegMoveSet& moves = moveList.at(n); + for (const auto& move : moves) { + if (activeMoves.count(move) || worklistMoves.count(move)) { + result.insert(move); + } + } + return result; +} + +bool RISCv64RegAlloc::moveRelated(unsigned n) { + return !nodeMoves(n).empty(); +} + +void RISCv64RegAlloc::decrementDegree(unsigned m) { + if (precolored.count(m)) { + return; + } + + int K = isFPVReg(m) ? K_fp : K_int; + int d = degree.at(m); + degree.at(m)--; + if (d == K) { + VRegSet nodes_to_enable = adjacent(m); + nodes_to_enable.insert(m); + enableMoves(nodes_to_enable); + spillWorklist.erase(m); + if (moveRelated(m)) { + freezeWorklist.insert(m); + } else { + simplifyWorklist.insert(m); + } + } +} + +void RISCv64RegAlloc::enableMoves(const VRegSet& nodes) { + for (unsigned n : nodes) { + VRegMoveSet moves = nodeMoves(n); + for (const auto& move : moves) { + if (activeMoves.count(move)) { + activeMoves.erase(move); + worklistMoves.insert(move); + } + } + } +} + +unsigned RISCv64RegAlloc::getAlias(unsigned n) { + if (precolored.count(n)) { + return n; + } + if (alias.count(n)) { + // 路径压缩 + alias.at(n) = getAlias(alias.at(n)); + return alias.at(n); + } + return n; +} + +void RISCv64RegAlloc::addWorklist(unsigned u) { + if (precolored.count(u)) return; + + int K = isFPVReg(u) ? K_fp : K_int; + if (!moveRelated(u) && degree.at(u) < K) { + freezeWorklist.erase(u); + simplifyWorklist.insert(u); + } +} + +// Briggs启发式 +bool RISCv64RegAlloc::briggsHeuristic(unsigned u, unsigned v) { + if (DEEPDEBUG) { + std::cerr << "\n[Briggs] >>>>> Checking coalesce between " << regIdToString(u) << " and " << regIdToString(v) << " <<<<<\n"; + } + + // 步骤 1: 分别获取 u 和 v 的邻居 + VRegSet u_adj = adjacent(u); + VRegSet v_adj = adjacent(v); + + // 步骤 2: 合并两个邻居集合 + VRegSet all_adj = u_adj; + all_adj.insert(v_adj.begin(), v_adj.end()); + + if (DEEPDEBUG) { + auto print_set = [this](const VRegSet& s, const std::string& name) { + std::cerr << "[Briggs] " << name << " (" << s.size() << "): { "; + for (unsigned id : s) std::cerr << regIdToString(id) << " "; + std::cerr << "}\n"; + }; + print_set(u_adj, "Neighbors of u"); + print_set(v_adj, "Neighbors of v"); + print_set(all_adj, "Combined neighbors"); + } + + // 步骤 3: 遍历合并后的邻居集合,计算度数 >= K 的节点数量 + int k = 0; + if (DEEPDEBUG) std::cerr << "[Briggs] Checking significance of combined neighbors:\n"; + for (unsigned n : all_adj) { + // 关键修正:只考虑那些在工作集中的邻居节点 n + if (degree.count(n) > 0) { + int K = isFPVReg(n) ? K_fp : K_int; + if (degree.at(n) >= K) { + k++; + if (DEEPDEBUG) { + std::cerr << "[Briggs] - Node " << regIdToString(n) << " is significant (degree " << degree.at(n) << " >= " << K << "). Count k is now " << k << ".\n"; + } + } + } + } + + // 步骤 4: 比较 "重要" 邻居的数量是否小于 K + int K_u = isFPVReg(u) ? K_fp : K_int; + bool result = (k < K_u); + + if (DEEPDEBUG) { + std::cerr << "[Briggs] Final count of significant neighbors (k) = " << k << ".\n"; + std::cerr << "[Briggs] K value for node " << regIdToString(u) << " is " << K_u << ".\n"; + std::cerr << "[Briggs] >>>>> Result (k < K): " << (result ? "OK (can coalesce)" : "FAIL (cannot coalesce)") << "\n\n"; + } + + return result; +} + +// George启发式 +bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) { + // 关键修正:如果 t 不是一个待分配的虚拟寄存器(即它是物理寄存器), + // 那么它已经被预着色,总是满足 George 启发式条件。 + // 我们通过检查 degree.count(t) 来判断 t 是否在我们的虚拟寄存器工作集中。 + if (degree.count(t) == 0) { + return true; + } + + int K = isFPVReg(t) ? K_fp : K_int; + // adjList.at(t) 现在是安全的,因为 degree.count(t) > 0 保证了 adjList.count(t) > 0 + return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u); +} + +void RISCv64RegAlloc::combine(unsigned u, unsigned v) { + freezeWorklist.erase(v); + spillWorklist.erase(v); + coalescedNodes.insert(v); + alias[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); + } + enableMoves({v}); + for (unsigned t : adjacent(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); + } +} + +void RISCv64RegAlloc::freezeMoves(unsigned u) { + if (precolored.count(u)) return; + + VRegMoveSet moves = nodeMoves(u); + for (const auto& move : moves) { + VRegSet use, def; + getInstrUseDef_Liveness(move, use, def); + unsigned x = *def.begin(); + unsigned y = *use.begin(); + unsigned v_alias; + + if (getAlias(y) == getAlias(u)) { + v_alias = getAlias(x); + } else { + v_alias = getAlias(y); + } + + activeMoves.erase(move); + frozenMoves.insert(move); + + if (!precolored.count(v_alias) && nodeMoves(v_alias).empty() && degree.at(v_alias) < (isFPVReg(v_alias) ? K_fp : K_int)) { + freezeWorklist.erase(v_alias); + simplifyWorklist.insert(v_alias); + } + } +} + +// 检查vreg是否为浮点类型 +bool RISCv64RegAlloc::isFPVReg(unsigned vreg) const { + // 1. 检查是否为虚拟寄存器 + if (vreg_type_map.count(vreg)) { + return vreg_type_map.at(vreg)->isFloat(); + } + + // 2. 检查是否为物理寄存器 (ID >= 100000) + const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); + if (vreg >= offset) { + // 先减去偏移,还原成原始的、小的枚举值 + unsigned raw_preg_id = vreg - offset; + + // 再用原始枚举值判断是否在浮点寄存器范围内 + if (raw_preg_id >= static_cast(PhysicalReg::F0) && raw_preg_id <= static_cast(PhysicalReg::F31)) { + return true; + } + } + + // 3. 其他所有情况(如未知的vreg,或整数物理寄存器)都默认为整数 + return false; +} + +// 收集被使用的被调用者保存寄存器 +void RISCv64RegAlloc::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()); + // s0总是被使用作为帧指针 + callee_saved_set.insert(PhysicalReg::S0); + + + for(const auto& pair : color_map) { + PhysicalReg preg = pair.second; + if(callee_saved_set.count(preg)) { + frame_info.used_callee_saved_regs.insert(preg); + } + } +} + +/** + * @brief 将最终的寄存器分配结果应用到所有机器指令上。 + * 遍历所有操作数,将虚拟寄存器替换为分配到的物理寄存器。 + */ +void RISCv64RegAlloc::applyColoring() { for (auto& mbb : MFunc->getBlocks()) { for (auto& instr_ptr : mbb->getInstructions()) { for (auto& op_ptr : instr_ptr->getOperands()) { - // 定义一个处理寄存器操作数的 lambda 函数 - auto process_reg_op = [&](RegOperand* reg_op) { + 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 (color_map.count(vreg)) { + // 使用 setPReg 将虚拟寄存器转换为物理寄存器 + reg_op->setPReg(color_map.at(vreg)); + } else { + // 如果一个vreg在成功分配后仍然没有颜色,这是一个错误 + std::cerr << "FATAL: Virtual register %vreg" << vreg << " has no color after allocation!\n"; + assert(false && "Virtual register has no color after allocation!"); + reg_op->setPReg(PhysicalReg::T6); + } + } + } 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 (color_map.count(vreg)) { reg_op->setPReg(color_map.at(vreg)); - } else if (spilled_vregs.count(vreg)) { - // 根据vreg类型,替换为对应的专用溢出寄存器 - assert(vreg_to_value_map.count(vreg)); - Value* val = vreg_to_value_map.at(vreg); - if (val->getType()->isFloat()) { - reg_op->setPReg(FP_SPILL_REG); - } else { - reg_op->setPReg(INT_SPILL_REG); - } + } else { + assert(false && "Virtual register in memory operand has no color!"); + reg_op->setPReg(PhysicalReg::T6); } } - }; - - if(op_ptr->getKind() == MachineOperand::KIND_REG) { - process_reg_op(static_cast(op_ptr.get())); - } else if (op_ptr->getKind() == MachineOperand::KIND_MEM) { - process_reg_op(static_cast(op_ptr.get())->getBase()); } } } } } +void RISCv64RegAlloc::dumpState(const std::string& stage) { + if (!DEEPDEBUG) return; + std::cerr << "\n=============== STATE DUMP (" << stage << ") ===============\n"; + auto print_vreg_set = [&](const VRegSet& s, const std::string& name){ + std::cerr << name << " (" << s.size() << "): { "; + for(unsigned v : s) std::cerr << "%vreg" << v << " "; + std::cerr << "}\n"; + }; + print_vreg_set(simplifyWorklist, "SimplifyWorklist"); + print_vreg_set(freezeWorklist, "FreezeWorklist"); + print_vreg_set(spillWorklist, "SpillWorklist"); + print_vreg_set(coalescedNodes, "CoalescedNodes"); + print_vreg_set(spilledNodes, "SpilledNodes"); + + std::cerr << "SelectStack (" << selectStack.size() << "): { "; + for(unsigned v : selectStack) std::cerr << "%vreg" << v << " "; + std::cerr << "}\n"; + + std::cerr << "WorklistMoves (" << worklistMoves.size() << ")\n"; + std::cerr << "ActiveMoves (" << activeMoves.size() << ")\n"; + + size_t final_nodes = coalescedNodes.size() + spilledNodes.size() + selectStack.size(); + std::cerr << "Total Final Nodes: " << final_nodes << "\n"; + std::cerr << "=======================================================\n"; +} + +std::string RISCv64RegAlloc::regToString(PhysicalReg reg) { + switch (reg) { + case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra"; + case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp"; + case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0"; + case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2"; + case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1"; + case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1"; + case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3"; + case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5"; + case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7"; + case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3"; + case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5"; + case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7"; + case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9"; + case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11"; + case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4"; + case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6"; + case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1"; + case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3"; + case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5"; + case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7"; + case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9"; + case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11"; + case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13"; + case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15"; + case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17"; + case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19"; + case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21"; + case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23"; + case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25"; + case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27"; + case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29"; + case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31"; + default: return "UNKNOWN_REG"; + } +} + +std::string RISCv64RegAlloc::regIdToString(unsigned id) { + const unsigned offset = static_cast(PhysicalReg::PHYS_REG_START_ID); + + // 使用更健壮的检查方式 + if (id >= offset && precolored.count(id)) { + // 先减去偏移量,得到原始的、小的枚举值 + PhysicalReg reg = static_cast(id - offset); + // 再将原始枚举值传给 regToString + return regToString(reg); + } else { + return "%vreg" + std::to_string(id); + } +} + } // namespace sysy \ No newline at end of file diff --git a/src/include/backend/RISCv64/Handler/EliminateFrameIndices.h b/src/include/backend/RISCv64/Handler/EliminateFrameIndices.h new file mode 100644 index 0000000..155bdba --- /dev/null +++ b/src/include/backend/RISCv64/Handler/EliminateFrameIndices.h @@ -0,0 +1,20 @@ +#ifndef ELIMINATE_FRAME_INDICES_H +#define ELIMINATE_FRAME_INDICES_H + +#include "RISCv64LLIR.h" + +namespace sysy { + +class EliminateFrameIndicesPass { +public: + // Pass 的主入口函数 + void runOnMachineFunction(MachineFunction* mfunc); + +private: + // 帮助计算类型大小的辅助函数,从原RegAlloc中移出 + unsigned getTypeSizeInBytes(Type* type); +}; + +} // namespace sysy + +#endif // ELIMINATE_FRAME_INDICES_H \ No newline at end of file diff --git a/src/include/backend/RISCv64/RISCv64LLIR.h b/src/include/backend/RISCv64/RISCv64LLIR.h index be11528..2c2aec0 100644 --- a/src/include/backend/RISCv64/RISCv64LLIR.h +++ b/src/include/backend/RISCv64/RISCv64LLIR.h @@ -195,6 +195,11 @@ public: preg = new_preg; is_virtual = false; } + + void setVRegNum(unsigned new_vreg_num) { + vreg_num = new_vreg_num; + is_virtual = true; // 确保设置vreg时,操作数状态正确 + } private: unsigned vreg_num = 0; PhysicalReg preg = PhysicalReg::ZERO; @@ -280,8 +285,8 @@ struct StackFrameInfo { std::map alloca_offsets; // std::map spill_offsets; // <溢出vreg, 栈偏移> std::set used_callee_saved_regs; // 使用的保存寄存器 - std::map vreg_to_preg_map; - std::vector callee_saved_regs; // 用于存储需要保存的被调用者保存寄存器列表 + std::map vreg_to_preg_map; // [新增] RegAlloc最终的分配结果 + std::vector callee_saved_regs_to_store; // [新增] 已排序的、需要存取的被调用者保存寄存器 }; // 机器函数 diff --git a/src/include/backend/RISCv64/RISCv64Passes.h b/src/include/backend/RISCv64/RISCv64Passes.h index de08882..756be1d 100644 --- a/src/include/backend/RISCv64/RISCv64Passes.h +++ b/src/include/backend/RISCv64/RISCv64Passes.h @@ -8,6 +8,7 @@ #include "CalleeSavedHandler.h" #include "LegalizeImmediates.h" #include "PrologueEpilogueInsertion.h" +#include "EliminateFrameIndices.h" #include "Pass.h" namespace sysy { diff --git a/src/include/backend/RISCv64/RISCv64RegAlloc.h b/src/include/backend/RISCv64/RISCv64RegAlloc.h index 992aa5c..caf8149 100644 --- a/src/include/backend/RISCv64/RISCv64RegAlloc.h +++ b/src/include/backend/RISCv64/RISCv64RegAlloc.h @@ -1,8 +1,14 @@ +// in file: RISCv64RegAlloc.h + #ifndef RISCV64_REGALLOC_H #define RISCV64_REGALLOC_H #include "RISCv64LLIR.h" #include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型 +#include +#include +#include +#include extern int DEBUG; extern int DEEPDEBUG; @@ -17,58 +23,98 @@ public: void run(); private: - using LiveSet = std::set; // 活跃虚拟寄存器集合 - using InterferenceGraph = std::map>; + // 类型定义,与Python版本对应 + using VRegSet = std::set; + using InterferenceGraph = std::map; + using VRegStack = std::vector; // 使用vector模拟栈,方便遍历 + using MoveList = std::map>; + using AliasMap = std::map; + using ColorMap = std::map; + using VRegMoveSet = std::set; - // 栈帧管理 - void eliminateFrameIndices(); - - // 活跃性分析 + // --- 核心算法流程 --- + void initialize(); + void build(); + void makeWorklist(); + void simplify(); + void coalesce(); + void freeze(); + void selectSpill(); + void assignColors(); + void rewriteProgram(); + bool doAllocation(); + void applyColoring(); + + void dumpState(const std::string &stage); + + void precolorByCallingConvention(); + + // --- 辅助函数 --- + void getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def); + void getInstrUseDef_Liveness(const MachineInstr *instr, VRegSet &use, VRegSet &def); + void addEdge(unsigned u, unsigned v); + VRegSet adjacent(unsigned n); + VRegMoveSet nodeMoves(unsigned n); + bool moveRelated(unsigned n); + void decrementDegree(unsigned m); + void enableMoves(const VRegSet& nodes); + unsigned getAlias(unsigned n); + void addWorklist(unsigned u); + bool briggsHeuristic(unsigned u, unsigned v); + bool georgeHeuristic(unsigned u, unsigned v); + void combine(unsigned u, unsigned v); + void freezeMoves(unsigned u); + void collectUsedCalleeSavedRegs(); + bool isFPVReg(unsigned vreg) const; + std::string regToString(PhysicalReg reg); + std::string regIdToString(unsigned id); + + // --- 活跃性分析 --- void analyzeLiveness(); - // 构建干扰图 - void buildInterferenceGraph(); - - // 图着色分配寄存器 - void colorGraph(); - - // 重写函数,替换vreg并插入溢出代码 - void rewriteFunction(); - - // 辅助函数,获取指令的Use/Def集合 - void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def); - - // 辅助函数,处理调用约定 - void handleCallingConvention(); - MachineFunction* MFunc; - - // 活跃性分析结果 - std::map live_in_map; - std::map live_out_map; + RISCv64ISel* ISel; - // 干扰图 - InterferenceGraph interference_graph; - - // 图着色结果 - std::map color_map; // vreg -> preg - std::set spilled_vregs; // 被溢出的vreg集合 - - // 可用的物理寄存器池 + // --- 算法数据结构 --- + // 寄存器池 std::vector allocable_int_regs; std::vector allocable_fp_regs; + int K_int; // 整数寄存器数量 + int K_fp; // 浮点寄存器数量 - // 存储vreg到IR Value*的反向映射 - // 这个map将在run()函数开始时被填充,并在rewriteFunction()中使用。 - std::map vreg_to_value_map; - std::map preg_to_vreg_id_map; // 物理寄存器到特殊vreg ID的映射 - - // 用于计算类型大小的辅助函数 - unsigned getTypeSizeInBytes(Type* type); + // 节点集合 + VRegSet precolored; // 预着色的节点 (物理寄存器) + VRegSet initial; // 初始的、所有待处理的虚拟寄存器节点 + VRegSet simplifyWorklist; + VRegSet freezeWorklist; + VRegSet spillWorklist; + VRegSet spilledNodes; + VRegSet coalescedNodes; + VRegSet coloredNodes; + VRegStack selectStack; - // 辅助函数,用于打印集合 - static void printLiveSet(const LiveSet& s, const std::string& name, std::ostream& os); + // Move指令相关 + std::set coalescedMoves; + std::set constrainedMoves; + std::set frozenMoves; + std::set worklistMoves; + std::set activeMoves; + + // 数据结构 + InterferenceGraph adjSet; + std::map adjList; // 邻接表 + std::map degree; + MoveList moveList; + AliasMap alias; + ColorMap color_map; + + // 活跃性分析结果 + std::map live_in_map; + std::map live_out_map; + // VReg -> Value* 和 VReg -> Type* 的映射 + const std::map& vreg_to_value_map; + const std::map& vreg_type_map; }; } // namespace sysy