[llvm] [RISCV][GISel] Optimize +0.0 to use fcvt.d.w for s64 on rv32 (PR #153978)
Shaoce SUN via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 16 14:29:06 PDT 2025
https://github.com/sunshaoce updated https://github.com/llvm/llvm-project/pull/153978
>From fac73445d32d674440630e6aa181c2b90c9a2d7d Mon Sep 17 00:00:00 2001
From: Shao-Ce SUN <sunshaoce at outlook.com>
Date: Sun, 17 Aug 2025 04:51:00 +0800
Subject: [PATCH] [RISCV][GISel] Optimize +0.0 to use fcvt.d.w for s64 on rv32
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 15 +++++-
.../CodeGen/RISCV/GlobalISel/double-arith.ll | 48 ++++---------------
.../instruction-select/fp-constant.mir | 6 +--
3 files changed, 24 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index f83c2b6da8923..51ea3fc5f6774 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -736,7 +736,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
}
case TargetOpcode::G_FCONSTANT: {
// TODO: Use constant pool for complex constants.
- // TODO: Optimize +0.0 to use fcvt.d.w for s64 on rv32.
Register DstReg = MI.getOperand(0).getReg();
const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
APInt Imm = FPimm.bitcastToAPInt();
@@ -753,8 +752,22 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
if (!FMV.constrainAllUses(TII, TRI, RBI))
return false;
} else {
+ // s64 on rv32
assert(Size == 64 && !Subtarget->is64Bit() &&
"Unexpected size or subtarget");
+
+ if (Imm.isNonNegative() && Imm.isZero()) {
+ // Optimize +0.0 to use fcvt.d.w
+ MachineInstrBuilder FCVT =
+ MIB.buildInstr(RISCV::FCVT_D_W, {DstReg}, {Register(RISCV::X0)})
+ .addImm(RISCVFPRndMode::RNE);
+ if (!FCVT.constrainAllUses(TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+
// Split into two pieces and build through the stack.
Register GPRRegHigh = MRI->createVirtualRegister(&RISCV::GPRRegClass);
Register GPRRegLow = MRI->createVirtualRegister(&RISCV::GPRRegClass);
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/double-arith.ll b/llvm/test/CodeGen/RISCV/GlobalISel/double-arith.ll
index cb2037f5fb027..4eb7646d13a39 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/double-arith.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/double-arith.ll
@@ -395,13 +395,9 @@ define double @fmadd_d(double %a, double %b, double %c) nounwind {
define double @fmsub_d(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fmsub_d:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa5, fa2, fa5
; RV32IFD-NEXT: fmsub.d fa0, fa0, fa1, fa5
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fmsub_d:
@@ -478,14 +474,10 @@ define double @fmsub_d(double %a, double %b, double %c) nounwind {
define double @fnmadd_d(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmadd_d:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa4, fa0, fa5
; RV32IFD-NEXT: fadd.d fa5, fa2, fa5
; RV32IFD-NEXT: fnmadd.d fa0, fa4, fa1, fa5
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmadd_d:
@@ -590,14 +582,10 @@ define double @fnmadd_d(double %a, double %b, double %c) nounwind {
define double @fnmadd_d_2(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmadd_d_2:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa4, fa1, fa5
; RV32IFD-NEXT: fadd.d fa5, fa2, fa5
; RV32IFD-NEXT: fnmadd.d fa0, fa4, fa0, fa5
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmadd_d_2:
@@ -772,13 +760,9 @@ define double @fnmadd_nsz(double %a, double %b, double %c) nounwind {
define double @fnmsub_d(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmsub_d:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa5, fa0, fa5
; RV32IFD-NEXT: fnmsub.d fa0, fa5, fa1, fa2
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmsub_d:
@@ -851,13 +835,9 @@ define double @fnmsub_d(double %a, double %b, double %c) nounwind {
define double @fnmsub_d_2(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmsub_d_2:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa5, fa1, fa5
; RV32IFD-NEXT: fnmsub.d fa0, fa5, fa0, fa2
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmsub_d_2:
@@ -976,14 +956,10 @@ define double @fmadd_d_contract(double %a, double %b, double %c) nounwind {
define double @fmsub_d_contract(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fmsub_d_contract:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa5, fa2, fa5
; RV32IFD-NEXT: fmul.d fa4, fa0, fa1
; RV32IFD-NEXT: fsub.d fa0, fa4, fa5
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fmsub_d_contract:
@@ -1069,17 +1045,13 @@ define double @fmsub_d_contract(double %a, double %b, double %c) nounwind {
define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmadd_d_contract:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa4, fa0, fa5
; RV32IFD-NEXT: fadd.d fa3, fa1, fa5
; RV32IFD-NEXT: fadd.d fa5, fa2, fa5
; RV32IFD-NEXT: fmul.d fa4, fa4, fa3
; RV32IFD-NEXT: fneg.d fa4, fa4
; RV32IFD-NEXT: fsub.d fa0, fa4, fa5
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmadd_d_contract:
@@ -1204,14 +1176,10 @@ define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind {
define double @fnmsub_d_contract(double %a, double %b, double %c) nounwind {
; RV32IFD-LABEL: fnmsub_d_contract:
; RV32IFD: # %bb.0:
-; RV32IFD-NEXT: addi sp, sp, -16
-; RV32IFD-NEXT: sw zero, 8(sp)
-; RV32IFD-NEXT: sw zero, 12(sp)
-; RV32IFD-NEXT: fld fa5, 8(sp)
+; RV32IFD-NEXT: fcvt.d.w fa5, zero
; RV32IFD-NEXT: fadd.d fa4, fa0, fa5
; RV32IFD-NEXT: fadd.d fa5, fa1, fa5
; RV32IFD-NEXT: fnmsub.d fa0, fa4, fa5, fa2
-; RV32IFD-NEXT: addi sp, sp, 16
; RV32IFD-NEXT: ret
;
; RV64IFD-LABEL: fnmsub_d_contract:
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir
index e82d4bcec48b1..4db80c6c1141f 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/fp-constant.mir
@@ -164,10 +164,8 @@ body: |
; RV32-LABEL: name: double_positive_zero
; RV32: liveins: $x10
; RV32-NEXT: {{ $}}
- ; RV32-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
- ; RV32-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
- ; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY1]], [[COPY]]
- ; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
+ ; RV32-NEXT: [[FCVT_D_W:%[0-9]+]]:fpr64 = FCVT_D_W $x0, 0
+ ; RV32-NEXT: $f10_d = COPY [[FCVT_D_W]]
; RV32-NEXT: PseudoRET implicit $f10_d
;
; RV64-LABEL: name: double_positive_zero
More information about the llvm-commits
mailing list