From f2477c4af3de86b537fc3732d719f269fc35de20 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Tue, 5 Aug 2025 02:43:46 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E4=BF=AE=E5=A4=8D=E6=B5=AE=E7=82=B9?= =?UTF-8?q?=E6=95=B0=E6=88=AA=E6=96=AD=E9=80=BB=E8=BE=91=20h36=E9=80=9A?= =?UTF-8?q?=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64AsmPrinter.cpp | 1 + src/backend/RISCv64/RISCv64ISel.cpp | 92 +++++------------------ src/include/backend/RISCv64/RISCv64LLIR.h | 3 + 3 files changed, 23 insertions(+), 73 deletions(-) diff --git a/src/backend/RISCv64/RISCv64AsmPrinter.cpp b/src/backend/RISCv64/RISCv64AsmPrinter.cpp index 5a01b8e..c71ce2f 100644 --- a/src/backend/RISCv64/RISCv64AsmPrinter.cpp +++ b/src/backend/RISCv64/RISCv64AsmPrinter.cpp @@ -106,6 +106,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) { case RVOpcodes::FMV_S: *OS << "fmv.s "; break; case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break; case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break; + case RVOpcodes::FSRMI: *OS << "fsrmi "; break; case RVOpcodes::CALL: { // 为CALL指令添加特殊处理逻辑 *OS << "call "; // 遍历所有操作数,只寻找并打印函数名标签 diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index a92171f..0c4a1d0 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -745,83 +745,29 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(instr)); break; } - case Instruction::kFtoI: { // 浮点 to 整数 (带向下取整) - // 目标:实现 floor(x) 的效果, C/C++中浮点转整数是截断(truncate) - // 对于正数,floor(x) == truncate(x) - // RISC-V的 fcvt.w.s 默认是“四舍五入到偶数” - // 我们需要手动实现截断逻辑 - // 逻辑: - // temp_i = fcvt.w.s(x) // 四舍五入 - // temp_f = fcvt.s.w(temp_i) // 转回浮点 - // if (x < temp_f) { // 如果原数更小,说明被“五入”了 - // result = temp_i - 1 - // } else { - // result = temp_i - // } - - auto temp_i_vreg = getNewVReg(Type::getIntType()); - auto temp_f_vreg = getNewVReg(Type::getFloatType()); - auto cmp_vreg = getNewVReg(Type::getIntType()); + case Instruction::kFtoI: { // 浮点 to 整数 (C/C++: 截断) + // C/C++ 标准要求向零截断 (truncate), 对应的RISC-V舍入模式是 RTZ (Round Towards Zero). + // fcvt.w.s 指令使用 fcsr 中的 frm 字段来决定舍入模式。 + // 我们需要手动设置 frm=1 (RTZ), 执行转换, 然后恢复 frm=0 (RNE, 默认). - // 1. fcvt.w.s temp_i_vreg, src_vreg - auto fcvt_w = std::make_unique(RVOpcodes::FCVT_W_S); - fcvt_w->addOperand(std::make_unique(temp_i_vreg)); - fcvt_w->addOperand(std::make_unique(src_vreg)); - CurMBB->addInstruction(std::move(fcvt_w)); + // 1. fsrmi x0, 1 (set rounding mode to RTZ) + auto fsrmi1 = std::make_unique(RVOpcodes::FSRMI); + fsrmi1->addOperand(std::make_unique(PhysicalReg::ZERO)); + fsrmi1->addOperand(std::make_unique(1)); + CurMBB->addInstruction(std::move(fsrmi1)); - // 2. fcvt.s.w temp_f_vreg, temp_i_vreg - auto fcvt_s = std::make_unique(RVOpcodes::FCVT_S_W); - fcvt_s->addOperand(std::make_unique(temp_f_vreg)); - fcvt_s->addOperand(std::make_unique(temp_i_vreg)); - CurMBB->addInstruction(std::move(fcvt_s)); + // 2. fcvt.w.s dest_vreg, src_vreg + auto fcvt = std::make_unique(RVOpcodes::FCVT_W_S); + fcvt->addOperand(std::make_unique(dest_vreg)); + fcvt->addOperand(std::make_unique(src_vreg)); + CurMBB->addInstruction(std::move(fcvt)); - // 3. flt.s cmp_vreg, src_vreg, temp_f_vreg - auto flt = std::make_unique(RVOpcodes::FLT_S); - flt->addOperand(std::make_unique(cmp_vreg)); - flt->addOperand(std::make_unique(src_vreg)); - flt->addOperand(std::make_unique(temp_f_vreg)); - CurMBB->addInstruction(std::move(flt)); + // 3. fsrmi x0, 0 (restore rounding mode to RNE) + auto fsrmi0 = std::make_unique(RVOpcodes::FSRMI); + fsrmi0->addOperand(std::make_unique(PhysicalReg::ZERO)); + fsrmi0->addOperand(std::make_unique(0)); + CurMBB->addInstruction(std::move(fsrmi0)); - // 创建标签 - int unique_id = this->local_label_counter++; - std::string rounded_up_label = MFunc->getName() + "_ftoi_rounded_up_" + std::to_string(unique_id); - std::string done_label = MFunc->getName() + "_ftoi_done_" + std::to_string(unique_id); - - // 4. bne cmp_vreg, x0, rounded_up_label - auto bne = std::make_unique(RVOpcodes::BNE); - bne->addOperand(std::make_unique(cmp_vreg)); - bne->addOperand(std::make_unique(PhysicalReg::ZERO)); - bne->addOperand(std::make_unique(rounded_up_label)); - CurMBB->addInstruction(std::move(bne)); - - // 5. else 分支: mv dest_vreg, temp_i_vreg - auto mv = std::make_unique(RVOpcodes::MV); - mv->addOperand(std::make_unique(dest_vreg)); - mv->addOperand(std::make_unique(temp_i_vreg)); - CurMBB->addInstruction(std::move(mv)); - - // 6. j done_label - auto j = std::make_unique(RVOpcodes::J); - j->addOperand(std::make_unique(done_label)); - CurMBB->addInstruction(std::move(j)); - - // 7. rounded_up_label: - auto label_up = std::make_unique(RVOpcodes::LABEL); - label_up->addOperand(std::make_unique(rounded_up_label)); - CurMBB->addInstruction(std::move(label_up)); - - // 8. addiw dest_vreg, temp_i_vreg, -1 - auto addi = std::make_unique(RVOpcodes::ADDIW); - addi->addOperand(std::make_unique(dest_vreg)); - addi->addOperand(std::make_unique(temp_i_vreg)); - addi->addOperand(std::make_unique(-1)); - CurMBB->addInstruction(std::move(addi)); - - // 9. done_label: - auto label_done = std::make_unique(RVOpcodes::LABEL); - label_done->addOperand(std::make_unique(done_label)); - CurMBB->addInstruction(std::move(label_done)); - break; } case Instruction::kFNeg: { // 浮点取负 diff --git a/src/include/backend/RISCv64/RISCv64LLIR.h b/src/include/backend/RISCv64/RISCv64LLIR.h index 977b348..77cdfe3 100644 --- a/src/include/backend/RISCv64/RISCv64LLIR.h +++ b/src/include/backend/RISCv64/RISCv64LLIR.h @@ -96,6 +96,9 @@ enum class RVOpcodes { FMV_X_W, // fmv.x.w rd, rs1 (浮点寄存器位模式 -> 整数寄存器) FNEG_S, // fneg.s rd, rs (浮点取负) + // 浮点控制状态寄存器 (CSR) + FSRMI, // fsrmi rd, imm (设置舍入模式立即数) + // 伪指令 FRAME_LOAD_W, // 从栈帧加载 32位 Word (对应 lw) FRAME_LOAD_D, // 从栈帧加载 64位 Doubleword (对应 ld)