[llvm-commits] [llvm] r97065 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/neon_minmax.ll

Bob Wilson bob.wilson at apple.com
Wed Feb 24 14:15:54 PST 2010


Author: bwilson
Date: Wed Feb 24 16:15:53 2010
New Revision: 97065

URL: http://llvm.org/viewvc/llvm-project?rev=97065&view=rev
Log:
Check for comparisons of +/- zero when optimizing less-than-or-equal and
greater-than-or-equal SELECT_CCs to NEON vmin/vmax instructions.  This is
only allowed when UnsafeFPMath is set or when at least one of the operands
is known to be nonzero.

Modified:
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/test/CodeGen/ARM/neon_minmax.ll

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=97065&r1=97064&r2=97065&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Wed Feb 24 16:15:53 2010
@@ -3879,50 +3879,59 @@
 
   unsigned Opcode = 0;
   bool IsReversed;
-  if (LHS == CondLHS && RHS == CondRHS) {
+  if (DAG.isEqualTo(LHS, CondLHS) && DAG.isEqualTo(RHS, CondRHS)) {
     IsReversed = false; // x CC y ? x : y
-  } else if (LHS == CondRHS && RHS == CondLHS) {
+  } else if (DAG.isEqualTo(LHS, CondRHS) && DAG.isEqualTo(RHS, CondLHS)) {
     IsReversed = true ; // x CC y ? y : x
   } else {
     return SDValue();
   }
 
+  bool IsUnordered;
   switch (CC) {
   default: break;
   case ISD::SETOLT:
   case ISD::SETOLE:
   case ISD::SETLT:
   case ISD::SETLE:
-    // This can be vmin if we can prove that the LHS is not a NaN.
-    // (If either operand is NaN, the comparison will be false and the result
-    // will be the RHS, which matches vmin if RHS is the NaN.)
-    if (DAG.isKnownNeverNaN(LHS))
-      Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
-    break;
-
   case ISD::SETULT:
   case ISD::SETULE:
-    // Likewise, for ULT/ULE we need to know that RHS is not a NaN.
-    if (DAG.isKnownNeverNaN(RHS))
-      Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
+    // If LHS is NaN, an ordered comparison will be false and the result will
+    // be the RHS, but vmin(NaN, RHS) = NaN.  Avoid this by checking that LHS
+    // != NaN.  Likewise, for unordered comparisons, check for RHS != NaN.
+    IsUnordered = (CC == ISD::SETULT || CC == ISD::SETULE);
+    if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS))
+      break;
+    // For less-than-or-equal comparisons, "+0 <= -0" will be true but vmin
+    // will return -0, so vmin can only be used for unsafe math or if one of
+    // the operands is known to be nonzero.
+    if ((CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE) &&
+        !UnsafeFPMath &&
+        !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
+      break;
+    Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN;
     break;
 
   case ISD::SETOGT:
   case ISD::SETOGE:
   case ISD::SETGT:
   case ISD::SETGE:
-    // This can be vmax if we can prove that the LHS is not a NaN.
-    // (If either operand is NaN, the comparison will be false and the result
-    // will be the RHS, which matches vmax if RHS is the NaN.)
-    if (DAG.isKnownNeverNaN(LHS))
-      Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
-    break;
-
   case ISD::SETUGT:
   case ISD::SETUGE:
-    // Likewise, for UGT/UGE we need to know that RHS is not a NaN.
-    if (DAG.isKnownNeverNaN(RHS))
-      Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
+    // If LHS is NaN, an ordered comparison will be false and the result will
+    // be the RHS, but vmax(NaN, RHS) = NaN.  Avoid this by checking that LHS
+    // != NaN.  Likewise, for unordered comparisons, check for RHS != NaN.
+    IsUnordered = (CC == ISD::SETUGT || CC == ISD::SETUGE);
+    if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS))
+      break;
+    // For greater-than-or-equal comparisons, "-0 >= +0" will be true but vmax
+    // will return +0, so vmax can only be used for unsafe math or if one of
+    // the operands is known to be nonzero.
+    if ((CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE) &&
+        !UnsafeFPMath &&
+        !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS)))
+      break;
+    Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX;
     break;
   }
 

Modified: llvm/trunk/test/CodeGen/ARM/neon_minmax.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/neon_minmax.ll?rev=97065&r1=97064&r2=97065&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/neon_minmax.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/neon_minmax.ll Wed Feb 24 16:15:53 2010
@@ -8,6 +8,14 @@
   ret float %min1
 }
 
+define float @fmin_ole_zero(float %x) nounwind {
+;CHECK: fmin_ole_zero:
+;CHECK-NOT: vmin.f32
+  %cond = fcmp ole float 0.0, %x
+  %min1 = select i1 %cond, float 0.0, float %x
+  ret float %min1
+}
+
 define float @fmin_ult(float %x) nounwind {
 ;CHECK: fmin_ult:
 ;CHECK: vmin.f32
@@ -32,6 +40,14 @@
   ret float %max1
 }
 
+define float @fmax_uge_zero(float %x) nounwind {
+;CHECK: fmax_uge_zero:
+;CHECK-NOT: vmax.f32
+  %cond = fcmp uge float %x, 0.0
+  %max1 = select i1 %cond, float %x, float 0.0
+  ret float %max1
+}
+
 define float @fmax_olt_reverse(float %x) nounwind {
 ;CHECK: fmax_olt_reverse:
 ;CHECK: vmax.f32





More information about the llvm-commits mailing list