Fold comparisons against a constant nan, and optimize ORD/UNORD
authorChris Lattner <sabre@nondot.org>
Sat, 29 Dec 2007 08:37:08 +0000 (08:37 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 29 Dec 2007 08:37:08 +0000 (08:37 +0000)
comparisons with a constant.  This allows us to compile isnan to:

_foo:
fcmpu cr7, f1, f1
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr

instead of:

LCPI1_0: ;  float
.space 4
_foo:
lis r2, ha16(LCPI1_0)
lfs f0, lo16(LCPI1_0)(r2)
fcmpu cr7, f1, f0
mfcr r2
rlwinm r3, r2, 0, 31, 31
blr

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45405 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/X86/README.txt
test/CodeGen/X86/isnan.ll [new file with mode: 0644]

index eb08bbae7c3b3d0f47668c6759b75fe5f746f3a9..ad3327335182e70d3c8ebc59c7f2822ac90f3426 100644 (file)
@@ -1280,6 +1280,28 @@ TargetLowering::SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1,
     // Constant fold or commute setcc.
     SDOperand O = DAG.FoldSetCC(VT, N0, N1, Cond);    
     if (O.Val) return O;
+  } else if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N1.Val)) {
+    // If the RHS of an FP comparison is a constant, simplify it away in
+    // some cases.
+    if (CFP->getValueAPF().isNaN()) {
+      // If an operand is known to be a nan, we can fold it.
+      switch (ISD::getUnorderedFlavor(Cond)) {
+      default: assert(0 && "Unknown flavor!");
+      case 0:  // Known false.
+        return DAG.getConstant(0, VT);
+      case 1:  // Known true.
+        return DAG.getConstant(1, VT);
+      case 2:  // undefind.
+        return DAG.getNode(ISD::UNDEF, VT);
+      }
+    }
+    
+    // Otherwise, we know the RHS is not a NaN.  Simplify the node to drop the
+    // constant if knowing that the operand is non-nan is enough.  We prefer to
+    // have SETO(x,x) instead of SETO(x, 0.0) because this avoids having to
+    // materialize 0.0.
+    if (Cond == ISD::SETO || Cond == ISD::SETUO)
+      return DAG.getSetCC(VT, N0, N0, Cond);
   }
 
   if (N0 == N1) {
index 08b5875c57443cad06cde80ab5b9f8f6844744fd..759c7acf389173e3d52de301f3720cb1855c3751 100644 (file)
@@ -816,23 +816,6 @@ _add_zf:
 
 //===---------------------------------------------------------------------===//
 
-This:
-#include <math.h>
-int foo(double X) { return isnan(X); }
-
-compiles to (-m64):
-
-_foo:
-        pxor %xmm1, %xmm1
-        ucomisd %xmm1, %xmm0
-        setp %al
-        movzbl %al, %eax
-        ret
-
-the pxor is not needed, we could compare the value against itself.
-
-//===---------------------------------------------------------------------===//
-
 These two functions have identical effects:
 
 unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return i;}
diff --git a/test/CodeGen/X86/isnan.ll b/test/CodeGen/X86/isnan.ll
new file mode 100644 (file)
index 0000000..18fe29a
--- /dev/null
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llc -march=x86 -mcpu=yonah | not grep pxor
+
+; This should not need to materialize 0.0 to evaluate the condition.
+
+define i32 @test(double %X) nounwind  {
+entry:
+       %tmp6 = fcmp uno double %X, 0.000000e+00                ; <i1> [#uses=1]
+       %tmp67 = zext i1 %tmp6 to i32           ; <i32> [#uses=1]
+       ret i32 %tmp67
+}
+