diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3778,29 +3778,45 @@ if (Value *NI = pushFreezeToPreventPoisonFromPropagating(I)) return replaceInstUsesWith(I, NI); - if (match(Op0, m_Undef())) { - // If I is freeze(undef), check its uses and fold it to a fixed constant. - // - or: pick -1 - // - select's condition: if the true value is constant, choose it by making - // the condition true. - // - default: pick 0 + // If I is freeze(undef), check its uses and fold it to a fixed constant. + // - or: pick -1 + // - select's condition: if the true value is constant, choose it by making + // the condition true. + // - default: pick 0 + // + // Note that this transform is intentionally done here rather than + // via an analysis in InstSimplify or at individual user sites. That is + // because we must produce the same value for all uses of the freeze - + // it's the reason "freeze" exists! + // + // TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid + // duplicating logic for binops at least. + auto getUndefReplacement = [&I](Type *Ty) { Constant *BestValue = nullptr; - Constant *NullValue = Constant::getNullValue(I.getType()); + Constant *NullValue = Constant::getNullValue(Ty); for (const auto *U : I.users()) { Constant *C = NullValue; - if (match(U, m_Or(m_Value(), m_Value()))) - C = ConstantInt::getAllOnesValue(I.getType()); + C = ConstantInt::getAllOnesValue(Ty); else if (match(U, m_Select(m_Specific(&I), m_Constant(), m_Value()))) - C = ConstantInt::getTrue(I.getType()); + C = ConstantInt::getTrue(Ty); if (!BestValue) BestValue = C; else if (BestValue != C) BestValue = NullValue; } + assert(BestValue && "Must have at least one use"); + return BestValue; + }; + + if (match(Op0, m_Undef())) + return replaceInstUsesWith(I, getUndefReplacement(I.getType())); - return replaceInstUsesWith(I, BestValue); + Constant *C; + if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement()) { + Constant *ReplaceC = getUndefReplacement(I.getType()->getScalarType()); + return replaceInstUsesWith(I, Constant::replaceUndefsWith(C, ReplaceC)); } // Replace all dominated uses of Op to freeze(Op). diff --git a/llvm/test/Transforms/InstCombine/freeze-phi.ll b/llvm/test/Transforms/InstCombine/freeze-phi.ll --- a/llvm/test/Transforms/InstCombine/freeze-phi.ll +++ b/llvm/test/Transforms/InstCombine/freeze-phi.ll @@ -51,10 +51,9 @@ ; CHECK: A: ; CHECK-NEXT: br label [[C:%.*]] ; CHECK: B: -; CHECK-NEXT: [[PHI_FR:%.*]] = freeze <2 x i32> ; CHECK-NEXT: br label [[C]] ; CHECK: C: -; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ , [[A]] ], [ [[PHI_FR]], [[B]] ] +; CHECK-NEXT: [[Y:%.*]] = phi <2 x i32> [ , [[A]] ], [ , [[B]] ] ; CHECK-NEXT: ret <2 x i32> [[Y]] ; br i1 %cond, label %A, label %B diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -89,8 +89,7 @@ define <3 x i4> @partial_undef_vec() { ; CHECK-LABEL: @partial_undef_vec( -; CHECK-NEXT: [[F:%.*]] = freeze <3 x i4> -; CHECK-NEXT: ret <3 x i4> [[F]] +; CHECK-NEXT: ret <3 x i4> ; %f = freeze <3 x i4> ret <3 x i4> %f diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -2633,9 +2633,7 @@ define <2 x i8> @partial_cond_freeze_constant_true_val_vec(<2 x i8> %x) { ; CHECK-LABEL: @partial_cond_freeze_constant_true_val_vec( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze <2 x i1> -; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND_FR]], <2 x i8> , <2 x i8> [[X:%.*]] -; CHECK-NEXT: ret <2 x i8> [[S]] +; CHECK-NEXT: ret <2 x i8> ; %cond.fr = freeze <2 x i1> %s = select <2 x i1> %cond.fr, <2 x i8> , <2 x i8> %x @@ -2644,9 +2642,8 @@ define <2 x i8> @partial_cond_freeze_constant_false_val_vec(<2 x i8> %x) { ; CHECK-LABEL: @partial_cond_freeze_constant_false_val_vec( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze <2 x i1> -; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND_FR]], <2 x i8> [[X:%.*]], <2 x i8> -; CHECK-NEXT: ret <2 x i8> [[S]] +; CHECK-NEXT: [[S1:%.*]] = insertelement <2 x i8> [[X:%.*]], i8 2, i64 1 +; CHECK-NEXT: ret <2 x i8> [[S1]] ; %cond.fr = freeze <2 x i1> %s = select <2 x i1> %cond.fr, <2 x i8> %x, <2 x i8> @@ -2655,9 +2652,7 @@ define <2 x i8> @partial_cond_freeze_both_arms_constant_vec() { ; CHECK-LABEL: @partial_cond_freeze_both_arms_constant_vec( -; CHECK-NEXT: [[COND_FR:%.*]] = freeze <2 x i1> -; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND_FR]], <2 x i8> , <2 x i8> -; CHECK-NEXT: ret <2 x i8> [[S]] +; CHECK-NEXT: ret <2 x i8> ; %cond.fr = freeze <2 x i1> %s = select <2 x i1> %cond.fr, <2 x i8> , <2 x i8>