Skip to content

Commit 689547b

Browse files
committed
Match range check pattern with SExt
= Background LLVM optimizes range check patterns like the following: ``` %nn = and i32 %n, 2147483647 ; %nn is non-negative %a = icmp sge i32 %x, 0 %b = icmp slt i32 %x, %nn %c = and i1 %a, %b ``` to a single unsigned comparison: ``` %nn = and i32 %n, 2147483647 %c = icmp ult i32 %x, %nn ``` = Extended Pattern This adds support for an extended version of this pattern where the upper range is compared with an `sext` value. Example: ``` %nn = and i64 %n, 2147483647 %x_sext = sext i32 %x to i64 %a = icmp sge i32 %x, 0 %b = icmp slt i64 %x_sext, %nn %c = and i1 %a, %b ``` is now optimized to: ``` %nn = and i64 %n, 2147483647 %x_sext = sext i32 %x to i64 %c = icmp ugt i64 %nn, %x_sext ``` In Alive2: https://alive2.llvm.org/ce/z/Ff7KJ_
1 parent 794afe0 commit 689547b

File tree

2 files changed

+137
-4
lines changed

2 files changed

+137
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,14 +695,27 @@ 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 (Cmp1Op0 == 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+
RangeEnd = Cmp1Op1;
704+
} else if (isa<SExtInst>(Cmp1Op0) &&
705+
cast<SExtInst>(Cmp1Op0)->getOperand(0) == Input) {
706+
// For the upper range compare we have: icmp (sext x), n
707+
Input = Cmp1Op0;
708+
RangeEnd = Cmp1Op1;
709+
} else if (Cmp1Op1 == Input) {
703710
// For the upper range compare we have: icmp n, x
704-
RangeEnd = Cmp1->getOperand(0);
705711
Pred1 = ICmpInst::getSwappedPredicate(Pred1);
712+
RangeEnd = Cmp1Op0;
713+
} else if (isa<SExtInst>(Cmp1Op1) &&
714+
cast<SExtInst>(Cmp1Op1)->getOperand(0) == Input) {
715+
// For the upper range compare we have: icmp n, (sext x)
716+
Pred1 = ICmpInst::getSwappedPredicate(Pred1);
717+
Input = Cmp1Op1;
718+
RangeEnd = Cmp1Op0;
706719
} else {
707720
return nullptr;
708721
}

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

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ 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: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
38+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
39+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]]
40+
; CHECK-NEXT: ret i1 [[C]]
41+
;
42+
%nn = and i64 %n, 2147483647
43+
%x_sext = sext i32 %x to i64
44+
%a = icmp sge i32 %x, 0
45+
%b = icmp slt i64 %x_sext, %nn
46+
%c = and i1 %a, %b
47+
ret i1 %c
48+
}
49+
3550
define i1 @test_and2(i32 %x, i32 %n) {
3651
; CHECK-LABEL: @test_and2(
3752
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -60,6 +75,21 @@ define i1 @test_and2_logical(i32 %x, i32 %n) {
6075
ret i1 %c
6176
}
6277

78+
define i1 @test_and2_sext(i32 %x, i64 %n) {
79+
; CHECK-LABEL: @test_and2_sext(
80+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
81+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
82+
; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]]
83+
; CHECK-NEXT: ret i1 [[C]]
84+
;
85+
%nn = and i64 %n, 2147483647
86+
%x_sext = sext i32 %x to i64
87+
%a = icmp sgt i32 %x, -1
88+
%b = icmp sle i64 %x_sext, %nn
89+
%c = and i1 %a, %b
90+
ret i1 %c
91+
}
92+
6393
define i1 @test_and3(i32 %x, i32 %n) {
6494
; CHECK-LABEL: @test_and3(
6595
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -86,6 +116,21 @@ define i1 @test_and3_logical(i32 %x, i32 %n) {
86116
ret i1 %c
87117
}
88118

119+
define i1 @test_and3_sext(i32 %x, i64 %n) {
120+
; CHECK-LABEL: @test_and3_sext(
121+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
122+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
123+
; CHECK-NEXT: [[C:%.*]] = icmp ugt i64 [[NN]], [[X_SEXT]]
124+
; CHECK-NEXT: ret i1 [[C]]
125+
;
126+
%nn = and i64 %n, 2147483647
127+
%x_sext = sext i32 %x to i64
128+
%a = icmp sgt i64 %nn, %x_sext
129+
%b = icmp sge i32 %x, 0
130+
%c = and i1 %a, %b
131+
ret i1 %c
132+
}
133+
89134
define i1 @test_and4(i32 %x, i32 %n) {
90135
; CHECK-LABEL: @test_and4(
91136
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -112,6 +157,21 @@ define i1 @test_and4_logical(i32 %x, i32 %n) {
112157
ret i1 %c
113158
}
114159

160+
define i1 @test_and4_sext(i32 %x, i64 %n) {
161+
; CHECK-LABEL: @test_and4_sext(
162+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
163+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
164+
; CHECK-NEXT: [[C:%.*]] = icmp uge i64 [[NN]], [[X_SEXT]]
165+
; CHECK-NEXT: ret i1 [[C]]
166+
;
167+
%nn = and i64 %n, 2147483647
168+
%x_sext = sext i32 %x to i64
169+
%a = icmp sge i64 %nn, %x_sext
170+
%b = icmp sge i32 %x, 0
171+
%c = and i1 %a, %b
172+
ret i1 %c
173+
}
174+
115175
define i1 @test_or1(i32 %x, i32 %n) {
116176
; CHECK-LABEL: @test_or1(
117177
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -140,6 +200,21 @@ define i1 @test_or1_logical(i32 %x, i32 %n) {
140200
ret i1 %c
141201
}
142202

203+
define i1 @test_or1_sext(i32 %x, i64 %n) {
204+
; CHECK-LABEL: @test_or1_sext(
205+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
206+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
207+
; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]]
208+
; CHECK-NEXT: ret i1 [[C]]
209+
;
210+
%nn = and i64 %n, 2147483647
211+
%x_sext = sext i32 %x to i64
212+
%a = icmp slt i32 %x, 0
213+
%b = icmp sge i64 %x_sext, %nn
214+
%c = or i1 %a, %b
215+
ret i1 %c
216+
}
217+
143218
define i1 @test_or2(i32 %x, i32 %n) {
144219
; CHECK-LABEL: @test_or2(
145220
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -168,6 +243,21 @@ define i1 @test_or2_logical(i32 %x, i32 %n) {
168243
ret i1 %c
169244
}
170245

246+
define i1 @test_or2_sext(i32 %x, i64 %n) {
247+
; CHECK-LABEL: @test_or2_sext(
248+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
249+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
250+
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]]
251+
; CHECK-NEXT: ret i1 [[C]]
252+
;
253+
%nn = and i64 %n, 2147483647
254+
%x_sext = sext i32 %x to i64
255+
%a = icmp sle i32 %x, -1
256+
%b = icmp sgt i64 %x_sext, %nn
257+
%c = or i1 %a, %b
258+
ret i1 %c
259+
}
260+
171261
define i1 @test_or3(i32 %x, i32 %n) {
172262
; CHECK-LABEL: @test_or3(
173263
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -194,6 +284,21 @@ define i1 @test_or3_logical(i32 %x, i32 %n) {
194284
ret i1 %c
195285
}
196286

287+
define i1 @test_or3_sext(i32 %x, i64 %n) {
288+
; CHECK-LABEL: @test_or3_sext(
289+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
290+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
291+
; CHECK-NEXT: [[C:%.*]] = icmp ule i64 [[NN]], [[X_SEXT]]
292+
; CHECK-NEXT: ret i1 [[C]]
293+
;
294+
%nn = and i64 %n, 2147483647
295+
%x_sext = sext i32 %x to i64
296+
%a = icmp sle i64 %nn, %x_sext
297+
%b = icmp slt i32 %x, 0
298+
%c = or i1 %a, %b
299+
ret i1 %c
300+
}
301+
197302
define i1 @test_or4(i32 %x, i32 %n) {
198303
; CHECK-LABEL: @test_or4(
199304
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
@@ -220,6 +325,21 @@ define i1 @test_or4_logical(i32 %x, i32 %n) {
220325
ret i1 %c
221326
}
222327

328+
define i1 @test_or4_sext(i32 %x, i64 %n) {
329+
; CHECK-LABEL: @test_or4_sext(
330+
; CHECK-NEXT: [[NN:%.*]] = and i64 [[N:%.*]], 2147483647
331+
; CHECK-NEXT: [[X_SEXT:%.*]] = sext i32 [[X:%.*]] to i64
332+
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[NN]], [[X_SEXT]]
333+
; CHECK-NEXT: ret i1 [[C]]
334+
;
335+
%nn = and i64 %n, 2147483647
336+
%x_sext = sext i32 %x to i64
337+
%a = icmp slt i64 %nn, %x_sext
338+
%b = icmp slt i32 %x, 0
339+
%c = or i1 %a, %b
340+
ret i1 %c
341+
}
342+
223343
; Negative tests
224344

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

0 commit comments

Comments
 (0)