From df50eedaeb7a340daf4ce935d452166fae4f8755 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Tue, 5 Aug 2025 01:08:42 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E5=B0=86=E6=B5=AE=E7=82=B9=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=94=B9=E4=B8=BA=E4=B8=8E=E5=BC=80=E5=8F=91=E6=9D=BF?= =?UTF-8?q?=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64ISel.cpp | 83 ++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 21e8e3c..a92171f 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -745,12 +745,83 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(instr)); break; } - case Instruction::kFtoI: { // 浮点 to 整数 (使用硬件指令进行向零截断) - // 直接生成一条带有 rtz 舍入模式的转换指令 - auto instr = std::make_unique(RVOpcodes::FCVT_W_S_RTZ); - 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: { // 浮点取负