Fold comparisons against a constant nan, and optimize ORD/UNORD 
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
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index eb08bba..ad33273 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1280,6 +1280,28 @@
     // 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) {
diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt
index 08b5875..759c7ac 100644
--- a/lib/Target/X86/README.txt
+++ b/lib/Target/X86/README.txt
@@ -816,23 +816,6 @@
 
 //===---------------------------------------------------------------------===//
 
-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
index 0000000..18fe29a
--- /dev/null
+++ b/test/CodeGen/X86/isnan.ll
@@ -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
+}
+