Index: llvm/include/llvm/IR/Constant.h =================================================================== --- llvm/include/llvm/IR/Constant.h +++ llvm/include/llvm/IR/Constant.h @@ -188,6 +188,10 @@ return const_cast( static_cast(this)->stripPointerCasts()); } + + /// Try to replace undefined constant C or undefined elements in C with + /// Replacement. If no changes are made, the constant C is returned. + static Constant *replaceUndefsWith(Constant *C, Constant *Replacement); }; } // end namespace llvm Index: llvm/lib/IR/Constants.cpp =================================================================== --- llvm/lib/IR/Constants.cpp +++ llvm/lib/IR/Constants.cpp @@ -31,6 +31,7 @@ #include using namespace llvm; +using namespace PatternMatch; //===----------------------------------------------------------------------===// // Constant Class @@ -259,10 +260,9 @@ auto *Cy = dyn_cast(Y); if (!Cy) return false; - return PatternMatch::match(ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_EQ, - const_cast(this), - Cy), - PatternMatch::m_One()); + return match(ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_EQ, + const_cast(this), Cy), + m_One()); } bool Constant::containsUndefElement() const { @@ -595,6 +595,27 @@ } } +Constant *Constant::replaceUndefsWith(Constant *C, Constant *Replacement) { + Type *Ty = C->getType(); + if (C && match(C, m_Undef())) { + assert(Ty == Replacement->getType() && "Expected matching types"); + return Replacement; + } + + // Don't know how to deal with this constant. + if (!Ty->isVectorTy()) + return C; + + unsigned NumElts = Ty->getVectorNumElements(); + SmallVector NewC(NumElts); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *EltC = C->getAggregateElement(i); + assert(EltC->getType() == Replacement->getType() && + "Expected matching types"); + NewC[i] = EltC && match(EltC, m_Undef()) ? Replacement : EltC; + } + return ConstantVector::get(NewC); +} //===----------------------------------------------------------------------===// Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5167,6 +5167,7 @@ return WillIncrement ? !C->isMaxValue(IsSigned) : !C->isMinValue(IsSigned); }; + Constant *SafeReplacementConstant = nullptr; if (auto *CI = dyn_cast(C)) { // Bail out if the constant can't be safely incremented/decremented. if (!ConstantIsOk(CI)) @@ -5186,12 +5187,21 @@ auto *CI = dyn_cast(Elt); if (!CI || !ConstantIsOk(CI)) return llvm::None; + SafeReplacementConstant = CI; } } else { // ConstantExpr? return llvm::None; } + // It may not be safe to change a compare predicate in the presence of + // undefined elements, so replace those elements with the first safe constant + // that we found. + if (C->containsUndefElement()) { + assert(SafeReplacementConstant && "Replacement constant not set"); + C = Constant::replaceUndefsWith(C, SafeReplacementConstant); + } + CmpInst::Predicate NewPred = CmpInst::getFlippedStrictnessPredicate(Pred); // Increment or decrement the constant. Index: llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -138,24 +138,6 @@ return Ret; } -// Try to replace `undef` constants in C with Replacement. -static Constant *replaceUndefsWith(Constant *C, Constant *Replacement) { - if (C && match(C, m_Undef())) - return Replacement; - - if (auto *CV = dyn_cast(C)) { - llvm::SmallVector NewOps(CV->getNumOperands()); - for (unsigned i = 0, NumElts = NewOps.size(); i != NumElts; ++i) { - Constant *EltC = CV->getOperand(i); - NewOps[i] = EltC && match(EltC, m_Undef()) ? Replacement : EltC; - } - return ConstantVector::get(NewOps); - } - - // Don't know how to deal with this constant. - return C; -} - // If we have some pattern that leaves only some low bits set, and then performs // left-shift of those bits, if none of the bits that are left after the final // shift are modified by the mask, we can omit the mask. @@ -216,7 +198,7 @@ // completely unknown. Replace the the `undef` shift amounts with final // shift bitwidth to ensure that the value remains undef when creating the // subsequent shift op. - SumOfShAmts = replaceUndefsWith( + SumOfShAmts = Constant::replaceUndefsWith( SumOfShAmts, ConstantInt::get(SumOfShAmts->getType()->getScalarType(), ExtendedTy->getScalarSizeInBits())); auto *ExtendedSumOfShAmts = ConstantExpr::getZExt(SumOfShAmts, ExtendedTy); @@ -241,7 +223,7 @@ // bitwidth of innermost shift to ensure that the value remains undef when // creating the subsequent shift op. unsigned WidestTyBitWidth = WidestTy->getScalarSizeInBits(); - ShAmtsDiff = replaceUndefsWith( + ShAmtsDiff = Constant::replaceUndefsWith( ShAmtsDiff, ConstantInt::get(ShAmtsDiff->getType()->getScalarType(), -WidestTyBitWidth)); auto *ExtendedNumHighBitsToClear = ConstantExpr::getZExt( Index: llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll =================================================================== --- llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll +++ llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll @@ -82,7 +82,7 @@ define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) { ; CHECK-LABEL: @p3_vec_splat_undef( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X:%.*]], ; CHECK-NEXT: ret <3 x i1> [[TMP1]] ; %tmp0 = and <3 x i8> %x, Index: llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll =================================================================== --- llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll +++ llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll @@ -61,7 +61,7 @@ define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) { ; CHECK-LABEL: @p3_vec_splat_undef( -; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i8> [[X:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i8> [[X:%.*]], ; CHECK-NEXT: ret <3 x i1> [[TMP1]] ; %tmp0 = and <3 x i8> %x, Index: llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll =================================================================== --- llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll +++ llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll @@ -76,7 +76,7 @@ define <3 x i1> @p3_vec_splat_undef() { ; CHECK-LABEL: @p3_vec_splat_undef( ; CHECK-NEXT: [[X:%.*]] = call <3 x i8> @gen3x8() -; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i8> [[X]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i8> [[X]], ; CHECK-NEXT: ret <3 x i1> [[TMP1]] ; %x = call <3 x i8> @gen3x8() Index: llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll =================================================================== --- llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll +++ llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll @@ -82,7 +82,7 @@ define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) { ; CHECK-LABEL: @p3_vec_splat_undef( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X:%.*]], ; CHECK-NEXT: ret <3 x i1> [[TMP1]] ; %tmp0 = and <3 x i8> %x, Index: llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll =================================================================== --- llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll +++ llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll @@ -99,7 +99,7 @@ define <3 x i1> @p3_vec_splat_undef() { ; CHECK-LABEL: @p3_vec_splat_undef( ; CHECK-NEXT: [[X:%.*]] = call <3 x i8> @gen3x8() -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <3 x i8> [[X]], ; CHECK-NEXT: ret <3 x i1> [[TMP1]] ; %x = call <3 x i8> @gen3x8() Index: llvm/test/Transforms/InstCombine/icmp-vec.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-vec.ll +++ llvm/test/Transforms/InstCombine/icmp-vec.ll @@ -181,7 +181,7 @@ define <2 x i1> @PR27756_2(<2 x i8> %a) { ; CHECK-LABEL: @PR27756_2( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %cmp = icmp sle <2 x i8> %a, Index: llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll +++ llvm/test/Transforms/InstCombine/reuse-constant-from-select-in-icmp.ll @@ -106,7 +106,7 @@ define <2 x i32> @p8_vec_nonsplat_undef0(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @p8_vec_nonsplat_undef0( -; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; @@ -126,7 +126,7 @@ } define <2 x i32> @p10_vec_nonsplat_undef2(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @p10_vec_nonsplat_undef2( -; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ;