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(C1) && isa(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