Skip to content

Commit 119194a

Browse files
committed
[InstCombine] Transform (icmp ult/uge (and X, Y), X) -> (icmp ne/eq (and X, Y), X)
eq/ne are generally easier to reason about elsewhere. ult -> ne: https://alive2.llvm.org/ce/z/5wxXGt uge -> eq: https://alive2.llvm.org/ce/z/Dw6kqG Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D145425
1 parent 67ba293 commit 119194a

6 files changed

+55
-28
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4427,6 +4427,30 @@ static Instruction *foldICmpXNegX(ICmpInst &I,
44274427
return nullptr;
44284428
}
44294429

4430+
static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q,
4431+
InstCombinerImpl &IC) {
4432+
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
4433+
// Normalize and operand as operand 0.
4434+
CmpInst::Predicate Pred = I.getPredicate();
4435+
if (match(Op1, m_c_And(m_Specific(Op0), m_Value()))) {
4436+
std::swap(Op0, Op1);
4437+
Pred = ICmpInst::getSwappedPredicate(Pred);
4438+
}
4439+
4440+
if (!match(Op0, m_c_And(m_Specific(Op1), m_Value(A))))
4441+
return nullptr;
4442+
4443+
// (icmp (X & Y) u< X --> (X & Y) != X
4444+
if (Pred == ICmpInst::ICMP_ULT)
4445+
return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
4446+
4447+
// (icmp (X & Y) u>= X --> (X & Y) == X
4448+
if (Pred == ICmpInst::ICMP_UGE)
4449+
return new ICmpInst(ICmpInst::ICMP_EQ, Op0, Op1);
4450+
4451+
return nullptr;
4452+
}
4453+
44304454
static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
44314455
InstCombinerImpl &IC) {
44324456
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
@@ -4956,6 +4980,9 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
49564980
if (Value *V = foldICmpWithLowBitMaskedVal(I, Builder))
49574981
return replaceInstUsesWith(I, V);
49584982

4983+
if (Instruction *R = foldICmpAndXX(I, Q, *this))
4984+
return R;
4985+
49594986
if (Value *V = foldICmpWithTruncSignExtendedVal(I, Builder))
49604987
return replaceInstUsesWith(I, V);
49614988

llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {
6262

6363
define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) {
6464
; CHECK-LABEL: @p2_vec_nonsplat_edgecase0(
65-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 0>
66-
; CHECK-NEXT: [[RET:%.*]] = icmp uge <2 x i8> [[TMP0]], [[X]]
65+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -4, i8 -1>
66+
; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
6767
; CHECK-NEXT: ret <2 x i1> [[RET]]
6868
;
6969
%tmp0 = and <2 x i8> %x, <i8 3, i8 0>
@@ -175,8 +175,8 @@ define i1 @oneuse0(i8 %x) {
175175

176176
define i1 @n0(i8 %x) {
177177
; CHECK-LABEL: @n0(
178-
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4
179-
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[TMP0]], [[X]]
178+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -5
179+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
180180
; CHECK-NEXT: ret i1 [[RET]]
181181
;
182182
%tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
@@ -197,8 +197,8 @@ define i1 @n1(i8 %x, i8 %y, i8 %notx) {
197197

198198
define <2 x i1> @n2(<2 x i8> %x) {
199199
; CHECK-LABEL: @n2(
200-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>
201-
; CHECK-NEXT: [[RET:%.*]] = icmp uge <2 x i8> [[TMP0]], [[X]]
200+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -4, i8 -17>
201+
; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
202202
; CHECK-NEXT: ret <2 x i1> [[RET]]
203203
;
204204
%tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.

llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ define <2 x i1> @p2_vec_nonsplat() {
7575
define <2 x i1> @p2_vec_nonsplat_edgecase0() {
7676
; CHECK-LABEL: @p2_vec_nonsplat_edgecase0(
7777
; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8()
78-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 0>
79-
; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X]], [[TMP0]]
78+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], <i8 -4, i8 -1>
79+
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
8080
; CHECK-NEXT: ret <2 x i1> [[RET]]
8181
;
8282
%x = call <2 x i8> @gen2x8()
@@ -201,8 +201,8 @@ define i1 @oneuse0() {
201201
define i1 @n0() {
202202
; CHECK-LABEL: @n0(
203203
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
204-
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 4
205-
; CHECK-NEXT: [[RET:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
204+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], -5
205+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
206206
; CHECK-NEXT: ret i1 [[RET]]
207207
;
208208
%x = call i8 @gen8()
@@ -227,8 +227,8 @@ define i1 @n1(i8 %y, i8 %notx) {
227227
define <2 x i1> @n2() {
228228
; CHECK-LABEL: @n2(
229229
; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8()
230-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 16>
231-
; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X]], [[TMP0]]
230+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], <i8 -4, i8 -17>
231+
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
232232
; CHECK-NEXT: ret <2 x i1> [[RET]]
233233
;
234234
%x = call <2 x i8> @gen2x8()

llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ define <2 x i1> @p2_vec_nonsplat() {
7575
define <2 x i1> @p2_vec_nonsplat_edgecase0() {
7676
; CHECK-LABEL: @p2_vec_nonsplat_edgecase0(
7777
; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8()
78-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 0>
79-
; CHECK-NEXT: [[RET:%.*]] = icmp ule <2 x i8> [[X]], [[TMP0]]
78+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], <i8 -4, i8 -1>
79+
; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
8080
; CHECK-NEXT: ret <2 x i1> [[RET]]
8181
;
8282
%x = call <2 x i8> @gen2x8()
@@ -189,8 +189,8 @@ define i1 @oneuse0() {
189189
define i1 @n0() {
190190
; CHECK-LABEL: @n0(
191191
; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
192-
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 4
193-
; CHECK-NEXT: [[RET:%.*]] = icmp ule i8 [[X]], [[TMP0]]
192+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], -5
193+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
194194
; CHECK-NEXT: ret i1 [[RET]]
195195
;
196196
%x = call i8 @gen8()
@@ -215,8 +215,8 @@ define i1 @n1(i8 %y, i8 %notx) {
215215
define <2 x i1> @n2() {
216216
; CHECK-LABEL: @n2(
217217
; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8()
218-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 16>
219-
; CHECK-NEXT: [[RET:%.*]] = icmp ule <2 x i8> [[X]], [[TMP0]]
218+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], <i8 -4, i8 -17>
219+
; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
220220
; CHECK-NEXT: ret <2 x i1> [[RET]]
221221
;
222222
%x = call <2 x i8> @gen2x8()

llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {
6262

6363
define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) {
6464
; CHECK-LABEL: @p2_vec_nonsplat_edgecase0(
65-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 0>
66-
; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[TMP0]], [[X]]
65+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -4, i8 -1>
66+
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
6767
; CHECK-NEXT: ret <2 x i1> [[RET]]
6868
;
6969
%tmp0 = and <2 x i8> %x, <i8 3, i8 0>
@@ -186,8 +186,8 @@ define i1 @oneuse0(i8 %x) {
186186

187187
define i1 @n0(i8 %x) {
188188
; CHECK-LABEL: @n0(
189-
; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4
190-
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[TMP0]], [[X]]
189+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -5
190+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
191191
; CHECK-NEXT: ret i1 [[RET]]
192192
;
193193
%tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
@@ -208,8 +208,8 @@ define i1 @n1(i8 %x, i8 %y, i8 %notx) {
208208

209209
define <2 x i1> @n2(<2 x i8> %x) {
210210
; CHECK-LABEL: @n2(
211-
; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>
212-
; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[TMP0]], [[X]]
211+
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -4, i8 -17>
212+
; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
213213
; CHECK-NEXT: ret <2 x i1> [[RET]]
214214
;
215215
%tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.

llvm/test/Transforms/InstCombine/icmp-of-and-x.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ declare void @llvm.assume(i1)
77
define i1 @icmp_ult_x_y(i8 %x, i8 %y) {
88
; CHECK-LABEL: @icmp_ult_x_y(
99
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
10-
; CHECK-NEXT: [[Z:%.*]] = icmp ult i8 [[AND]], [[X]]
10+
; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[AND]], [[X]]
1111
; CHECK-NEXT: ret i1 [[Z]]
1212
;
1313
%and = and i8 %x, %y
@@ -19,7 +19,7 @@ define i1 @icmp_ult_x_y_2(i8 %xx, i8 %y) {
1919
; CHECK-LABEL: @icmp_ult_x_y_2(
2020
; CHECK-NEXT: [[X:%.*]] = mul i8 [[XX:%.*]], [[XX]]
2121
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y:%.*]]
22-
; CHECK-NEXT: [[Z:%.*]] = icmp ugt i8 [[X]], [[AND]]
22+
; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[AND]], [[X]]
2323
; CHECK-NEXT: ret i1 [[Z]]
2424
;
2525
%x = mul i8 %xx, %xx
@@ -31,7 +31,7 @@ define i1 @icmp_ult_x_y_2(i8 %xx, i8 %y) {
3131
define <2 x i1> @icmp_uge_x_y(<2 x i8> %x, <2 x i8> %y) {
3232
; CHECK-LABEL: @icmp_uge_x_y(
3333
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]]
34-
; CHECK-NEXT: [[Z:%.*]] = icmp uge <2 x i8> [[AND]], [[X]]
34+
; CHECK-NEXT: [[Z:%.*]] = icmp eq <2 x i8> [[AND]], [[X]]
3535
; CHECK-NEXT: ret <2 x i1> [[Z]]
3636
;
3737
%and = and <2 x i8> %x, %y
@@ -43,7 +43,7 @@ define i1 @icmp_uge_x_y_2(i8 %xx, i8 %y) {
4343
; CHECK-LABEL: @icmp_uge_x_y_2(
4444
; CHECK-NEXT: [[X:%.*]] = mul i8 [[XX:%.*]], [[XX]]
4545
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y:%.*]]
46-
; CHECK-NEXT: [[Z:%.*]] = icmp ule i8 [[X]], [[AND]]
46+
; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[AND]], [[X]]
4747
; CHECK-NEXT: ret i1 [[Z]]
4848
;
4949
%x = mul i8 %xx, %xx

0 commit comments

Comments
 (0)