[llvm] r245196 - Generate FMINNAN/FMINNUM/FMAXNAN/FMAXNUM from SDAGBuilder.

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 00:13:10 PDT 2015


Author: jamesm
Date: Mon Aug 17 02:13:10 2015
New Revision: 245196

URL: http://llvm.org/viewvc/llvm-project?rev=245196&view=rev
Log:
Generate FMINNAN/FMINNUM/FMAXNAN/FMAXNUM from SDAGBuilder.

These only get generated if the target supports them. If one of the variants is not legal and the other is, and it is safe to do so, the other variant will be emitted.

For example on AArch32 (V8), we have scalar fminnm but not fmin.

Fix up a couple of tests while we're here - one now produces better code, and the other was just plain wrong to start with.

Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/test/CodeGen/AArch64/arm64-fmax-safe.ll
    llvm/trunk/test/CodeGen/ARM/vminmaxnm.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=245196&r1=245195&r2=245196&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Mon Aug 17 02:13:10 2015
@@ -2297,24 +2297,45 @@ void SelectionDAGBuilder::visitSelect(co
 
   // Min/max matching is only viable if all output VTs are the same.
   if (std::equal(ValueVTs.begin(), ValueVTs.end(), ValueVTs.begin())) {
-    Value *LHS, *RHS;
-    SelectPatternFlavor SPF =
-      matchSelectPattern(const_cast<User*>(&I), LHS, RHS).Flavor;
-    ISD::NodeType Opc = ISD::DELETED_NODE;
-    switch (SPF) {
-    case SPF_UMAX: Opc = ISD::UMAX; break;
-    case SPF_UMIN: Opc = ISD::UMIN; break;
-    case SPF_SMAX: Opc = ISD::SMAX; break;
-    case SPF_SMIN: Opc = ISD::SMIN; break;
-    default: break;
-    }
-
     EVT VT = ValueVTs[0];
     LLVMContext &Ctx = *DAG.getContext();
     auto &TLI = DAG.getTargetLoweringInfo();
     while (TLI.getTypeAction(Ctx, VT) == TargetLoweringBase::TypeSplitVector)
       VT = TLI.getTypeToTransformTo(Ctx, VT);
 
+    Value *LHS, *RHS;
+    auto SPR = matchSelectPattern(const_cast<User*>(&I), LHS, RHS);
+    ISD::NodeType Opc = ISD::DELETED_NODE;
+    switch (SPR.Flavor) {
+    case SPF_UMAX:    Opc = ISD::UMAX; break;
+    case SPF_UMIN:    Opc = ISD::UMIN; break;
+    case SPF_SMAX:    Opc = ISD::SMAX; break;
+    case SPF_SMIN:    Opc = ISD::SMIN; break;
+    case SPF_FMINNUM:
+      switch (SPR.NaNBehavior) {
+      case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
+      case SPNB_RETURNS_NAN:   Opc = ISD::FMINNAN; break;
+      case SPNB_RETURNS_OTHER: Opc = ISD::FMINNUM; break;
+      case SPNB_RETURNS_ANY:
+        Opc = TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT) ? ISD::FMINNUM
+          : ISD::FMINNAN;
+        break;
+      }
+      break;
+    case SPF_FMAXNUM:
+      switch (SPR.NaNBehavior) {
+      case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
+      case SPNB_RETURNS_NAN:   Opc = ISD::FMAXNAN; break;
+      case SPNB_RETURNS_OTHER: Opc = ISD::FMAXNUM; break;
+      case SPNB_RETURNS_ANY:
+        Opc = TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT) ? ISD::FMAXNUM
+          : ISD::FMAXNAN;
+        break;
+      }
+      break;
+    default: break;
+    }
+
     if (Opc != ISD::DELETED_NODE && TLI.isOperationLegalOrCustom(Opc, VT) &&
         // If the underlying comparison instruction is used by any other instruction,
         // the consumed instructions won't be destroyed, so it is not profitable

Modified: llvm/trunk/test/CodeGen/AArch64/arm64-fmax-safe.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-fmax-safe.ll?rev=245196&r1=245195&r2=245196&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-fmax-safe.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-fmax-safe.ll Mon Aug 17 02:13:10 2015
@@ -7,7 +7,7 @@ define double @test_direct(float %in) {
   %longer = fpext float %val to double
   ret double %longer
 
-; CHECK: fmax
+; CHECK: fmax s
 }
 
 define double @test_cross(float %in) {
@@ -17,11 +17,11 @@ define double @test_cross(float %in) {
   %longer = fpext float %val to double
   ret double %longer
 
-; CHECK: fmin
+; CHECK: fmin s
 }
 
 ; Same as previous, but with ordered comparison;
-; can't be converted in safe-math mode.
+; must become fminnm, not fmin.
 define double @test_cross_fail_nan(float %in) {
 ; CHECK-LABEL: test_cross_fail_nan:
   %cmp = fcmp olt float %in, 0.000000e+00
@@ -29,7 +29,7 @@ define double @test_cross_fail_nan(float
   %longer = fpext float %val to double
   ret double %longer
 
-; CHECK: fcsel s0, s0, s1, mi
+; CHECK: fminnm s
 }
 
 ; This isn't a min or a max, but passes the first condition for swapping the

Modified: llvm/trunk/test/CodeGen/ARM/vminmaxnm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vminmaxnm.ll?rev=245196&r1=245195&r2=245196&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/vminmaxnm.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/vminmaxnm.ll Mon Aug 17 02:13:10 2015
@@ -343,7 +343,7 @@ define float @fp-armv8_vminmaxnm_neg0(fl
 ; CHECK: vmaxnm.f32
   %cmp1 = fcmp fast olt float %a, -0.
   %cond1 = select i1 %cmp1, float %a, float -0.
-  %cmp2 = fcmp fast ogt float %cond1, -0.
+  %cmp2 = fcmp fast ugt float %cond1, -0.
   %cond2 = select i1 %cmp2, float %cond1, float -0.
   ret float %cond2
 }




More information about the llvm-commits mailing list