[llvm] 563720c - [RISCV] Fix lowering of negative zero with Zdinx 32-bit (#71869)

via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 12 22:38:18 PST 2023


Author: Nemanja Ivanovic
Date: 2023-11-13T07:38:14+01:00
New Revision: 563720c3bed42a9ce042ba3f334793b5b4373acf

URL: https://github.com/llvm/llvm-project/commit/563720c3bed42a9ce042ba3f334793b5b4373acf
DIFF: https://github.com/llvm/llvm-project/commit/563720c3bed42a9ce042ba3f334793b5b4373acf.diff

LOG: [RISCV] Fix lowering of negative zero with Zdinx 32-bit (#71869)

The compiler currently abends with an impossible reg-to-reg copy when
producing a negative zero FP immediate on RV32 with -Zdinx. This is
because we emit a negation that uses FP registers. Emit the right node
to produce correct code.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/test/CodeGen/RISCV/double-imm.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index f9580f410931612..e1375f05cdecdc7 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 dd554a8ce0dcf74..9254369baf19f3d 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.
+}


        


More information about the llvm-commits mailing list