From b2c2f3289dfb4195847bb0588e3cfff55a0782a6 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Mon, 4 Aug 2025 01:34:39 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E4=BF=AE=E6=94=B9=E4=BA=86=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E5=90=8E=E7=AB=AF=20RISCv64ISel.cpp=EF=BC=8C?= =?UTF-8?q?=E5=9C=A8=20kFtoI=20=E7=9A=84=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E4=B8=AD=EF=BC=8C=E7=94=A8=E4=B8=80=E6=AE=B5=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=BA=8F=E5=88=97=E6=A8=A1=E6=8B=9F=E4=BA=86=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=E2=80=9C=E5=90=91=E9=9B=B6=E5=8F=96=E6=95=B4?= =?UTF-8?q?=E2=80=9D=E8=A1=8C=E4=B8=BA=E3=80=8295=20h35=20h37=20h38?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64ISel.cpp | 82 +++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 2f7c9ae..4758b37 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -767,11 +767,83 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(instr)); break; } - case Instruction::kFtoI: { // 浮点 to 整数 - auto instr = std::make_unique(RVOpcodes::FCVT_W_S); - instr->addOperand(std::make_unique(dest_vreg)); // 目标是整数vreg - instr->addOperand(std::make_unique(src_vreg)); // 源是浮点vreg - CurMBB->addInstruction(std::move(instr)); + 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()); + + // 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)); + + // 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)); + + // 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)); + + // 创建标签 + 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: { // 浮点取负