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