Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -1124,13 +1124,16 @@ // [any flop] undef, undef -> undef if (isa(C1) && isa(C2)) return C1; - // [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. + // [any flop] with "regular" constant operand and undef --> undef + // TODO: We could try harder to fold zero operands based on opcode. + if (isa(C1) && C2->isFiniteNonZeroFP()) + return C1; + if (isa(C2) && C1->isFiniteNonZeroFP()) + return C2; + // [any flop] C, undef --> NaN + // [any flop] undef, C --> NaN + // It is always safe to fold to NaN because we can choose the undef + // operand as NaN. Any FP opcode with a NaN operand will propagate NaN. return ConstantFP::getNaN(C1->getType()); case Instruction::BinaryOpsEnd: llvm_unreachable("Invalid BinaryOp"); Index: llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll =================================================================== --- llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll +++ llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll @@ -45,7 +45,7 @@ define <3 x float> @fadd() { ; CHECK-LABEL: @fadd( -; CHECK-NEXT: ret <3 x float> +; CHECK-NEXT: ret <3 x float> undef ; %c = fadd <3 x float> , undef ret <3 x float> %c @@ -53,7 +53,7 @@ define <3 x float> @fadd_commute() { ; CHECK-LABEL: @fadd_commute( -; CHECK-NEXT: ret <3 x float> +; CHECK-NEXT: ret <3 x float> undef ; %c = fadd <3 x float> undef, ret <3 x float> %c Index: llvm/test/Transforms/InstSimplify/fp-undef.ll =================================================================== --- llvm/test/Transforms/InstSimplify/fp-undef.ll +++ llvm/test/Transforms/InstSimplify/fp-undef.ll @@ -209,7 +209,7 @@ define float @fadd_undef_op0_nnan_constant(float %x) { ; CHECK-LABEL: @fadd_undef_op0_nnan_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fadd nnan float undef, 1.0 ret float %r @@ -217,7 +217,7 @@ define float @fadd_undef_op1_constant(float %x) { ; CHECK-LABEL: @fadd_undef_op1_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fadd float 2.0, undef ret float %r @@ -225,7 +225,7 @@ define float @fsub_undef_op0_fast_constant(float %x) { ; CHECK-LABEL: @fsub_undef_op0_fast_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fsub fast float undef, 3.0 ret float %r @@ -233,7 +233,7 @@ define float @fsub_undef_op1_constant(float %x) { ; CHECK-LABEL: @fsub_undef_op1_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fsub float 4.0, undef ret float %r @@ -241,7 +241,7 @@ define float @fmul_undef_op0_nnan_constant(float %x) { ; CHECK-LABEL: @fmul_undef_op0_nnan_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fmul nnan float undef, 5.0 ret float %r @@ -249,7 +249,7 @@ define float @fmul_undef_op1_constant(float %x) { ; CHECK-LABEL: @fmul_undef_op1_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fmul float 6.0, undef ret float %r @@ -257,7 +257,7 @@ define float @fdiv_undef_op0_fast_constant(float %x) { ; CHECK-LABEL: @fdiv_undef_op0_fast_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fdiv fast float undef, 7.0 ret float %r @@ -265,7 +265,7 @@ define float @fdiv_undef_op1_constant(float %x) { ; CHECK-LABEL: @fdiv_undef_op1_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = fdiv float 8.0, undef ret float %r @@ -273,7 +273,7 @@ define float @frem_undef_op0_nnan_constant(float %x) { ; CHECK-LABEL: @frem_undef_op0_nnan_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = frem nnan float undef, 9.0 ret float %r @@ -281,7 +281,7 @@ define float @frem_undef_op1_constant(float %x) { ; CHECK-LABEL: @frem_undef_op1_constant( -; CHECK-NEXT: ret float 0x7FF8000000000000 +; CHECK-NEXT: ret float undef ; %r = frem float 10.0, undef ret float %r @@ -453,7 +453,7 @@ define <2 x double> @fadd_undef_op1_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fadd_undef_op1_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fadd <2 x double> , undef ret <2 x double> %r @@ -461,7 +461,7 @@ define <2 x double> @fadd_undef_op0_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fadd_undef_op0_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fadd <2 x double> undef, ret <2 x double> %r @@ -469,7 +469,7 @@ define <2 x double> @fsub_undef_op1_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fsub_undef_op1_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fsub <2 x double> , undef ret <2 x double> %r @@ -477,7 +477,7 @@ define <2 x double> @fsub_undef_op0_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fsub_undef_op0_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fsub <2 x double> undef, ret <2 x double> %r @@ -485,7 +485,7 @@ define <2 x double> @fmul_undef_op1_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fmul_undef_op1_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fmul <2 x double> , undef ret <2 x double> %r @@ -493,7 +493,7 @@ define <2 x double> @fmul_undef_op0_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fmul_undef_op0_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fmul <2 x double> undef, ret <2 x double> %r @@ -501,7 +501,7 @@ define <2 x double> @fdiv_undef_op1_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fdiv_undef_op1_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fdiv <2 x double> , undef ret <2 x double> %r @@ -509,7 +509,7 @@ define <2 x double> @fdiv_undef_op0_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @fdiv_undef_op0_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = fdiv <2 x double> undef, ret <2 x double> %r @@ -517,7 +517,7 @@ define <2 x double> @frem_undef_op1_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @frem_undef_op1_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = frem <2 x double> , undef ret <2 x double> %r @@ -525,7 +525,7 @@ define <2 x double> @frem_undef_op0_constant_vec(<2 x double> %x) { ; CHECK-LABEL: @frem_undef_op0_constant_vec( -; CHECK-NEXT: ret <2 x double> +; CHECK-NEXT: ret <2 x double> undef ; %r = frem <2 x double> undef, ret <2 x double> %r Index: llvm/test/Transforms/NewGVN/pr32607.ll =================================================================== --- llvm/test/Transforms/NewGVN/pr32607.ll +++ llvm/test/Transforms/NewGVN/pr32607.ll @@ -1,12 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -newgvn %s -S -o - | FileCheck %s + define hidden void @foo() { ; CHECK-LABEL: @foo( ; CHECK-NEXT: top: ; CHECK-NEXT: br label [[IF:%.*]] ; CHECK: if: -; CHECK-NEXT: [[TMP0:%.*]] = phi double [ [[TMP1:%.*]], [[IF]] ], [ undef, [[TOP:%.*]] ] -; CHECK-NEXT: [[TMP1]] = fadd double [[TMP0]], 1.000000e+00 ; CHECK-NEXT: br i1 false, label [[L50:%.*]], label [[IF]] ; CHECK: L50: ; CHECK-NEXT: store i8 undef, i8* null @@ -31,3 +30,33 @@ ret void } +define hidden void @foo_less_undef() { +; CHECK-LABEL: @foo_less_undef( +; CHECK-NEXT: top: +; CHECK-NEXT: br label [[IF:%.*]] +; CHECK: if: +; CHECK-NEXT: [[TMP0:%.*]] = phi double [ [[TMP1:%.*]], [[IF]] ], [ undef, [[TOP:%.*]] ] +; CHECK-NEXT: [[TMP1]] = fadd double [[TMP0]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 false, label [[L50:%.*]], label [[IF]] +; CHECK: L50: +; CHECK-NEXT: store i8 undef, i8* null +; CHECK-NEXT: ret void +; +top: + %.promoted = load double, double* undef, align 8 + br label %if + +;; This is really a multi-valued phi, because the phi is defined by an expression of the phi. +;; This means that we can't propagate the value over the backedge, because we'll just cycle +;; through every value. + +if: ; preds = %if, %top + %0 = phi double [ %1, %if ], [ %.promoted, %top ] + %1 = fadd double %0, 0x7ff0000000000000 ; undef + infinity --> NaN (not undef) + br i1 false, label %L50, label %if + +L50: ; preds = %if + %.lcssa = phi double [ %1, %if ] + store double %.lcssa, double* undef, align 8 + ret void +}