Index: llvm/trunk/lib/IR/ConstantFold.cpp
===================================================================
--- llvm/trunk/lib/IR/ConstantFold.cpp
+++ llvm/trunk/lib/IR/ConstantFold.cpp
@@ -1012,8 +1012,14 @@
       // [any flop] undef, undef -> undef
       if (isa<UndefValue>(C1) && isa<UndefValue>(C2))
         return C1;
-      // TODO: Handle one undef operand and some other constant.
-      return nullptr;
+      // [any flop] C, undef -> NaN
+      // [any flop] undef, C -> NaN
+      // We could potentially specialize NaN/Inf constants vs. 'normal'
+      // constants (possibly differently depending on opcode and operand). This
+      // would allow returning undef sometimes. But it is always safe to fold to
+      // NaN because we can choose the undef operand as NaN, and any FP opcode
+      // with a NaN operand will propagate NaN.
+      return ConstantFP::getNaN(C1->getType());
     case Instruction::BinaryOpsEnd:
       llvm_unreachable("Invalid BinaryOp");
     }
Index: llvm/trunk/test/Transforms/InstCombine/fsub.ll
===================================================================
--- llvm/trunk/test/Transforms/InstCombine/fsub.ll
+++ llvm/trunk/test/Transforms/InstCombine/fsub.ll
@@ -47,31 +47,3 @@
   ret float %sub
 }
 
-define float @fneg_undef(float %val) {
-; CHECK-LABEL: @fneg_undef(
-; CHECK-NEXT:    ret float fsub (float -0.000000e+00, float undef)
-;
-  %sub = fsub float -0.0, undef
-  ret float %sub
-}
-
-define float @fneg_fast_undef(float %val) {
-; CHECK-LABEL: @fneg_fast_undef(
-; CHECK-NEXT:    ret float fsub (float -0.000000e+00, float undef)
-;
-  %sub = fsub fast float -0.0, undef
-  ret float %sub
-}
-
-; This folds to a constant expression, which produced 0 instructions
-; contrary to the expected one for negation.
-
-define float @inconsistent_numbers_fsub_undef(float %val) {
-; CHECK-LABEL: @inconsistent_numbers_fsub_undef(
-; CHECK-NEXT:    ret float fsub (float -0.000000e+00, float undef)
-;
-  %sub0 = fsub fast float %val, undef
-  %sub1 = fsub fast float %sub0, %val
-  ret float %sub1
-}
-
Index: llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll
===================================================================
--- llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll
+++ llvm/trunk/test/Transforms/InstSimplify/fp-undef.ll
@@ -221,7 +221,7 @@
 
 define float @fadd_undef_op0_nnan_constant(float %x) {
 ; CHECK-LABEL: @fadd_undef_op0_nnan_constant(
-; CHECK-NEXT:    ret float fadd (float undef, float 1.000000e+00)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fadd nnan float undef, 1.0
   ret float %r
@@ -229,7 +229,7 @@
 
 define float @fadd_undef_op1_constant(float %x) {
 ; CHECK-LABEL: @fadd_undef_op1_constant(
-; CHECK-NEXT:    ret float fadd (float 2.000000e+00, float undef)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fadd float 2.0, undef
   ret float %r
@@ -237,7 +237,7 @@
 
 define float @fsub_undef_op0_fast_constant(float %x) {
 ; CHECK-LABEL: @fsub_undef_op0_fast_constant(
-; CHECK-NEXT:    ret float fsub (float undef, float 3.000000e+00)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fsub fast float undef, 3.0
   ret float %r
@@ -245,7 +245,7 @@
 
 define float @fsub_undef_op1_constant(float %x) {
 ; CHECK-LABEL: @fsub_undef_op1_constant(
-; CHECK-NEXT:    ret float fsub (float 4.000000e+00, float undef)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fsub float 4.0, undef
   ret float %r
@@ -253,7 +253,7 @@
 
 define float @fmul_undef_op0_nnan_constant(float %x) {
 ; CHECK-LABEL: @fmul_undef_op0_nnan_constant(
-; CHECK-NEXT:    ret float fmul (float undef, float 5.000000e+00)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fmul nnan float undef, 5.0
   ret float %r
@@ -261,7 +261,7 @@
 
 define float @fmul_undef_op1_constant(float %x) {
 ; CHECK-LABEL: @fmul_undef_op1_constant(
-; CHECK-NEXT:    ret float fmul (float 6.000000e+00, float undef)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fmul float 6.0, undef
   ret float %r
@@ -269,7 +269,7 @@
 
 define float @fdiv_undef_op0_fast_constant(float %x) {
 ; CHECK-LABEL: @fdiv_undef_op0_fast_constant(
-; CHECK-NEXT:    ret float fdiv (float undef, float 7.000000e+00)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fdiv fast float undef, 7.0
   ret float %r
@@ -277,7 +277,7 @@
 
 define float @fdiv_undef_op1_constant(float %x) {
 ; CHECK-LABEL: @fdiv_undef_op1_constant(
-; CHECK-NEXT:    ret float fdiv (float 8.000000e+00, float undef)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = fdiv float 8.0, undef
   ret float %r
@@ -285,7 +285,7 @@
 
 define float @frem_undef_op0_nnan_constant(float %x) {
 ; CHECK-LABEL: @frem_undef_op0_nnan_constant(
-; CHECK-NEXT:    ret float frem (float undef, float 9.000000e+00)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = frem nnan float undef, 9.0
   ret float %r
@@ -293,7 +293,7 @@
 
 define float @frem_undef_op1_constant(float %x) {
 ; CHECK-LABEL: @frem_undef_op1_constant(
-; CHECK-NEXT:    ret float frem (float 1.000000e+01, float undef)
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %r = frem float 10.0, undef
   ret float %r
@@ -303,7 +303,7 @@
 
 define double @fadd_undef_op0_constant_nan(double %x) {
 ; CHECK-LABEL: @fadd_undef_op0_constant_nan(
-; CHECK-NEXT:    ret double fadd (double undef, double 0x7FF8000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fadd double undef, 0x7FF8000000000000
   ret double %r
@@ -311,7 +311,7 @@
 
 define double @fadd_undef_op1_fast_constant_nan(double %x) {
 ; CHECK-LABEL: @fadd_undef_op1_fast_constant_nan(
-; CHECK-NEXT:    ret double fadd (double 0xFFF0000000000001, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fadd fast double 0xFFF0000000000001, undef
   ret double %r
@@ -319,7 +319,7 @@
 
 define double @fsub_undef_op0_constant_nan(double %x) {
 ; CHECK-LABEL: @fsub_undef_op0_constant_nan(
-; CHECK-NEXT:    ret double fsub (double undef, double 0xFFF8000000000010)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fsub double undef, 0xFFF8000000000010
   ret double %r
@@ -327,7 +327,7 @@
 
 define double @fsub_undef_op1_nnan_constant_nan(double %x) {
 ; CHECK-LABEL: @fsub_undef_op1_nnan_constant_nan(
-; CHECK-NEXT:    ret double fsub (double 0x7FF0000000000011, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fsub nnan double 0x7FF0000000000011, undef
   ret double %r
@@ -335,7 +335,7 @@
 
 define double @fmul_undef_op0_constant_nan(double %x) {
 ; CHECK-LABEL: @fmul_undef_op0_constant_nan(
-; CHECK-NEXT:    ret double fmul (double undef, double 0x7FF8000000000100)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fmul double undef, 0x7FF8000000000100
   ret double %r
@@ -343,7 +343,7 @@
 
 define double @fmul_undef_op1_fast_constant_nan(double %x) {
 ; CHECK-LABEL: @fmul_undef_op1_fast_constant_nan(
-; CHECK-NEXT:    ret double fmul (double 0xFFF0000000000101, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fmul fast double 0xFFF0000000000101, undef
   ret double %r
@@ -351,7 +351,7 @@
 
 define double @fdiv_undef_op0_constant_nan(double %x) {
 ; CHECK-LABEL: @fdiv_undef_op0_constant_nan(
-; CHECK-NEXT:    ret double fdiv (double undef, double 0xFFF8000000000110)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fdiv double undef, 0xFFF8000000000110
   ret double %r
@@ -359,7 +359,7 @@
 
 define double @fdiv_undef_op1_nnan_constant_nan(double %x) {
 ; CHECK-LABEL: @fdiv_undef_op1_nnan_constant_nan(
-; CHECK-NEXT:    ret double fdiv (double 0x7FF0000000000111, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fdiv nnan double 0x7FF0000000000111, undef
   ret double %r
@@ -367,7 +367,7 @@
 
 define double @frem_undef_op0_constant_nan(double %x) {
 ; CHECK-LABEL: @frem_undef_op0_constant_nan(
-; CHECK-NEXT:    ret double frem (double undef, double 0x7FF8000000001000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = frem double undef, 0x7FF8000000001000
   ret double %r
@@ -375,7 +375,7 @@
 
 define double @frem_undef_op1_fast_constant_nan(double %x) {
 ; CHECK-LABEL: @frem_undef_op1_fast_constant_nan(
-; CHECK-NEXT:    ret double frem (double 0xFFF0000000001001, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = frem fast double 0xFFF0000000001001, undef
   ret double %r
@@ -385,7 +385,7 @@
 
 define double @fadd_undef_op0_constant_inf(double %x) {
 ; CHECK-LABEL: @fadd_undef_op0_constant_inf(
-; CHECK-NEXT:    ret double fadd (double undef, double 0x7FF0000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fadd double undef, 0x7FF0000000000000
   ret double %r
@@ -393,7 +393,7 @@
 
 define double @fadd_undef_op1_fast_constant_inf(double %x) {
 ; CHECK-LABEL: @fadd_undef_op1_fast_constant_inf(
-; CHECK-NEXT:    ret double fadd (double 0xFFF0000000000000, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fadd fast double 0xFFF0000000000000, undef
   ret double %r
@@ -401,7 +401,7 @@
 
 define double @fsub_undef_op0_constant_inf(double %x) {
 ; CHECK-LABEL: @fsub_undef_op0_constant_inf(
-; CHECK-NEXT:    ret double fsub (double undef, double 0xFFF0000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fsub double undef, 0xFFF0000000000000
   ret double %r
@@ -409,7 +409,7 @@
 
 define double @fsub_undef_op1_ninf_constant_inf(double %x) {
 ; CHECK-LABEL: @fsub_undef_op1_ninf_constant_inf(
-; CHECK-NEXT:    ret double fsub (double 0x7FF0000000000000, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fsub ninf double 0x7FF0000000000000, undef
   ret double %r
@@ -417,7 +417,7 @@
 
 define double @fmul_undef_op0_constant_inf(double %x) {
 ; CHECK-LABEL: @fmul_undef_op0_constant_inf(
-; CHECK-NEXT:    ret double fmul (double undef, double 0x7FF0000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fmul double undef, 0x7FF0000000000000
   ret double %r
@@ -425,7 +425,7 @@
 
 define double @fmul_undef_op1_fast_constant_inf(double %x) {
 ; CHECK-LABEL: @fmul_undef_op1_fast_constant_inf(
-; CHECK-NEXT:    ret double fmul (double 0xFFF0000000000000, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fmul fast double 0xFFF0000000000000, undef
   ret double %r
@@ -433,7 +433,7 @@
 
 define double @fdiv_undef_op0_constant_inf(double %x) {
 ; CHECK-LABEL: @fdiv_undef_op0_constant_inf(
-; CHECK-NEXT:    ret double fdiv (double undef, double 0xFFF0000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fdiv double undef, 0xFFF0000000000000
   ret double %r
@@ -441,7 +441,7 @@
 
 define double @fdiv_undef_op1_ninf_constant_inf(double %x) {
 ; CHECK-LABEL: @fdiv_undef_op1_ninf_constant_inf(
-; CHECK-NEXT:    ret double fdiv (double 0x7FF0000000000000, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = fdiv ninf double 0x7FF0000000000000, undef
   ret double %r
@@ -449,7 +449,7 @@
 
 define double @frem_undef_op0_constant_inf(double %x) {
 ; CHECK-LABEL: @frem_undef_op0_constant_inf(
-; CHECK-NEXT:    ret double frem (double undef, double 0x7FF0000000000000)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = frem double undef, 0x7FF0000000000000
   ret double %r
@@ -457,7 +457,7 @@
 
 define double @frem_undef_op1_fast_constant_inf(double %x) {
 ; CHECK-LABEL: @frem_undef_op1_fast_constant_inf(
-; CHECK-NEXT:    ret double frem (double 0xFFF0000000000000, double undef)
+; CHECK-NEXT:    ret double 0x7FF8000000000000
 ;
   %r = frem fast double 0xFFF0000000000000, undef
   ret double %r