Skip to content

Commit c1ad064

Browse files
authored
[InstCombine] Fold icmp spred (and X, highmask), C1 into icmp spred X, C2 (#118197)
Alive2: https://alive2.llvm.org/ce/z/Ffg64g Closes #104772.
1 parent d097070 commit c1ad064

File tree

4 files changed

+124
-15
lines changed

4 files changed

+124
-15
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,6 +1760,17 @@ Instruction *InstCombinerImpl::foldICmpAndConstConst(ICmpInst &Cmp,
17601760
if (!match(And, m_And(m_Value(X), m_APInt(C2))))
17611761
return nullptr;
17621762

1763+
// (and X, highmask) s> [0, ~highmask] --> X s> ~highmask
1764+
if (Cmp.getPredicate() == ICmpInst::ICMP_SGT && C1.ule(~*C2) &&
1765+
C2->isNegatedPowerOf2())
1766+
return new ICmpInst(ICmpInst::ICMP_SGT, X,
1767+
ConstantInt::get(X->getType(), ~*C2));
1768+
// (and X, highmask) s< [1, -highmask] --> X s< -highmask
1769+
if (Cmp.getPredicate() == ICmpInst::ICMP_SLT && !C1.isSignMask() &&
1770+
(C1 - 1).ule(~*C2) && C2->isNegatedPowerOf2() && !C2->isSignMask())
1771+
return new ICmpInst(ICmpInst::ICMP_SLT, X,
1772+
ConstantInt::get(X->getType(), -*C2));
1773+
17631774
// Don't perform the following transforms if the AND has multiple uses
17641775
if (!And->hasOneUse())
17651776
return nullptr;

llvm/test/Transforms/InstCombine/icmp-binop.ll

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,110 @@ false:
252252
call void @use64(i64 %v)
253253
ret i1 false
254254
}
255+
256+
define i1 @test_icmp_sgt_and_negpow2_zero(i32 %add) {
257+
; CHECK-LABEL: @test_icmp_sgt_and_negpow2_zero(
258+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD:%.*]], 7
259+
; CHECK-NEXT: ret i1 [[CMP]]
260+
;
261+
%and = and i32 %add, -8
262+
%cmp = icmp sgt i32 %and, 0
263+
ret i1 %cmp
264+
}
265+
266+
define i1 @test_icmp_slt_and_negpow2_one(i32 %add) {
267+
; CHECK-LABEL: @test_icmp_slt_and_negpow2_one(
268+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD:%.*]], 8
269+
; CHECK-NEXT: ret i1 [[CMP]]
270+
;
271+
%and = and i32 %add, -8
272+
%cmp = icmp slt i32 %and, 1
273+
ret i1 %cmp
274+
}
275+
276+
define i1 @test_icmp_sgt_and_negpow2_nonzero(i32 %add) {
277+
; CHECK-LABEL: @test_icmp_sgt_and_negpow2_nonzero(
278+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD:%.*]], -8
279+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[AND]], -2
280+
; CHECK-NEXT: ret i1 [[CMP]]
281+
;
282+
%and = and i32 %add, -8
283+
%cmp = icmp sgt i32 %and, -2
284+
ret i1 %cmp
285+
}
286+
287+
define i1 @test_icmp_sgt_and_nonnegpow2_zero(i32 %add) {
288+
; CHECK-LABEL: @test_icmp_sgt_and_nonnegpow2_zero(
289+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD:%.*]], 8
290+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
291+
; CHECK-NEXT: ret i1 [[CMP]]
292+
;
293+
%and = and i32 %add, 8
294+
%cmp = icmp sgt i32 %and, 0
295+
ret i1 %cmp
296+
}
297+
298+
define i1 @test_icmp_ult_and_negpow2_one(i32 %add) {
299+
; CHECK-LABEL: @test_icmp_ult_and_negpow2_one(
300+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD:%.*]], 8
301+
; CHECK-NEXT: ret i1 [[CMP]]
302+
;
303+
%and = and i32 %add, -8
304+
%cmp = icmp ult i32 %and, 1
305+
ret i1 %cmp
306+
}
307+
308+
define i1 @test_imply_dom_condition(i32 %add) {
309+
; CHECK-LABEL: @test_imply_dom_condition(
310+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD:%.*]], 7
311+
; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
312+
; CHECK-NEXT: ret i1 false
313+
;
314+
%and = and i32 %add, -8
315+
%cmp = icmp sgt i32 %and, 0
316+
tail call void @llvm.assume(i1 %cmp)
317+
%min.iters.check = icmp ult i32 %and, 8
318+
ret i1 %min.iters.check
319+
}
320+
321+
define i1 @test_icmp_slt_and_negpow2_c(i32 %add) {
322+
; CHECK-LABEL: @test_icmp_slt_and_negpow2_c(
323+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD:%.*]], 32
324+
; CHECK-NEXT: ret i1 [[CMP]]
325+
;
326+
%and = and i32 %add, -32
327+
%cmp = icmp slt i32 %and, 16
328+
ret i1 %cmp
329+
}
330+
331+
define i1 @test_icmp_slt_and_negpow2_invalid_c(i32 %add) {
332+
; CHECK-LABEL: @test_icmp_slt_and_negpow2_invalid_c(
333+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD:%.*]], -32
334+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[AND]], 48
335+
; CHECK-NEXT: ret i1 [[CMP]]
336+
;
337+
%and = and i32 %add, -32
338+
%cmp = icmp slt i32 %and, 48
339+
ret i1 %cmp
340+
}
341+
342+
define i1 @test_icmp_sgt_and_negpow2_c(i32 %add) {
343+
; CHECK-LABEL: @test_icmp_sgt_and_negpow2_c(
344+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD:%.*]], 31
345+
; CHECK-NEXT: ret i1 [[CMP]]
346+
;
347+
%and = and i32 %add, -32
348+
%cmp = icmp sgt i32 %and, 16
349+
ret i1 %cmp
350+
}
351+
352+
define i1 @test_icmp_sgt_and_negpow2_invalid_c(i32 %add) {
353+
; CHECK-LABEL: @test_icmp_sgt_and_negpow2_invalid_c(
354+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD:%.*]], -32
355+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[AND]], 48
356+
; CHECK-NEXT: ret i1 [[CMP]]
357+
;
358+
%and = and i32 %add, -32
359+
%cmp = icmp sgt i32 %and, 48
360+
ret i1 %cmp
361+
}

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,8 +2197,7 @@ define i1 @icmp_ashr_and_overshift(i8 %X) {
21972197

21982198
define i1 @icmp_and_ashr_neg_and_legal(i8 %x) {
21992199
; CHECK-LABEL: @icmp_and_ashr_neg_and_legal(
2200-
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -32
2201-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 16
2200+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 32
22022201
; CHECK-NEXT: ret i1 [[CMP]]
22032202
;
22042203
%ashr = ashr i8 %x, 4

llvm/test/Transforms/InstCombine/pr17827.ll

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
define i1 @test_shift_and_cmp_not_changed1(i8 %p) {
66
; CHECK-LABEL: @test_shift_and_cmp_not_changed1(
77
; CHECK-NEXT: [[SHLP:%.*]] = shl i8 [[P:%.*]], 5
8-
; CHECK-NEXT: [[ANDP:%.*]] = and i8 [[SHLP]], -64
9-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ANDP]], 32
8+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SHLP]], 64
109
; CHECK-NEXT: ret i1 [[CMP]]
1110
;
1211
%shlp = shl i8 %p, 5
@@ -18,10 +17,7 @@ define i1 @test_shift_and_cmp_not_changed1(i8 %p) {
1817
; With arithmetic right shift, the comparison should not be modified.
1918
define i1 @test_shift_and_cmp_not_changed2(i8 %p) {
2019
; CHECK-LABEL: @test_shift_and_cmp_not_changed2(
21-
; CHECK-NEXT: [[SHLP:%.*]] = ashr i8 [[P:%.*]], 5
22-
; CHECK-NEXT: [[ANDP:%.*]] = and i8 [[SHLP]], -64
23-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ANDP]], 32
24-
; CHECK-NEXT: ret i1 [[CMP]]
20+
; CHECK-NEXT: ret i1 true
2521
;
2622
%shlp = ashr i8 %p, 5
2723
%andp = and i8 %shlp, -64
@@ -34,8 +30,7 @@ define i1 @test_shift_and_cmp_not_changed2(i8 %p) {
3430
define i1 @test_shift_and_cmp_changed1(i8 %p, i8 %q) {
3531
; CHECK-LABEL: @test_shift_and_cmp_changed1(
3632
; CHECK-NEXT: [[ANDP:%.*]] = shl i8 [[P:%.*]], 5
37-
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[ANDP]], -64
38-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 32
33+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ANDP]], 33
3934
; CHECK-NEXT: ret i1 [[CMP]]
4035
;
4136
%andp = and i8 %p, 6
@@ -50,8 +45,7 @@ define i1 @test_shift_and_cmp_changed1(i8 %p, i8 %q) {
5045
define <2 x i1> @test_shift_and_cmp_changed1_vec(<2 x i8> %p, <2 x i8> %q) {
5146
; CHECK-LABEL: @test_shift_and_cmp_changed1_vec(
5247
; CHECK-NEXT: [[ANDP:%.*]] = shl <2 x i8> [[P:%.*]], splat (i8 5)
53-
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[ANDP]], splat (i8 -64)
54-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], splat (i8 32)
48+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[ANDP]], splat (i8 33)
5549
; CHECK-NEXT: ret <2 x i1> [[CMP]]
5650
;
5751
%andp = and <2 x i8> %p, <i8 6, i8 6>
@@ -91,9 +85,7 @@ define <2 x i1> @test_shift_and_cmp_changed2_vec(<2 x i8> %p) {
9185
; nsw on the shift should not affect the comparison.
9286
define i1 @test_shift_and_cmp_changed3(i8 %p) {
9387
; CHECK-LABEL: @test_shift_and_cmp_changed3(
94-
; CHECK-NEXT: [[SHLP:%.*]] = shl nsw i8 [[P:%.*]], 5
95-
; CHECK-NEXT: [[ANDP:%.*]] = and i8 [[SHLP]], -64
96-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ANDP]], 32
88+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[P:%.*]], 2
9789
; CHECK-NEXT: ret i1 [[CMP]]
9890
;
9991
%shlp = shl nsw i8 %p, 5

0 commit comments

Comments
 (0)