[llvm] r352247 - [RISCV] Add target DAG combine for bitcast fabs/fneg on RV32FD

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 25 13:55:48 PST 2019


Author: asb
Date: Fri Jan 25 13:55:48 2019
New Revision: 352247

URL: http://llvm.org/viewvc/llvm-project?rev=352247&view=rev
Log:
[RISCV] Add target DAG combine for bitcast fabs/fneg on RV32FD

DAGCombiner::visitBITCAST will perform:
 fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
 fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))

As shown in double-bitmanip-dagcombines.ll, this can be advantageous. But
RV32FD doesn't use bitcast directly (as i64 isn't a legal type), and instead
uses RISCVISD::SplitF64. This patch adds an equivalent DAG combine for
SplitF64.


Modified:
    llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/trunk/test/CodeGen/RISCV/double-arith.ll
    llvm/trunk/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
    llvm/trunk/test/CodeGen/RISCV/double-intrinsics.ll

Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp?rev=352247&r1=352246&r2=352247&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp Fri Jan 25 13:55:48 2019
@@ -584,16 +584,41 @@ void RISCVTargetLowering::ReplaceNodeRes
 
 SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
                                                DAGCombinerInfo &DCI) const {
+  SelectionDAG &DAG = DCI.DAG;
+
   switch (N->getOpcode()) {
   default:
     break;
   case RISCVISD::SplitF64: {
+    SDValue Op0 = N->getOperand(0);
     // If the input to SplitF64 is just BuildPairF64 then the operation is
     // redundant. Instead, use BuildPairF64's operands directly.
-    SDValue Op0 = N->getOperand(0);
-    if (Op0->getOpcode() != RISCVISD::BuildPairF64)
+    if (Op0->getOpcode() == RISCVISD::BuildPairF64)
+      return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
+
+    SDLoc DL(N);
+    // This is a target-specific version of a DAGCombine performed in
+    // DAGCombiner::visitBITCAST. It performs the equivalent of:
+    // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
+    // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
+    if (!(Op0.getOpcode() == ISD::FNEG || Op0.getOpcode() == ISD::FABS) ||
+        !Op0.getNode()->hasOneUse())
       break;
-    return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
+    SDValue NewSplitF64 =
+        DAG.getNode(RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32),
+                    Op0.getOperand(0));
+    SDValue Lo = NewSplitF64.getValue(0);
+    SDValue Hi = NewSplitF64.getValue(1);
+    APInt SignBit = APInt::getSignMask(32);
+    if (Op0.getOpcode() == ISD::FNEG) {
+      SDValue NewHi = DAG.getNode(ISD::XOR, DL, MVT::i32, Hi,
+                                  DAG.getConstant(SignBit, DL, MVT::i32));
+      return DCI.CombineTo(N, Lo, NewHi);
+    }
+    assert(Op0.getOpcode() == ISD::FABS);
+    SDValue NewHi = DAG.getNode(ISD::AND, DL, MVT::i32, Hi,
+                                DAG.getConstant(~SignBit, DL, MVT::i32));
+    return DCI.CombineTo(N, Lo, NewHi);
   }
   case RISCVISD::SLLW:
   case RISCVISD::SRAW:

Modified: llvm/trunk/test/CodeGen/RISCV/double-arith.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/double-arith.ll?rev=352247&r1=352246&r2=352247&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/double-arith.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/double-arith.ll Fri Jan 25 13:55:48 2019
@@ -127,21 +127,25 @@ define double @fsgnj_d(double %a, double
   ret double %1
 }
 
-define double @fneg_d(double %a) nounwind {
+; This function performs extra work to ensure that
+; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
+define i32 @fneg_d(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: fneg_d:
 ; RV32IFD:       # %bb.0:
 ; RV32IFD-NEXT:    addi sp, sp, -16
 ; RV32IFD-NEXT:    sw a0, 8(sp)
 ; RV32IFD-NEXT:    sw a1, 12(sp)
 ; RV32IFD-NEXT:    fld ft0, 8(sp)
-; RV32IFD-NEXT:    fneg.d ft0, ft0
-; RV32IFD-NEXT:    fsd ft0, 8(sp)
-; RV32IFD-NEXT:    lw a0, 8(sp)
-; RV32IFD-NEXT:    lw a1, 12(sp)
+; RV32IFD-NEXT:    fadd.d ft0, ft0, ft0
+; RV32IFD-NEXT:    fneg.d ft1, ft0
+; RV32IFD-NEXT:    feq.d a0, ft0, ft1
 ; RV32IFD-NEXT:    addi sp, sp, 16
 ; RV32IFD-NEXT:    ret
-  %1 = fsub double -0.0, %a
-  ret double %1
+  %1 = fadd double %a, %a
+  %2 = fneg double %1
+  %3 = fcmp oeq double %1, %2
+  %4 = zext i1 %3 to i32
+  ret i32 %4
 }
 
 define double @fsgnjn_d(double %a, double %b) nounwind {
@@ -167,21 +171,30 @@ define double @fsgnjn_d(double %a, doubl
 
 declare double @llvm.fabs.f64(double)
 
-define double @fabs_d(double %a) nounwind {
+; This function performs extra work to ensure that
+; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
+define double @fabs_d(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: fabs_d:
 ; RV32IFD:       # %bb.0:
 ; RV32IFD-NEXT:    addi sp, sp, -16
+; RV32IFD-NEXT:    sw a2, 8(sp)
+; RV32IFD-NEXT:    sw a3, 12(sp)
+; RV32IFD-NEXT:    fld ft0, 8(sp)
 ; RV32IFD-NEXT:    sw a0, 8(sp)
 ; RV32IFD-NEXT:    sw a1, 12(sp)
-; RV32IFD-NEXT:    fld ft0, 8(sp)
-; RV32IFD-NEXT:    fabs.d ft0, ft0
+; RV32IFD-NEXT:    fld ft1, 8(sp)
+; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
+; RV32IFD-NEXT:    fabs.d ft1, ft0
+; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
 ; RV32IFD-NEXT:    fsd ft0, 8(sp)
 ; RV32IFD-NEXT:    lw a0, 8(sp)
 ; RV32IFD-NEXT:    lw a1, 12(sp)
 ; RV32IFD-NEXT:    addi sp, sp, 16
 ; RV32IFD-NEXT:    ret
-  %1 = call double @llvm.fabs.f64(double %a)
-  ret double %1
+  %1 = fadd double %a, %b
+  %2 = call double @llvm.fabs.f64(double %1)
+  %3 = fadd double %2, %1
+  ret double %3
 }
 
 declare double @llvm.minnum.f64(double, double)

Modified: llvm/trunk/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll?rev=352247&r1=352246&r2=352247&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll Fri Jan 25 13:55:48 2019
@@ -24,15 +24,8 @@ define double @fneg(double %a) nounwind
 ;
 ; RV32IFD-LABEL: fneg:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    addi sp, sp, -16
-; RV32IFD-NEXT:    sw a0, 8(sp)
-; RV32IFD-NEXT:    sw a1, 12(sp)
-; RV32IFD-NEXT:    fld ft0, 8(sp)
-; RV32IFD-NEXT:    fneg.d ft0, ft0
-; RV32IFD-NEXT:    fsd ft0, 8(sp)
-; RV32IFD-NEXT:    lw a0, 8(sp)
-; RV32IFD-NEXT:    lw a1, 12(sp)
-; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    lui a2, 524288
+; RV32IFD-NEXT:    xor a1, a1, a2
 ; RV32IFD-NEXT:    ret
 ;
 ; RV64I-LABEL: fneg:
@@ -57,15 +50,9 @@ define double @fabs(double %a) nounwind
 ;
 ; RV32IFD-LABEL: fabs:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    addi sp, sp, -16
-; RV32IFD-NEXT:    sw a0, 8(sp)
-; RV32IFD-NEXT:    sw a1, 12(sp)
-; RV32IFD-NEXT:    fld ft0, 8(sp)
-; RV32IFD-NEXT:    fabs.d ft0, ft0
-; RV32IFD-NEXT:    fsd ft0, 8(sp)
-; RV32IFD-NEXT:    lw a0, 8(sp)
-; RV32IFD-NEXT:    lw a1, 12(sp)
-; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    lui a2, 524288
+; RV32IFD-NEXT:    addi a2, a2, -1
+; RV32IFD-NEXT:    and a1, a1, a2
 ; RV32IFD-NEXT:    ret
 ;
 ; RV64I-LABEL: fabs:

Modified: llvm/trunk/test/CodeGen/RISCV/double-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/double-intrinsics.ll?rev=352247&r1=352246&r2=352247&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/double-intrinsics.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/double-intrinsics.ll Fri Jan 25 13:55:48 2019
@@ -254,15 +254,9 @@ declare double @llvm.fabs.f64(double)
 define double @fabs_f64(double %a) nounwind {
 ; RV32IFD-LABEL: fabs_f64:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    addi sp, sp, -16
-; RV32IFD-NEXT:    sw a0, 8(sp)
-; RV32IFD-NEXT:    sw a1, 12(sp)
-; RV32IFD-NEXT:    fld ft0, 8(sp)
-; RV32IFD-NEXT:    fabs.d ft0, ft0
-; RV32IFD-NEXT:    fsd ft0, 8(sp)
-; RV32IFD-NEXT:    lw a0, 8(sp)
-; RV32IFD-NEXT:    lw a1, 12(sp)
-; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    lui a2, 524288
+; RV32IFD-NEXT:    addi a2, a2, -1
+; RV32IFD-NEXT:    and a1, a1, a2
 ; RV32IFD-NEXT:    ret
   %1 = call double @llvm.fabs.f64(double %a)
   ret double %1




More information about the llvm-commits mailing list