Skip to content

Commit 193b3d6

Browse files
committed
[InstCombine] Recognize (icmp eq/ne (and X, ~Mask), 0) pattern in foldICmpWithLowBitMaskedVal
`(icmp eq/ne (and X, ~Mask), 0)` is equivilent to `(icmp eq/ne (and X, Mask), X` and we sometimes generate the former pattern intentionally to reduce number of uses of `X`. Proof: https://alive2.llvm.org/ce/z/3u-usC Differential Revision: https://reviews.llvm.org/D159329 Closes #81562
1 parent d77eb9e commit 193b3d6

File tree

6 files changed

+36
-42
lines changed

6 files changed

+36
-42
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4163,6 +4163,7 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q,
41634163
/// a check for a lossy truncation.
41644164
/// Folds:
41654165
/// icmp SrcPred (x & Mask), x to icmp DstPred x, Mask
4166+
/// icmp eq/ne (x & ~Mask), 0 to icmp DstPred x, Mask
41664167
/// Where Mask is some pattern that produces all-ones in low bits:
41674168
/// (-1 >> y)
41684169
/// ((-1 << y) >> y) <- non-canonical, has extra uses
@@ -4174,7 +4175,7 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q,
41744175
static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0,
41754176
Value *Op1, const SimplifyQuery &Q,
41764177
InstCombiner &IC) {
4177-
Value *M;
4178+
Value *X, *M;
41784179
bool NeedsNot = false;
41794180

41804181
auto CheckMask = [&](Value *V, bool Not) {
@@ -4183,11 +4184,20 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0,
41834184
return isMaskOrZero(V, Not, Q);
41844185
};
41854186

4186-
if (!match(Op0, m_c_And(m_Specific(Op1), m_Value(M))))
4187-
return nullptr;
4188-
4189-
if (!CheckMask(M, /*Not*/ false))
4187+
if (match(Op0, m_c_And(m_Specific(Op1), m_Value(M))) &&
4188+
CheckMask(M, /*Not*/ false)) {
4189+
X = Op1;
4190+
} else if (match(Op1, m_Zero()) && ICmpInst::isEquality(Pred) &&
4191+
match(Op0, m_OneUse(m_And(m_Value(X), m_Value(M))))) {
4192+
NeedsNot = true;
4193+
if (IC.isFreeToInvert(X, X->hasOneUse()) && CheckMask(X, /*Not*/ true))
4194+
std::swap(X, M);
4195+
else if (!IC.isFreeToInvert(M, M->hasOneUse()) ||
4196+
!CheckMask(M, /*Not*/ true))
4197+
return nullptr;
4198+
} else {
41904199
return nullptr;
4200+
}
41914201

41924202
ICmpInst::Predicate DstPred;
41934203
switch (Pred) {
@@ -4258,7 +4268,7 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0,
42584268

42594269
if (NeedsNot)
42604270
M = IC.Builder.CreateNot(M);
4261-
return IC.Builder.CreateICmp(DstPred, Op1, M);
4271+
return IC.Builder.CreateICmp(DstPred, X, M);
42624272
}
42634273

42644274
/// Some comparisons can be simplified.

llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@ define i1 @src_is_mask_zext_fail_not_mask(i16 %x_in, i8 %y) {
4141
define i1 @src_is_mask_sext(i16 %x_in, i8 %y) {
4242
; CHECK-LABEL: @src_is_mask_sext(
4343
; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123
44-
; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 -32, [[Y:%.*]]
45-
; CHECK-NEXT: [[NOTMASK:%.*]] = sext i8 [[TMP1]] to i16
46-
; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[NOTMASK]]
47-
; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0
44+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 31, [[Y:%.*]]
45+
; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i8 [[TMP1]] to i16
46+
; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[TMP2]]
4847
; CHECK-NEXT: ret i1 [[R]]
4948
;
5049
%x = xor i16 %x_in, 123
@@ -212,9 +211,7 @@ define i1 @src_is_mask_shl_lshr(i8 %x_in, i8 %y, i1 %cond) {
212211
; CHECK-LABEL: @src_is_mask_shl_lshr(
213212
; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122
214213
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]]
215-
; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], -1
216-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]]
217-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0
214+
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[TMP1]]
218215
; CHECK-NEXT: ret i1 [[R]]
219216
;
220217
%x = xor i8 %x_in, 123
@@ -558,11 +555,10 @@ define i1 @src_is_notmask_neg_p2(i8 %x_in, i8 %y) {
558555
define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) {
559556
; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable(
560557
; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
561-
; CHECK-NEXT: [[NY:%.*]] = sub i8 0, [[Y:%.*]]
562-
; CHECK-NEXT: [[P2:%.*]] = and i8 [[NY]], [[Y]]
563-
; CHECK-NEXT: [[NOTMASK:%.*]] = sub i8 0, [[P2]]
564-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]]
565-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
558+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
559+
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1
560+
; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]]
561+
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]]
566562
; CHECK-NEXT: ret i1 [[R]]
567563
;
568564
%x = xor i8 %x_in, 123

llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_lshr_and_negC_eq(<4 x i32> %x, <4 x i32> %y) {
8484
define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
8585
; CHECK-LABEL: @vec_lshr_and_negC_eq_undef1(
8686
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
87-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 undef, i32 -8, i32 -8>
88-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer
87+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], <i32 8, i32 8, i32 8, i32 8>
8988
; CHECK-NEXT: ret <4 x i1> [[R]]
9089
;
9190
%lshr = lshr <4 x i32> %x, %y
@@ -97,8 +96,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
9796
define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
9897
; CHECK-LABEL: @vec_lshr_and_negC_eq_undef2(
9998
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
100-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 -8, i32 -8, i32 -8>
101-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
99+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], <i32 8, i32 8, i32 8, i32 8>
102100
; CHECK-NEXT: ret <4 x i1> [[R]]
103101
;
104102
%lshr = lshr <4 x i32> %x, %y
@@ -110,8 +108,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
110108
define <4 x i1> @vec_lshr_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) {
111109
; CHECK-LABEL: @vec_lshr_and_negC_eq_undef3(
112110
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
113-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -8, i32 -8, i32 undef, i32 -8>
114-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
111+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], <i32 8, i32 8, i32 8, i32 8>
115112
; CHECK-NEXT: ret <4 x i1> [[R]]
116113
;
117114
%lshr = lshr <4 x i32> %x, %y

llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq(<4 x i32> %x, <4 x i32> %y) {
8484
define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
8585
; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef1(
8686
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
87-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -2147483648, i32 undef, i32 -2147483648, i32 -2147483648>
88-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer
87+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], <i32 -1, i32 -1, i32 -1, i32 -1>
8988
; CHECK-NEXT: ret <4 x i1> [[R]]
9089
;
9190
%lshr = lshr <4 x i32> %x, %y
@@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y
9796
define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
9897
; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef2(
9998
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
100-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648>
101-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 undef, i32 0, i32 0, i32 0>
99+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], <i32 -1, i32 -1, i32 -1, i32 -1>
102100
; CHECK-NEXT: ret <4 x i1> [[R]]
103101
;
104102
%lshr = lshr <4 x i32> %x, %y
@@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y
110108
define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) {
111109
; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef3(
112110
; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
113-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], <i32 -2147483648, i32 undef, i32 -2147483648, i32 -2147483648>
114-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
111+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], <i32 -1, i32 -1, i32 -1, i32 -1>
115112
; CHECK-NEXT: ret <4 x i1> [[R]]
116113
;
117114
%lshr = lshr <4 x i32> %x, %y

llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_shl_and_negC_eq(<4 x i32> %x, <4 x i32> %y) {
8484
define <4 x i1> @vec_shl_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
8585
; CHECK-LABEL: @vec_shl_and_negC_eq_undef1(
8686
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
87-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -8, i32 undef, i32 -8, i32 -8>
88-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer
87+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 8, i32 8, i32 8, i32 8>
8988
; CHECK-NEXT: ret <4 x i1> [[R]]
9089
;
9190
%shl = shl <4 x i32> %x, %y
@@ -97,8 +96,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
9796
define <4 x i1> @vec_shl_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
9897
; CHECK-LABEL: @vec_shl_and_negC_eq_undef2(
9998
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
100-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -8, i32 -8, i32 -8, i32 -8>
101-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
99+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 8, i32 8, i32 8, i32 8>
102100
; CHECK-NEXT: ret <4 x i1> [[R]]
103101
;
104102
%shl = shl <4 x i32> %x, %y
@@ -110,8 +108,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
110108
define <4 x i1> @vec_shl_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) {
111109
; CHECK-LABEL: @vec_shl_and_negC_eq_undef3(
112110
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
113-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -8, i32 -8, i32 undef, i32 -8>
114-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
111+
; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], <i32 8, i32 8, i32 8, i32 8>
115112
; CHECK-NEXT: ret <4 x i1> [[R]]
116113
;
117114
%shl = shl <4 x i32> %x, %y

llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq(<4 x i32> %x, <4 x i32> %y) {
8484
define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) {
8585
; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef1(
8686
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
87-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -2147483648, i32 undef, i32 -2147483648, i32 -2147483648>
88-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer
87+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], <i32 -1, i32 -1, i32 -1, i32 -1>
8988
; CHECK-NEXT: ret <4 x i1> [[R]]
9089
;
9190
%shl = shl <4 x i32> %x, %y
@@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y)
9796
define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) {
9897
; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef2(
9998
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
100-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648>
101-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 undef, i32 0, i32 0, i32 0>
99+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], <i32 -1, i32 -1, i32 -1, i32 -1>
102100
; CHECK-NEXT: ret <4 x i1> [[R]]
103101
;
104102
%shl = shl <4 x i32> %x, %y
@@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y)
110108
define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) {
111109
; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef3(
112110
; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
113-
; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], <i32 -2147483648, i32 undef, i32 -2147483648, i32 -2147483648>
114-
; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], <i32 0, i32 0, i32 0, i32 undef>
111+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], <i32 -1, i32 -1, i32 -1, i32 -1>
115112
; CHECK-NEXT: ret <4 x i1> [[R]]
116113
;
117114
%shl = shl <4 x i32> %x, %y

0 commit comments

Comments
 (0)