diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index de90907701743..5ef6861755f68 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4724,6 +4724,26 @@ static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q, if (Pred == ICmpInst::ICMP_UGE) return new ICmpInst(ICmpInst::ICMP_EQ, Op0, Op1); + if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) { + // icmp (X & Y) eq/ne Y --> (X | ~Y) eq/ne -1 if Y is freely invertible and + // Y is non-constant. If Y is constant the `X & C == C` form is preferable + // so don't do this fold. + if (!match(Op1, m_ImmConstant())) + if (auto *NotOp1 = + IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder)) + return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1), + Constant::getAllOnesValue(Op1->getType())); + // icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible. + // Since we may be consuming a `not` here, first check if we match + // `foldICmpWithLowBitMaskedVal` as it is a "better" user of `not` + // instructions. + if (Value *R = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Q, IC)) + return IC.replaceInstUsesWith(I, R); + if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder)) + return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA), + Constant::getNullValue(Op1->getType())); + } + return nullptr; } @@ -5498,21 +5518,6 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { } } - // canoncalize: - // (icmp eq/ne (and X, C), X) - // -> (icmp eq/ne (and X, ~C), 0) - { - Constant *CMask; - A = nullptr; - if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_ImmConstant(CMask))))) - A = Op1; - else if (match(Op1, m_OneUse(m_And(m_Specific(Op0), m_ImmConstant(CMask))))) - A = Op0; - if (A) - return new ICmpInst(Pred, Builder.CreateAnd(A, Builder.CreateNot(CMask)), - Constant::getNullValue(A->getType())); - } - if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) { // A == (A^B) -> B == 0 Value *OtherVal = A == Op0 ? B : A; diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll index 88487b38e2c70..24ca49386b7e8 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll @@ -269,9 +269,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) { define i1 @n1(i8 %x, i8 %y) { ; CHECK-LABEL: @n1( ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]] -; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 -; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]] +; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 1, %y ; not -1 @@ -284,9 +283,9 @@ define i1 @n1(i8 %x, i8 %y) { define i1 @n2(i8 %x, i8 %y) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]] -; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1 +; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2 ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 -1, %y diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll index b717925fd644f..271d78d589b60 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll @@ -269,9 +269,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) { define i1 @n1(i8 %x, i8 %y) { ; CHECK-LABEL: @n1( ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]] -; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 -; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]] +; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 1, %y ; not -1 @@ -284,9 +283,9 @@ define i1 @n1(i8 %x, i8 %y) { define i1 @n2(i8 %x, i8 %y) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]] -; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1 +; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2 ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 -1, %y diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll index a65be1e9ceeca..c7c57b601eab3 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll @@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) { ; CHECK-LABEL: @n1( ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]] ; CHECK-NEXT: call void @use8(i8 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1 +; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]] ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 -1, %y ; not 1 @@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]] ; CHECK-NEXT: call void @use8(i8 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1 +; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]] ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 1, %y diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll index f156d9bf007cb..d5826524f1637 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll @@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) { ; CHECK-LABEL: @n1( ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]] ; CHECK-NEXT: call void @use8(i8 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1 +; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]] ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 -1, %y ; not 1 @@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]] ; CHECK-NEXT: call void @use8(i8 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1 +; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]] ; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]] -; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %t0 = shl i8 1, %y diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 5de3e89d7027a..8bb7fd0e522cb 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -5,9 +5,9 @@ declare void @use.i8(i8) declare void @use.i16(i16) define i1 @src_is_mask_zext(i16 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_zext( -; 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: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -22,11 +22,11 @@ define i1 @src_is_mask_zext(i16 %x_in, i8 %y) { define i1 @src_is_mask_zext_fail_not_mask(i16 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_zext_fail_not_mask( -; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -2, [[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: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[TMP1]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[TMP2]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -80,10 +80,10 @@ define i1 @src_is_mask_sext_fail_multiuse(i16 %x_in, i8 %y) { define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) { ; CHECK-LABEL: @src_is_mask_and( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MY:%.*]] = lshr i8 7, [[Y:%.*]] ; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]] +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -99,12 +99,12 @@ define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) { define i1 @src_is_mask_and_fail_mixed(i8 %x_in, i8 %y, i8 %z) { ; CHECK-LABEL: @src_is_mask_and_fail_mixed( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MY:%.*]] = ashr i8 -8, [[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: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[MASK]], [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -119,9 +119,9 @@ define i1 @src_is_mask_and_fail_mixed(i8 %x_in, i8 %y, i8 %z) { define i1 @src_is_mask_or(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_or( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MY:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], 7 +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -136,9 +136,9 @@ define i1 @src_is_mask_or(i8 %x_in, i8 %y) { define i1 @src_is_mask_xor(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_xor( -; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -152,11 +152,11 @@ define i1 @src_is_mask_xor(i8 %x_in, i8 %y) { define i1 @src_is_mask_xor_fail_notmask(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_xor_fail_notmask( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[Y:%.*]] ; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[NOTMASK]], [[TMP2]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -170,10 +170,10 @@ define i1 @src_is_mask_xor_fail_notmask(i8 %x_in, i8 %y) { define i1 @src_is_mask_select(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_mask_select( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -245,11 +245,11 @@ define i1 @src_is_mask_shl_lshr_fail_not_allones(i8 %x_in, i8 %y, i1 %cond) { define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { ; CHECK-LABEL: @src_is_mask_lshr( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -265,11 +265,11 @@ define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { ; CHECK-LABEL: @src_is_mask_ashr( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -285,9 +285,9 @@ define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_p2_m1( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[P2ORZ:%.*]] = shl i8 2, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = add i8 [[P2ORZ]], -1 +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -301,10 +301,10 @@ define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) { define i1 @src_is_mask_umax(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_umax( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -320,11 +320,11 @@ define i1 @src_is_mask_umax(i8 %x_in, i8 %y) { define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) { ; CHECK-LABEL: @src_is_mask_umin( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -341,12 +341,12 @@ define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) { define i1 @src_is_mask_umin_fail_mismatch(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_umin_fail_mismatch( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 -32) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[MASK]], [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP2]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -361,10 +361,10 @@ define i1 @src_is_mask_umin_fail_mismatch(i8 %x_in, i8 %y) { define i1 @src_is_mask_smax(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_smax( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -380,10 +380,10 @@ define i1 @src_is_mask_smax(i8 %x_in, i8 %y) { define i1 @src_is_mask_smin(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_smin( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; 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: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -399,9 +399,9 @@ define i1 @src_is_mask_smin(i8 %x_in, i8 %y) { define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_bitreverse_not_mask( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; @@ -417,7 +417,7 @@ define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) { define i1 @src_is_notmask_sext(i16 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_notmask_sext( ; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -8, [[Y:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -128 ; CHECK-NEXT: [[TMP2:%.*]] = sext i8 [[M_IN]] to i16 ; CHECK-NEXT: [[R:%.*]] = icmp uge i16 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[R]] @@ -529,12 +529,11 @@ define i1 @src_is_notmask_lshr_shl(i8 %x_in, i8 %y) { define i1 @src_is_notmask_lshr_shl_fail_mismatch_shifts(i8 %x_in, i8 %y, i8 %z) { ; CHECK-LABEL: @src_is_notmask_lshr_shl_fail_mismatch_shifts( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MASK_SHR:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[NMASK:%.*]] = shl i8 [[MASK_SHR]], [[Z:%.*]] -; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[NMASK]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[NMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 diff --git a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll index e95c72b75f97d..0f26be12c39cc 100644 --- a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll +++ b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll @@ -3,6 +3,7 @@ declare i1 @barrier() declare void @llvm.assume(i1) +declare void @use.i8(i8) define i1 @icmp_ult_x_y(i8 %x, i8 %y) { ; CHECK-LABEL: @icmp_ult_x_y( @@ -238,9 +239,9 @@ define i1 @icmp_sle_negx_y_fail_maybe_zero(i8 %x, i8 %y) { define i1 @icmp_eq_x_invertable_y_todo(i8 %x, i1 %y) { ; CHECK-LABEL: @icmp_eq_x_invertable_y_todo( -; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 7, i8 24 +; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25 ; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %yy = select i1 %y, i8 7, i8 24 @@ -251,22 +252,36 @@ define i1 @icmp_eq_x_invertable_y_todo(i8 %x, i1 %y) { define i1 @icmp_eq_x_invertable_y(i8 %x, i8 %y) { ; CHECK-LABEL: @icmp_eq_x_invertable_y( +; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY:%.*]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %yy = xor i8 %y, -1 + %and = and i8 %x, %yy + %r = icmp eq i8 %x, %and + ret i1 %r +} + +define i1 @icmp_eq_x_invertable_y_fail_multiuse(i8 %x, i8 %y) { +; CHECK-LABEL: @icmp_eq_x_invertable_y_fail_multiuse( ; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]] +; CHECK-NEXT: call void @use.i8(i8 [[AND]]) ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] ; CHECK-NEXT: ret i1 [[R]] ; %yy = xor i8 %y, -1 %and = and i8 %x, %yy + call void @use.i8(i8 %and) %r = icmp eq i8 %x, %and ret i1 %r } define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) { ; CHECK-LABEL: @icmp_eq_x_invertable_y2_todo( -; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 7, i8 24 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[YY]], [[AND]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25 +; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %yy = select i1 %y, i8 7, i8 24 @@ -277,9 +292,8 @@ define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) { define i1 @icmp_eq_x_invertable_y2(i8 %x, i8 %y) { ; CHECK-LABEL: @icmp_eq_x_invertable_y2( -; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[YY]] +; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %yy = xor i8 %y, -1