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 @@ -4083,6 +4083,7 @@ /// a check for a lossy truncation. /// Folds: /// icmp SrcPred (x & Mask), x to icmp DstPred x, Mask +/// icmp eq/ne (x & ~Mask), 0 to icmp DstPred x, Mask /// Where Mask is some pattern that produces all-ones in low bits: /// (-1 >> y) /// ((-1 << y) >> y) <- non-canonical, has extra uses @@ -4115,6 +4116,16 @@ SrcPred = ICmpInst::getSwappedPredicate(Pred); return CheckMask(M, /*Not*/ false); } + if (OpNo == 1 && match(I.getOperand(1), m_Zero()) && + ICmpInst::isEquality(Pred) && + match(I.getOperand(0), m_OneUse(m_And(m_Value(X), m_Value(M))))) { + NeedsNot = true; + if (IC.isFreeToInvert(X, X->hasOneUse()) && CheckMask(X, /*Not*/ true)) { + std::swap(X, M); + return true; + } + return IC.isFreeToInvert(M, M->hasOneUse()) && CheckMask(M, /*Not*/ true); + } return false; }; 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 @@ -50,9 +50,7 @@ ; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 31, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16 -; CHECK-NEXT: [[NOTMASK:%.*]] = xor i16 [[MASK]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -220,9 +218,7 @@ ; CHECK-LABEL: @src_is_mask_shl_lshr( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]] -; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -449,10 +445,8 @@ ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 ; CHECK-NEXT: [[NMASK:%.*]] = shl i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) -; CHECK-NEXT: [[NOTMASK0:%.*]] = xor i8 [[MASK]], -1 -; CHECK-NEXT: [[NOTMASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 -8 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND:%.*]], i8 [[MASK]], i8 7 +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -550,9 +544,7 @@ ; CHECK-NEXT: [[P2:%.*]] = and i8 [[NY]], [[Y]] ; CHECK-NEXT: [[NMASK:%.*]] = sub i8 0, [[P2]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) -; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[MASK]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -569,11 +561,10 @@ define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[NY:%.*]] = sub i8 0, [[Y:%.*]] -; CHECK-NEXT: [[P2:%.*]] = and i8 [[NY]], [[Y]] -; CHECK-NEXT: [[NOTMASK:%.*]] = sub i8 0, [[P2]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1 +; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 diff --git a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef2( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef3( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef2( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef3( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef1( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef2( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef3( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef1( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef2( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef3( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y