diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -564,6 +564,19 @@ return V; } +struct is_negated_power2_or_zero { + bool isValue(const APInt &C) { return !C || C.isNegatedPowerOf2(); } +}; +/// Match a integer or vector negated power-of-2. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty m_NegatedPower2OrZero() { + return cst_pred_ty(); +} +inline api_pred_ty +m_NegatedPower2OrZero(const APInt *&V) { + return V; +} + struct is_power2_or_zero { bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } }; @@ -595,6 +608,18 @@ } inline api_pred_ty m_LowBitMask(const APInt *&V) { return V; } +struct is_lowbit_mask_or_zero { + bool isValue(const APInt &C) { return !C || C.isMask(); } +}; +/// Match an integer or vector with only the low bit(s) set. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty m_LowBitMaskOrZero() { + return cst_pred_ty(); +} +inline api_pred_ty m_LowBitMaskOrZero(const APInt *&V) { + return V; +} + struct icmp_pred_with_threshold { ICmpInst::Predicate Pred; const APInt *Thr; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3975,6 +3975,109 @@ return nullptr; } +// Returns of V is a Mask ((X + 1) & X == 0) or ~Mask (-Pow2OrZero) +static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, + unsigned Depth = 0) { + if (Not ? match(V, m_NegatedPower2OrZero()) : match(V, m_LowBitMaskOrZero())) + return true; + if (V->getType()->getScalarSizeInBits() == 1) + return true; + if (Depth++ >= MaxAnalysisRecursionDepth) + return false; + Value *X; + if (match(V, m_Not(m_Value(X)))) + return isMaskOrZero(X, !Not, Q, Depth); + const Operator *I = dyn_cast(V); + if (I == nullptr) + return false; + switch (I->getOpcode()) { + case Instruction::ZExt: + // ZExt(Mask) is a Mask. + return !Not && isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::SExt: + // SExt(Mask) is a Mask. + // SExt(~Mask) is a ~Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::And: + case Instruction::Or: + // Mask0 | Mask1 is a Mask. + // Mask0 & Mask1 is a Mask. + // ~Mask0 | ~Mask1 is a ~Mask. + // ~Mask0 & ~Mask1 is a ~Mask. + return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && + isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::Xor: + // (X ^ (X - 1)) is a Mask + return match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); + case Instruction::Select: + // c ? Mask0 : Mask1 is a Mask. + return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && + isMaskOrZero(I->getOperand(2), Not, Q, Depth); + case Instruction::Shl: + if (Not) { + // (-1 >> X) << X is ~Mask + if (match(I->getOperand(0), + m_Shr(m_AllOnes(), m_Specific(I->getOperand(1))))) + return true; + + // (~Mask) << X is a ~Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + } + break; + case Instruction::LShr: + if (!Not) { + // (-1 << X) >> X is a Mask + if (match(I->getOperand(0), + m_Shl(m_AllOnes(), m_Specific(I->getOperand(1))))) + return true; + // Mask >> X is a Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + } + return false; + case Instruction::AShr: + // Mask s>> X is a Mask. + // ~Mask s>> X is a ~Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::Add: + // Pow2 - 1 is a Mask. + if (!Not && match(I->getOperand(1), m_AllOnes())) + return isKnownToBeAPowerOfTwo(I->getOperand(0), Q.DL, /*OrZero*/ true, + Depth, Q.AC, Q.CxtI, Q.DT); + break; + case Instruction::Sub: + // -Pow2 is a ~Mask. + if (Not && match(I->getOperand(0), m_Zero())) + return isKnownToBeAPowerOfTwo(I->getOperand(1), Q.DL, /*OrZero*/ true, + Depth, Q.AC, Q.CxtI, Q.DT); + break; + case Instruction::Invoke: + case Instruction::Call: { + if (auto *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + // min/max(Mask0, Mask1) is a Mask. + // min/max(~Mask0, ~Mask1) is a ~Mask. + case Intrinsic::umax: + case Intrinsic::smax: + case Intrinsic::umin: + case Intrinsic::smin: + return isMaskOrZero(II->getArgOperand(1), Not, Q, Depth) && + isMaskOrZero(II->getArgOperand(0), Not, Q, Depth); + + // In the context of masks, bitreverse(Mask) == ~Mask + case Intrinsic::bitreverse: + return isMaskOrZero(II->getArgOperand(0), !Not, Q, Depth); + default: + break; + } + } + break; + } + default: + break; + } + return false; +} + /// Some comparisons can be simplified. /// In this case, we are looking for comparisons that look like /// a check for a lossy truncation. @@ -3988,21 +4091,35 @@ /// The Mask can be a constant, too. /// For some predicates, the operands are commutative. /// For others, x can only be on a specific side. -static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I, - InstCombiner::BuilderTy &Builder) { +static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I, const SimplifyQuery &Q, + InstCombiner &IC) { + + Value *X, *M; + ICmpInst::Predicate Pred = I.getPredicate(); ICmpInst::Predicate SrcPred; - Value *X, *M, *Y; - auto m_VariableMask = m_CombineOr( - m_CombineOr(m_Not(m_Shl(m_AllOnes(), m_Value())), - m_Add(m_Shl(m_One(), m_Value()), m_AllOnes())), - m_CombineOr(m_LShr(m_AllOnes(), m_Value()), - m_LShr(m_Shl(m_AllOnes(), m_Value(Y)), m_Deferred(Y)))); - auto m_Mask = m_CombineOr(m_VariableMask, m_LowBitMask()); - if (!match(&I, m_c_ICmp(SrcPred, - m_c_And(m_CombineAnd(m_Mask, m_Value(M)), m_Value(X)), - m_Deferred(X)))) - return nullptr; + bool NeedsNot = false; + + auto CheckMask = [&](Value *V, bool Not) { + if (!ICmpInst::isSigned(Pred)) + return isMaskOrZero(V, Not, Q); + return Not ? match(V, m_NegatedPower2OrZero()) + : match(V, m_LowBitMaskOrZero()); + }; + auto TryMatch = [&](unsigned OpNo) { + SrcPred = Pred; + if (match(I.getOperand(OpNo), + m_c_And(m_Specific(I.getOperand(1 - OpNo)), m_Value(M)))) { + X = I.getOperand(1 - OpNo); + if (OpNo) + SrcPred = ICmpInst::getSwappedPredicate(Pred); + return CheckMask(M, /*Not*/ false); + } + return false; + }; + + if (!TryMatch(0) && !TryMatch(1)) + return nullptr; ICmpInst::Predicate DstPred; switch (SrcPred) { case ICmpInst::Predicate::ICMP_EQ: @@ -4070,7 +4187,9 @@ M = Constant::replaceUndefsWith(VecC, SafeReplacementConstant); } - return Builder.CreateICmp(DstPred, X, M); + if (NeedsNot) + M = IC.Builder.CreateNot(M); + return IC.Builder.CreateICmp(DstPred, X, M); } /// Some comparisons can be simplified. @@ -4977,7 +5096,7 @@ if (Value *V = foldMultiplicationOverflowCheck(I)) return replaceInstUsesWith(I, V); - if (Value *V = foldICmpWithLowBitMaskedVal(I, Builder)) + if (Value *V = foldICmpWithLowBitMaskedVal(I, Q, *this)) return replaceInstUsesWith(I, V); if (Instruction *R = foldICmpAndXX(I, Q, *this)) diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll @@ -50,8 +50,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll @@ -63,8 +63,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll @@ -63,8 +63,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp sle <2 x i8> [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll @@ -50,8 +50,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll @@ -75,8 +75,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll @@ -75,8 +75,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -15,8 +15,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -94,8 +93,7 @@ ; CHECK-NEXT: [[MY:%.*]] = lshr i8 7, [[Y:%.*]] ; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -133,8 +131,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MY:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], 7 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -151,8 +148,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[Y_M1]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -187,8 +183,7 @@ ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -267,8 +262,7 @@ ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 ; CHECK-NEXT: [[MASK:%.*]] = lshr i8 [[SMASK]], [[Z:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -288,8 +282,7 @@ ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 ; CHECK-NEXT: [[MASK:%.*]] = ashr i8 [[SMASK]], [[Z:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -307,8 +300,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[P2ORZ:%.*]] = shl i8 2, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = add i8 [[P2ORZ]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -325,8 +317,7 @@ ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umax.i8(i8 [[YMASK]], i8 3) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -346,8 +337,7 @@ ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[ZMASK:%.*]] = lshr i8 15, [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 [[ZMASK]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -387,8 +377,7 @@ ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smax.i8(i8 [[YMASK]], i8 -1) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -407,8 +396,7 @@ ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smin.i8(i8 [[YMASK]], i8 0) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -426,8 +414,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[NMASK:%.*]] = shl i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -445,8 +432,7 @@ ; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -8, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M_IN]], -1 ; CHECK-NEXT: [[MASK:%.*]] = sext i8 [[TMP1]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -544,8 +530,7 @@ ; CHECK-NEXT: [[NMASK:%.*]] = sext i8 [[M_IN]] to i16 ; CHECK-NEXT: [[NMASK_SHR:%.*]] = ashr i16 [[NMASK]], [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = xor i16 [[NMASK_SHR]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123