From b57a3f1953f61c0da3f6660ed082bcf976a67273 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Sun, 17 Aug 2025 22:45:57 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E6=AD=A3=E5=9C=A8=E4=BF=AE=E5=A4=8Dh/?= =?UTF-8?q?39?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RISCv64/Handler/LegalizeImmediates.cpp | 2 +- src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp | 128 ++++++++---------- 2 files changed, 58 insertions(+), 72 deletions(-) diff --git a/src/backend/RISCv64/Handler/LegalizeImmediates.cpp b/src/backend/RISCv64/Handler/LegalizeImmediates.cpp index 76e80e9..06b0691 100644 --- a/src/backend/RISCv64/Handler/LegalizeImmediates.cpp +++ b/src/backend/RISCv64/Handler/LegalizeImmediates.cpp @@ -95,7 +95,7 @@ void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) { case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD: case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU: case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD: - case RVOpcodes::FLW: case RVOpcodes::FSW: { + case RVOpcodes::FLW: case RVOpcodes::FSW: case RVOpcodes::FLD: case RVOpcodes::FSD: { auto& operands = instr_ptr->getOperands(); auto mem_op = static_cast(operands.back().get()); auto offset_op = mem_op->getOffset(); diff --git a/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp b/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp index ef266ec..9608b31 100644 --- a/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp @@ -517,18 +517,15 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { for (auto& instr_ptr : mbb->getInstructions()) { if (instr_ptr->getOpcode() != RVOpcodes::CALL) { - // --- 对于非CALL的普通指令,使用原始的、更高效的溢出逻辑 --- - // 因为它们的操作数很少,几乎不可能耗尽池 + // --- 对于非CALL的普通指令,此逻辑已是正确的 --- + // (此部分代码与上一版相同,保持不变) std::vector int_spill_pool = {PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6}; std::vector fp_spill_pool = {PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3}; std::map vreg_to_preg_map_for_this_instr; - LiveSet use, def; getInstrUseDef(instr_ptr.get(), use, def); - LiveSet all_vregs_in_instr = use; all_vregs_in_instr.insert(def.begin(), def.end()); - for(unsigned vreg : all_vregs_in_instr) { if (spilled_vregs.count(vreg)) { auto [type, size] = getTypeAndSize(vreg); @@ -543,7 +540,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { } } } - for (unsigned vreg : use) { if (spilled_vregs.count(vreg)) { PhysicalReg target_preg = vreg_to_preg_map_for_this_instr.at(vreg); @@ -558,13 +554,11 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { new_instructions.push_back(std::move(load)); } } - auto new_instr = std::make_unique(instr_ptr->getOpcode()); for (const auto& op : instr_ptr->getOperands()) { const RegOperand* reg_op = nullptr; if (op->getKind() == MachineOperand::KIND_REG) reg_op = static_cast(op.get()); else if (op->getKind() == MachineOperand::KIND_MEM) reg_op = static_cast(op.get())->getBase(); - if (reg_op) { PhysicalReg final_preg; if (reg_op->isVirtual()) { @@ -591,7 +585,6 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { } } new_instructions.push_back(std::move(new_instr)); - for (unsigned vreg : def) { if (spilled_vregs.count(vreg)) { PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg); @@ -607,39 +600,32 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { } } } else { - // --- 对CALL指令采用序列化溢出处理逻辑 --- - const PhysicalReg INT_TEMP_REG = PhysicalReg::T6; // 选择一个固定的临时寄存器 - const PhysicalReg FP_TEMP_REG = PhysicalReg::F0; // 为浮点选择一个 + // --- 对于CALL指令,使用修正后的、完全区分类型的序列化逻辑 --- + const PhysicalReg INT_TEMP_REG = PhysicalReg::T6; + const PhysicalReg FP_TEMP_REG = PhysicalReg::F7; auto& operands = instr_ptr->getOperands(); - unsigned arg_count = 0; - // CALL指令的操作数布局:[def_vreg], label, [use_vreg1, use_vreg2, ...] - // 我们需要从标签之后的操作数开始计数 + int int_arg_idx = 0; + int fp_arg_idx = 0; bool label_found = false; - for(const auto& op : operands) { + + for (const auto& op : operands) { if (op->getKind() == MachineOperand::KIND_LABEL) { label_found = true; continue; } if (!label_found) continue; - // 确定参数的最终位置(ABI规定) - int int_arg_idx = 0; - int fp_arg_idx = 0; - auto [type, size] = getTypeAndSize(static_cast(op.get())->getVRegNum()); - // (这部分逻辑可以做得更精确,但为了简化,我们假设参数类型顺序与abi寄存器顺序匹配) - // 这是一个简化的假设,但在很多情况下成立 - if(type == Type::kFloat) { - fp_arg_idx = arg_count; // Simplified logic - } else { - int_arg_idx = arg_count; // Simplified logic - } - unsigned vreg = static_cast(op.get())->getVRegNum(); - if(spilled_vregs.count(vreg)) { - // 1. 从永久溢出槽加载到临时物理寄存器 - RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : RVOpcodes::LD; + auto [type, size] = getTypeAndSize(vreg); + PhysicalReg source_reg; + + if (spilled_vregs.count(vreg)) { PhysicalReg temp_reg = (type == Type::kFloat) ? FP_TEMP_REG : INT_TEMP_REG; + source_reg = temp_reg; + + // --- FIX 1: Correctly choose LW/LD/FLW based on type --- + RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : ((type == Type::kPointer) ? RVOpcodes::LD : RVOpcodes::LW); auto load = std::make_unique(load_op); load->addOperand(std::make_unique(temp_reg)); load->addOperand(std::make_unique( @@ -647,45 +633,47 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { std::make_unique(frame_info.spill_offsets.at(vreg)) )); new_instructions.push_back(std::move(load)); + } else { + source_reg = color_map.at(vreg); + } - // 2. 将临时寄存器的值移动到最终的ABI位置 + if (type == Type::kFloat) { + if (fp_arg_idx < 8) { + auto fmv = std::make_unique(RVOpcodes::FMV_S); + fmv->addOperand(std::make_unique(static_cast(static_cast(PhysicalReg::F10) + fp_arg_idx))); + fmv->addOperand(std::make_unique(source_reg)); + new_instructions.push_back(std::move(fmv)); + } else { + auto store = std::make_unique(RVOpcodes::FSW); + store->addOperand(std::make_unique(source_reg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique((int_arg_idx - 8) * 8 + (fp_arg_idx - 8) * 4) // Simplified offset + )); + new_instructions.push_back(std::move(store)); + } + fp_arg_idx++; + } else { if (int_arg_idx < 8) { auto mv = std::make_unique(RVOpcodes::MV); mv->addOperand(std::make_unique(static_cast(static_cast(PhysicalReg::A0) + int_arg_idx))); - mv->addOperand(std::make_unique(temp_reg)); + mv->addOperand(std::make_unique(source_reg)); new_instructions.push_back(std::move(mv)); } else { - // 对于栈传递的参数,需要一个pass来提前分配caller的栈帧空间 - // 这里我们假设之前的pass已经处理好了sp的偏移 - auto store = std::make_unique(RVOpcodes::SD); - store->addOperand(std::make_unique(temp_reg)); + // --- FIX 2: Correctly choose SW/SD based on type --- + RVOpcodes store_op = (type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW; + auto store = std::make_unique(store_op); + store->addOperand(std::make_unique(source_reg)); store->addOperand(std::make_unique( std::make_unique(PhysicalReg::SP), - std::make_unique((int_arg_idx - 8) * 8) - )); - new_instructions.push_back(std::move(store)); - } - } else { // 如果参数未溢出 - PhysicalReg colored_reg = color_map.at(vreg); - if(int_arg_idx < 8) { - auto mv = std::make_unique(RVOpcodes::MV); - mv->addOperand(std::make_unique(static_cast(static_cast(PhysicalReg::A0) + int_arg_idx))); - mv->addOperand(std::make_unique(colored_reg)); - new_instructions.push_back(std::move(mv)); - } else { - auto store = std::make_unique(RVOpcodes::SD); - store->addOperand(std::make_unique(colored_reg)); - store->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique((int_arg_idx - 8) * 8) + std::make_unique((int_arg_idx - 8) * 8) // Simplified offset )); new_instructions.push_back(std::move(store)); } + int_arg_idx++; } - arg_count++; } - // 插入原始的CALL指令(只保留标签) auto new_call = std::make_unique(RVOpcodes::CALL); for(const auto& op : operands) { if(op->getKind() == MachineOperand::KIND_LABEL) { @@ -695,20 +683,20 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { } new_instructions.push_back(std::move(new_call)); - // 处理返回值 if(operands.front()->getKind() == MachineOperand::KIND_REG) { unsigned def_vreg = static_cast(operands.front().get())->getVRegNum(); + auto [type, size] = getTypeAndSize(def_vreg); + PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0; + if(spilled_vregs.count(def_vreg)) { - auto [type, size] = getTypeAndSize(def_vreg); - PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0; PhysicalReg temp_reg = type == Type::kFloat ? FP_TEMP_REG : INT_TEMP_REG; - RVOpcodes store_op = type == Type::kFloat ? RVOpcodes::FSW : RVOpcodes::SD; + // --- FIX 3: Correctly choose SW/SD based on type for storing return value --- + RVOpcodes store_op = (type == Type::kFloat) ? RVOpcodes::FSW : ((type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW); - // 由于返回值在 a0/fa0, 我们需要用一个临时寄存器来存储它,以防 a0/fa0 马上被复用 - auto mv = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); - mv->addOperand(std::make_unique(temp_reg)); - mv->addOperand(std::make_unique(result_reg)); - new_instructions.push_back(std::move(mv)); + auto mv_from_abi = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); + mv_from_abi->addOperand(std::make_unique(temp_reg)); + mv_from_abi->addOperand(std::make_unique(result_reg)); + new_instructions.push_back(std::move(mv_from_abi)); auto store = std::make_unique(store_op); store->addOperand(std::make_unique(temp_reg)); @@ -718,12 +706,10 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { )); new_instructions.push_back(std::move(store)); } else { - auto [type, size] = getTypeAndSize(def_vreg); - PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0; - auto mv = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); - mv->addOperand(std::make_unique(color_map.at(def_vreg))); - mv->addOperand(std::make_unique(result_reg)); - new_instructions.push_back(std::move(mv)); + auto mv_to_dest = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); + mv_to_dest->addOperand(std::make_unique(color_map.at(def_vreg))); + mv_to_dest->addOperand(std::make_unique(result_reg)); + new_instructions.push_back(std::move(mv_to_dest)); } } }