Skip to content

Commit e9c68c6

Browse files
authored
[InstCombine] Match range check pattern with SExt (#118910)
= Background We optimize range check patterns like the following: ``` %n_not_negative = icmp sge i32 %n, 0 call void @llvm.assume(i1 %n_not_negative) %a = icmp sge i32 %x, 0 %b = icmp slt i32 %x, %n %c = and i1 %a, %b ``` to a single unsigned comparison: ``` %n_not_negative = icmp sge i32 %n, 0 call void @llvm.assume(i1 %n_not_negative) %c = icmp ult i32 %x, %n ``` = Extended Pattern This adds support for a variant of this pattern where the upper range is compared with a sign extended value: ``` %n_not_negative = icmp sge i64 %n, 0 call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %a = icmp sge i32 %x, 0 %b = icmp slt i64 %x_sext, %n %c = and i1 %a, %b ``` is now optimized to: ``` %n_not_negative = icmp sge i64 %n, 0 call void @llvm.assume(i1 %n_not_negative) %x_sext = sext i32 %x to i64 %c = icmp ult i64 %x_sext, %n ``` Alive2: https://alive2.llvm.org/ce/z/XVuz9L
1 parent fd57946 commit e9c68c6

File tree

2 files changed

+144
-4
lines changed

2 files changed

+144
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,13 +695,17 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
695695
Cmp1->getPredicate());
696696

697697
Value *Input = Cmp0->getOperand(0);
698+
Value *Cmp1Op0 = Cmp1->getOperand(0);
699+
Value *Cmp1Op1 = Cmp1->getOperand(1);
698700
Value *RangeEnd;
699-
if (Cmp1->getOperand(0) == Input) {
701+
if (match(Cmp1Op0, m_SExtOrSelf(m_Specific(Input)))) {
700702
// For the upper range compare we have: icmp x, n
701-
RangeEnd = Cmp1->getOperand(1);
702-
} else if (Cmp1->getOperand(1) == Input) {
703+
Input = Cmp1Op0;
704+
RangeEnd = Cmp1Op1;
705+
} else if (match(Cmp1Op1, m_SExtOrSelf(m_Specific(Input)))) {
703706
// For the upper range compare we have: icmp n, x
704-
RangeEnd = Cmp1->getOperand(0);
707+
Input = Cmp1Op1;
708+
RangeEnd = Cmp1Op0;
705709
Pred1 = ICmpInst::getSwappedPredicate(Pred1);
706710
} else {
707711
return nullptr;

llvm/test/Transforms/InstCombine/range-check.ll

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ define i1 @test_and1_logical(i32 %x, i32 %n) {
3232
ret i1 %c
3333
}
3434

35+
define i1 @test_and1_sext(i32 %x, i64 %n) {
36+
; CHECK-LABEL: @test_and1_sext(
37+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
38+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
39+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
40+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]]
41+
; CHECK-NEXT: ret i1 [[C]]
42+
;
43+
%n_not_negative = icmp sge i64 %n, 0
44+
call void @llvm.assume(i1 %n_not_negative)
45+
%x_sext = sext i32 %x to i64
46+
%a = icmp sge i32 %x, 0
47+
%b = icmp slt i64 %x_sext, %n
48+
%c = and i1 %a, %b
49+
ret i1 %c
50+
}
51+
3552
define i1 @test_and2(i32 %x, i32 %n) {
3653
; CHECK-LABEL: @test_and2(
3754
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -60,6 +77,23 @@ define i1 @test_and2_logical(i32 %x, i32 %n) {
6077
ret i1 %c
6178
}
6279

80+
define i1 @test_and2_sext(i32 %x, i64 %n) {
81+
; CHECK-LABEL: @test_and2_sext(
82+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
83+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
84+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
85+
; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]]
86+
; CHECK-NEXT: ret i1 [[C]]
87+
;
88+
%n_not_negative = icmp sge i64 %n, 0
89+
call void @llvm.assume(i1 %n_not_negative)
90+
%x_sext = sext i32 %x to i64
91+
%a = icmp sgt i32 %x, -1
92+
%b = icmp sle i64 %x_sext, %n
93+
%c = and i1 %a, %b
94+
ret i1 %c
95+
}
96+
6397
define i1 @test_and3(i32 %x, i32 %n) {
6498
; CHECK-LABEL: @test_and3(
6599
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -86,6 +120,23 @@ define i1 @test_and3_logical(i32 %x, i32 %n) {
86120
ret i1 %c
87121
}
88122

123+
define i1 @test_and3_sext(i32 %x, i64 %n) {
124+
; CHECK-LABEL: @test_and3_sext(
125+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
126+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
127+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
128+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]]
129+
; CHECK-NEXT: ret i1 [[C]]
130+
;
131+
%n_not_negative = icmp sge i64 %n, 0
132+
call void @llvm.assume(i1 %n_not_negative)
133+
%x_sext = sext i32 %x to i64
134+
%a = icmp sgt i64 %n, %x_sext
135+
%b = icmp sge i32 %x, 0
136+
%c = and i1 %a, %b
137+
ret i1 %c
138+
}
139+
89140
define i1 @test_and4(i32 %x, i32 %n) {
90141
; CHECK-LABEL: @test_and4(
91142
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -112,6 +163,23 @@ define i1 @test_and4_logical(i32 %x, i32 %n) {
112163
ret i1 %c
113164
}
114165

166+
define i1 @test_and4_sext(i32 %x, i64 %n) {
167+
; CHECK-LABEL: @test_and4_sext(
168+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
169+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
170+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
171+
; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]]
172+
; CHECK-NEXT: ret i1 [[C]]
173+
;
174+
%n_not_negative = icmp sge i64 %n, 0
175+
call void @llvm.assume(i1 %n_not_negative)
176+
%x_sext = sext i32 %x to i64
177+
%a = icmp sge i64 %n, %x_sext
178+
%b = icmp sge i32 %x, 0
179+
%c = and i1 %a, %b
180+
ret i1 %c
181+
}
182+
115183
define i1 @test_or1(i32 %x, i32 %n) {
116184
; CHECK-LABEL: @test_or1(
117185
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -140,6 +208,23 @@ define i1 @test_or1_logical(i32 %x, i32 %n) {
140208
ret i1 %c
141209
}
142210

211+
define i1 @test_or1_sext(i32 %x, i64 %n) {
212+
; CHECK-LABEL: @test_or1_sext(
213+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
214+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
215+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
216+
; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]]
217+
; CHECK-NEXT: ret i1 [[C]]
218+
;
219+
%n_not_negative = icmp sge i64 %n, 0
220+
call void @llvm.assume(i1 %n_not_negative)
221+
%x_sext = sext i32 %x to i64
222+
%a = icmp slt i32 %x, 0
223+
%b = icmp sge i64 %x_sext, %n
224+
%c = or i1 %a, %b
225+
ret i1 %c
226+
}
227+
143228
define i1 @test_or2(i32 %x, i32 %n) {
144229
; CHECK-LABEL: @test_or2(
145230
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -168,6 +253,23 @@ define i1 @test_or2_logical(i32 %x, i32 %n) {
168253
ret i1 %c
169254
}
170255

256+
define i1 @test_or2_sext(i32 %x, i64 %n) {
257+
; CHECK-LABEL: @test_or2_sext(
258+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
259+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
260+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
261+
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]]
262+
; CHECK-NEXT: ret i1 [[C]]
263+
;
264+
%n_not_negative = icmp sge i64 %n, 0
265+
call void @llvm.assume(i1 %n_not_negative)
266+
%x_sext = sext i32 %x to i64
267+
%a = icmp sle i32 %x, -1
268+
%b = icmp sgt i64 %x_sext, %n
269+
%c = or i1 %a, %b
270+
ret i1 %c
271+
}
272+
171273
define i1 @test_or3(i32 %x, i32 %n) {
172274
; CHECK-LABEL: @test_or3(
173275
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -194,6 +296,23 @@ define i1 @test_or3_logical(i32 %x, i32 %n) {
194296
ret i1 %c
195297
}
196298

299+
define i1 @test_or3_sext(i32 %x, i64 %n) {
300+
; CHECK-LABEL: @test_or3_sext(
301+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
302+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
303+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
304+
; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]]
305+
; CHECK-NEXT: ret i1 [[C]]
306+
;
307+
%n_not_negative = icmp sge i64 %n, 0
308+
call void @llvm.assume(i1 %n_not_negative)
309+
%x_sext = sext i32 %x to i64
310+
%a = icmp sle i64 %n, %x_sext
311+
%b = icmp slt i32 %x, 0
312+
%c = or i1 %a, %b
313+
ret i1 %c
314+
}
315+
197316
define i1 @test_or4(i32 %x, i32 %n) {
198317
; CHECK-LABEL: @test_or4(
199318
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -220,6 +339,23 @@ define i1 @test_or4_logical(i32 %x, i32 %n) {
220339
ret i1 %c
221340
}
222341

342+
define i1 @test_or4_sext(i32 %x, i64 %n) {
343+
; CHECK-LABEL: @test_or4_sext(
344+
; CHECK-NEXT: [[N_NOT_NEGATIVE:%.*]] = icmp sgt i64 [[NN:%.*]], -1
345+
; CHECK-NEXT: call void @llvm.assume(i1 [[N_NOT_NEGATIVE]])
346+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
347+
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]]
348+
; CHECK-NEXT: ret i1 [[C]]
349+
;
350+
%n_not_negative = icmp sge i64 %n, 0
351+
call void @llvm.assume(i1 %n_not_negative)
352+
%x_sext = sext i32 %x to i64
353+
%a = icmp slt i64 %n, %x_sext
354+
%b = icmp slt i32 %x, 0
355+
%c = or i1 %a, %b
356+
ret i1 %c
357+
}
358+
223359
; Negative tests
224360

225361
define i1 @negative1(i32 %x, i32 %n) {

0 commit comments

Comments
 (0)