diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index f9580f4109316..e1375f05cdecd 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -901,6 +901,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { Imm = selectImm(CurDAG, DL, XLenVT, APF.bitcastToAPInt().getSExtValue(), *Subtarget); + bool HasZdinx = Subtarget->hasStdExtZdinx(); + bool Is64Bit = Subtarget->is64Bit(); unsigned Opc; switch (VT.SimpleTy) { default: @@ -920,8 +922,7 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { // For RV32, we can't move from a GPR, we need to convert instead. This // should only happen for +0.0 and -0.0. assert((Subtarget->is64Bit() || APF.isZero()) && "Unexpected constant"); - bool HasZdinx = Subtarget->hasStdExtZdinx(); - if (Subtarget->is64Bit()) + if (Is64Bit) Opc = HasZdinx ? RISCV::COPY : RISCV::FMV_D_X; else Opc = HasZdinx ? RISCV::FCVT_D_W_IN32X : RISCV::FCVT_D_W; @@ -937,9 +938,13 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { Res = CurDAG->getMachineNode(Opc, DL, VT, Imm); // For f64 -0.0, we need to insert a fneg.d idiom. - if (NegZeroF64) - Res = CurDAG->getMachineNode(RISCV::FSGNJN_D, DL, VT, SDValue(Res, 0), - SDValue(Res, 0)); + if (NegZeroF64) { + Opc = RISCV::FSGNJN_D; + if (HasZdinx) + Opc = Is64Bit ? RISCV::FSGNJN_D_INX : RISCV::FSGNJN_D_IN32X; + Res = + CurDAG->getMachineNode(Opc, DL, VT, SDValue(Res, 0), SDValue(Res, 0)); + } ReplaceNode(Node, Res); return; diff --git a/llvm/test/CodeGen/RISCV/double-imm.ll b/llvm/test/CodeGen/RISCV/double-imm.ll index dd554a8ce0dcf..9254369baf19f 100644 --- a/llvm/test/CodeGen/RISCV/double-imm.ll +++ b/llvm/test/CodeGen/RISCV/double-imm.ll @@ -1,19 +1,25 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ -; RUN: -target-abi=ilp32d | FileCheck %s +; RUN: -target-abi=ilp32d | FileCheck %s --check-prefix=CHECK32D ; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ -; RUN: -target-abi=lp64d | FileCheck %s +; RUN: -target-abi=lp64d | FileCheck %s --check-prefix=CHECK64D ; RUN: llc -mtriple=riscv32 -mattr=+zdinx -verify-machineinstrs < %s \ ; RUN: -target-abi=ilp32 | FileCheck --check-prefix=CHECKRV32ZDINX %s ; RUN: llc -mtriple=riscv64 -mattr=+zdinx -verify-machineinstrs < %s \ ; RUN: -target-abi=lp64 | FileCheck --check-prefix=CHECKRV64ZDINX %s define double @double_imm() nounwind { -; CHECK-LABEL: double_imm: -; CHECK: # %bb.0: -; CHECK-NEXT: lui a0, %hi(.LCPI0_0) -; CHECK-NEXT: fld fa0, %lo(.LCPI0_0)(a0) -; CHECK-NEXT: ret +; CHECK32D-LABEL: double_imm: +; CHECK32D: # %bb.0: +; CHECK32D-NEXT: lui a0, %hi(.LCPI0_0) +; CHECK32D-NEXT: fld fa0, %lo(.LCPI0_0)(a0) +; CHECK32D-NEXT: ret +; +; CHECK64D-LABEL: double_imm: +; CHECK64D: # %bb.0: +; CHECK64D-NEXT: lui a0, %hi(.LCPI0_0) +; CHECK64D-NEXT: fld fa0, %lo(.LCPI0_0)(a0) +; CHECK64D-NEXT: ret ; ; CHECKRV32ZDINX-LABEL: double_imm: ; CHECKRV32ZDINX: # %bb.0: @@ -32,12 +38,19 @@ define double @double_imm() nounwind { } define double @double_imm_op(double %a) nounwind { -; CHECK-LABEL: double_imm_op: -; CHECK: # %bb.0: -; CHECK-NEXT: lui a0, %hi(.LCPI1_0) -; CHECK-NEXT: fld fa5, %lo(.LCPI1_0)(a0) -; CHECK-NEXT: fadd.d fa0, fa0, fa5 -; CHECK-NEXT: ret +; CHECK32D-LABEL: double_imm_op: +; CHECK32D: # %bb.0: +; CHECK32D-NEXT: lui a0, %hi(.LCPI1_0) +; CHECK32D-NEXT: fld fa5, %lo(.LCPI1_0)(a0) +; CHECK32D-NEXT: fadd.d fa0, fa0, fa5 +; CHECK32D-NEXT: ret +; +; CHECK64D-LABEL: double_imm_op: +; CHECK64D: # %bb.0: +; CHECK64D-NEXT: lui a0, %hi(.LCPI1_0) +; CHECK64D-NEXT: fld fa5, %lo(.LCPI1_0)(a0) +; CHECK64D-NEXT: fadd.d fa0, fa0, fa5 +; CHECK64D-NEXT: ret ; ; CHECKRV32ZDINX-LABEL: double_imm_op: ; CHECKRV32ZDINX: # %bb.0: @@ -68,6 +81,16 @@ define double @double_imm_op(double %a) nounwind { } define double @double_positive_zero(ptr %pd) nounwind { +; CHECK32D-LABEL: double_positive_zero: +; CHECK32D: # %bb.0: +; CHECK32D-NEXT: fcvt.d.w fa0, zero +; CHECK32D-NEXT: ret +; +; CHECK64D-LABEL: double_positive_zero: +; CHECK64D: # %bb.0: +; CHECK64D-NEXT: fmv.d.x fa0, zero +; CHECK64D-NEXT: ret +; ; CHECKRV32ZDINX-LABEL: double_positive_zero: ; CHECKRV32ZDINX: # %bb.0: ; CHECKRV32ZDINX-NEXT: li a0, 0 @@ -82,6 +105,18 @@ define double @double_positive_zero(ptr %pd) nounwind { } define double @double_negative_zero(ptr %pd) nounwind { +; CHECK32D-LABEL: double_negative_zero: +; CHECK32D: # %bb.0: +; CHECK32D-NEXT: fcvt.d.w fa5, zero +; CHECK32D-NEXT: fneg.d fa0, fa5 +; CHECK32D-NEXT: ret +; +; CHECK64D-LABEL: double_negative_zero: +; CHECK64D: # %bb.0: +; CHECK64D-NEXT: fmv.d.x fa5, zero +; CHECK64D-NEXT: fneg.d fa0, fa5 +; CHECK64D-NEXT: ret +; ; CHECKRV32ZDINX-LABEL: double_negative_zero: ; CHECKRV32ZDINX: # %bb.0: ; CHECKRV32ZDINX-NEXT: lui a1, 524288 @@ -95,3 +130,61 @@ define double @double_negative_zero(ptr %pd) nounwind { ; CHECKRV64ZDINX-NEXT: ret ret double -0.0 } +define dso_local double @negzero_sel(i16 noundef %a, double noundef %d) nounwind { +; CHECK32D-LABEL: negzero_sel: +; CHECK32D: # %bb.0: # %entry +; CHECK32D-NEXT: slli a0, a0, 16 +; CHECK32D-NEXT: fcvt.d.w fa5, zero +; CHECK32D-NEXT: beqz a0, .LBB4_2 +; CHECK32D-NEXT: # %bb.1: # %entry +; CHECK32D-NEXT: fneg.d fa0, fa5 +; CHECK32D-NEXT: .LBB4_2: # %entry +; CHECK32D-NEXT: ret +; +; CHECK64D-LABEL: negzero_sel: +; CHECK64D: # %bb.0: # %entry +; CHECK64D-NEXT: slli a0, a0, 48 +; CHECK64D-NEXT: beqz a0, .LBB4_2 +; CHECK64D-NEXT: # %bb.1: # %entry +; CHECK64D-NEXT: fmv.d.x fa5, zero +; CHECK64D-NEXT: fneg.d fa0, fa5 +; CHECK64D-NEXT: .LBB4_2: # %entry +; CHECK64D-NEXT: ret +; +; CHECKRV32ZDINX-LABEL: negzero_sel: +; CHECKRV32ZDINX: # %bb.0: # %entry +; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 +; CHECKRV32ZDINX-NEXT: sw a1, 8(sp) +; CHECKRV32ZDINX-NEXT: sw a2, 12(sp) +; CHECKRV32ZDINX-NEXT: slli a2, a0, 16 +; CHECKRV32ZDINX-NEXT: fcvt.d.w a0, zero +; CHECKRV32ZDINX-NEXT: beqz a2, .LBB4_2 +; CHECKRV32ZDINX-NEXT: # %bb.1: # %entry +; CHECKRV32ZDINX-NEXT: fneg.d a0, a0 +; CHECKRV32ZDINX-NEXT: j .LBB4_3 +; CHECKRV32ZDINX-NEXT: .LBB4_2: +; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) +; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) +; CHECKRV32ZDINX-NEXT: .LBB4_3: # %entry +; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) +; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) +; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) +; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) +; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 +; CHECKRV32ZDINX-NEXT: ret +; +; CHECKRV64ZDINX-LABEL: negzero_sel: +; CHECKRV64ZDINX: # %bb.0: # %entry +; CHECKRV64ZDINX-NEXT: slli a2, a0, 48 +; CHECKRV64ZDINX-NEXT: beqz a2, .LBB4_2 +; CHECKRV64ZDINX-NEXT: # %bb.1: # %entry +; CHECKRV64ZDINX-NEXT: fneg.d a0, zero +; CHECKRV64ZDINX-NEXT: ret +; CHECKRV64ZDINX-NEXT: .LBB4_2: +; CHECKRV64ZDINX-NEXT: mv a0, a1 +; CHECKRV64ZDINX-NEXT: ret +entry: + %tobool.not = icmp eq i16 %a, 0 + %d. = select i1 %tobool.not, double %d, double -0.000000e+00 + ret double %d. +}