[llvm] 3b80d02 - DAG: Look through fneg when trying to create unsafe minnum/maxnum

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 23 02:07:29 PST 2023


Author: Matt Arsenault
Date: 2023-01-23T06:07:22-04:00
New Revision: 3b80d02992892c34c5d0860efb764d8f11352dec

URL: https://github.com/llvm/llvm-project/commit/3b80d02992892c34c5d0860efb764d8f11352dec
DIFF: https://github.com/llvm/llvm-project/commit/3b80d02992892c34c5d0860efb764d8f11352dec.diff

LOG: DAG: Look through fneg when trying to create unsafe minnum/maxnum

This makes most sense for isFNegFree targets, but shouldn't make
things worse without it. This avoids AMDGPU test regressions in a
future patch.

For some reason APFloat::compareAbsoluteValue is private, so compute
the neg of the constants.

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 42f6221e402f..8c87fc4acd3a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10346,14 +10346,11 @@ static bool isLegalToCombineMinNumMaxNum(SelectionDAG &DAG, SDValue LHS,
          DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS);
 }
 
-/// Generate Min/Max node
-static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
-                                   SDValue RHS, SDValue True, SDValue False,
-                                   ISD::CondCode CC, const TargetLowering &TLI,
-                                   SelectionDAG &DAG) {
-  if (!(LHS == True && RHS == False) && !(LHS == False && RHS == True))
-    return SDValue();
-
+static SDValue combineMinNumMaxNumImpl(const SDLoc &DL, EVT VT, SDValue LHS,
+                                       SDValue RHS, SDValue True, SDValue False,
+                                       ISD::CondCode CC,
+                                       const TargetLowering &TLI,
+                                       SelectionDAG &DAG) {
   EVT TransformVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
   switch (CC) {
   case ISD::SETOLT:
@@ -10394,6 +10391,43 @@ static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
   }
 }
 
+/// Generate Min/Max node
+static SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
+                                   SDValue RHS, SDValue True, SDValue False,
+                                   ISD::CondCode CC, const TargetLowering &TLI,
+                                   SelectionDAG &DAG) {
+  if ((LHS == True && RHS == False) || (LHS == False && RHS == True))
+    return combineMinNumMaxNumImpl(DL, VT, LHS, RHS, True, False, CC, TLI, DAG);
+
+  // If we can't directly match this, try to see if we can pull an fneg out of
+  // the select.
+  if (True.getOpcode() != ISD::FNEG)
+    return SDValue();
+
+  ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
+  ConstantFPSDNode *CFalse = dyn_cast<ConstantFPSDNode>(False);
+  SDValue NegTrue = True.getOperand(0);
+
+  // Try to unfold an fneg from the select if we are comparing the negated
+  // constant.
+  //
+  // select (setcc x, K) (fneg x), -K -> fneg(minnum(x, K))
+  //
+  // TODO: Handle fabs
+  if (LHS == NegTrue && CFalse && CRHS) {
+    APFloat NegRHS = neg(CRHS->getValueAPF());
+    if (NegRHS == CFalse->getValueAPF()) {
+      SDValue Combined = combineMinNumMaxNumImpl(DL, VT, LHS, RHS, NegTrue,
+                                                 False, CC, TLI, DAG);
+      if (Combined)
+        return DAG.getNode(ISD::FNEG, DL, VT, Combined);
+      return SDValue();
+    }
+  }
+
+  return SDValue();
+}
+
 /// If a (v)select has a condition value that is a sign-bit test, try to smear
 /// the condition operand sign-bit across the value width and use it as a mask.
 static SDValue foldSelectOfConstantsUsingSra(SDNode *N, SelectionDAG &DAG) {

diff  --git a/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll b/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
index d18295fc0132..23fdf0708470 100644
--- a/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
+++ b/llvm/test/CodeGen/ARM/unsafe-fneg-select-minnum-maxnum-combine.ll
@@ -6,12 +6,9 @@ define float @select_fneg_a_or_8_cmp_olt_a_neg8_f32(float %a, float %b) #0 {
 ; CHECK:       @ %bb.0:
 ; CHECK-NEXT:    vmov.f32 s0, #-8.000000e+00
 ; CHECK-NEXT:    vmov s2, r0
-; CHECK-NEXT:    vmov.f32 s4, #8.000000e+00
-; CHECK-NEXT:    vneg.f32 s6, s2
-; CHECK-NEXT:    vcmp.f32 s0, s2
-; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
-; CHECK-NEXT:    vselgt.f32 s0, s6, s4
+; CHECK-NEXT:    vminnm.f32 s0, s2, s0
 ; CHECK-NEXT:    vmov r0, s0
+; CHECK-NEXT:    eor r0, r0, #-2147483648
 ; CHECK-NEXT:    mov pc, lr
   %fneg.a = fneg nnan nsz float %a
   %cmp.a = fcmp nnan nsz olt float %a, -8.0
@@ -22,13 +19,10 @@ define float @select_fneg_a_or_8_cmp_olt_a_neg8_f32(float %a, float %b) #0 {
 define half @select_fneg_a_or_8_cmp_olt_a_neg8_f16(half %a, half %b) #0 {
 ; CHECK-LABEL: select_fneg_a_or_8_cmp_olt_a_neg8_f16:
 ; CHECK:       @ %bb.0:
-; CHECK-NEXT:    vmov.f16 s4, r0
 ; CHECK-NEXT:    vmov.f16 s0, #-8.000000e+00
-; CHECK-NEXT:    vcmp.f16 s0, s4
-; CHECK-NEXT:    vmov.f16 s2, #8.000000e+00
-; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
-; CHECK-NEXT:    vneg.f16 s6, s4
-; CHECK-NEXT:    vselgt.f16 s0, s6, s2
+; CHECK-NEXT:    vmov.f16 s2, r0
+; CHECK-NEXT:    vminnm.f16 s0, s2, s0
+; CHECK-NEXT:    vneg.f16 s0, s0
 ; CHECK-NEXT:    vmov r0, s0
 ; CHECK-NEXT:    mov pc, lr
   %fneg.a = fneg nnan nsz half %a
@@ -42,12 +36,9 @@ define float @select_fneg_a_or_8_cmp_ogt_a_neg8_f32(float %a, float %b) #0 {
 ; CHECK:       @ %bb.0:
 ; CHECK-NEXT:    vmov.f32 s0, #-8.000000e+00
 ; CHECK-NEXT:    vmov s2, r0
-; CHECK-NEXT:    vmov.f32 s4, #8.000000e+00
-; CHECK-NEXT:    vneg.f32 s6, s2
-; CHECK-NEXT:    vcmp.f32 s2, s0
-; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
-; CHECK-NEXT:    vselgt.f32 s0, s6, s4
+; CHECK-NEXT:    vmaxnm.f32 s0, s2, s0
 ; CHECK-NEXT:    vmov r0, s0
+; CHECK-NEXT:    eor r0, r0, #-2147483648
 ; CHECK-NEXT:    mov pc, lr
   %fneg.a = fneg nnan nsz float %a
   %cmp.a = fcmp nnan nsz ogt float %a, -8.0
@@ -58,13 +49,10 @@ define float @select_fneg_a_or_8_cmp_ogt_a_neg8_f32(float %a, float %b) #0 {
 define half @select_fneg_a_or_8_cmp_ogt_a_neg8_f16(half %a, half %b) #0 {
 ; CHECK-LABEL: select_fneg_a_or_8_cmp_ogt_a_neg8_f16:
 ; CHECK:       @ %bb.0:
-; CHECK-NEXT:    vmov.f16 s4, r0
 ; CHECK-NEXT:    vmov.f16 s0, #-8.000000e+00
-; CHECK-NEXT:    vcmp.f16 s4, s0
-; CHECK-NEXT:    vmov.f16 s2, #8.000000e+00
-; CHECK-NEXT:    vmrs APSR_nzcv, fpscr
-; CHECK-NEXT:    vneg.f16 s6, s4
-; CHECK-NEXT:    vselgt.f16 s0, s6, s2
+; CHECK-NEXT:    vmov.f16 s2, r0
+; CHECK-NEXT:    vmaxnm.f16 s0, s2, s0
+; CHECK-NEXT:    vneg.f16 s0, s0
 ; CHECK-NEXT:    vmov r0, s0
 ; CHECK-NEXT:    mov pc, lr
   %fneg.a = fneg nnan nsz half %a


        


More information about the llvm-commits mailing list