Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / geps-signed-predicates.ll
blob8c285554619781feb0ed30c1720065fcc6013bb5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 define i32 @test.slt(ptr readonly %src, ptr readnone %min, ptr readnone %max) {
5 ; CHECK-LABEL: @test.slt(
6 ; CHECK-NEXT:  check.0.min:
7 ; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp slt ptr [[SRC:%.*]], [[MIN:%.*]]
8 ; CHECK-NEXT:    br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
9 ; CHECK:       trap:
10 ; CHECK-NEXT:    ret i32 10
11 ; CHECK:       check.0.max:
12 ; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[SRC]], [[MAX:%.*]]
13 ; CHECK-NEXT:    br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]]
14 ; CHECK:       check.3.min:
15 ; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[SRC]], align 4
16 ; CHECK-NEXT:    [[ADD_PTR_I36:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
17 ; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MIN]]
18 ; CHECK-NEXT:    br i1 [[C_3_MIN]], label [[TRAP]], label [[CHECK_3_MAX:%.*]]
19 ; CHECK:       check.3.max:
20 ; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MAX]]
21 ; CHECK-NEXT:    br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]]
22 ; CHECK:       check.1.min:
23 ; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4
24 ; CHECK-NEXT:    [[ADD_PTR_I29:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
25 ; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MIN]]
26 ; CHECK-NEXT:    br i1 [[C_1_MIN]], label [[TRAP]], label [[CHECK_1_MAX:%.*]]
27 ; CHECK:       check.1.max:
28 ; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MAX]]
29 ; CHECK-NEXT:    br i1 [[C_1_MAX]], label [[CHECK_2_MIN:%.*]], label [[TRAP]]
30 ; CHECK:       check.2.min:
31 ; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4
32 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
33 ; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MIN]]
34 ; CHECK-NEXT:    br i1 [[C_2_MIN]], label [[TRAP]], label [[CHECK_2_MAX:%.*]]
35 ; CHECK:       check.2.max:
36 ; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MAX]]
37 ; CHECK-NEXT:    br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]]
38 ; CHECK:       exit:
39 ; CHECK-NEXT:    [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4
40 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]]
41 ; CHECK-NEXT:    [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]]
42 ; CHECK-NEXT:    [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]]
43 ; CHECK-NEXT:    ret i32 [[ADD9]]
45 check.0.min:
46   %c.min.0 = icmp slt ptr %src, %min
47   br i1 %c.min.0, label %trap, label %check.0.max
49 trap:
50   ret i32 10
52 check.0.max:
53   %c.max.0 = icmp slt ptr %src, %max
54   br i1 %c.max.0, label %check.3.min, label %trap
56 check.3.min:
57   %l0 = load i32, ptr %src, align 4
58   %add.ptr.i36 = getelementptr inbounds i32, ptr %src, i64 3
59   %c.3.min = icmp slt ptr %add.ptr.i36, %min
60   br i1 %c.3.min, label %trap, label %check.3.max
62 check.3.max:
63   %c.3.max = icmp slt ptr %add.ptr.i36, %max
64   br i1 %c.3.max, label %check.1.min, label %trap
66 check.1.min:
67   %l1 = load i32, ptr %add.ptr.i36, align 4
68   %add.ptr.i29 = getelementptr inbounds i32, ptr %src, i64 1
69   %c.1.min = icmp slt ptr %add.ptr.i29, %min
70   br i1 %c.1.min, label %trap, label %check.1.max
72 check.1.max:
73   %c.1.max = icmp slt ptr %add.ptr.i29, %max
74   br i1 %c.1.max, label %check.2.min, label %trap
76 check.2.min:
77   %l2 = load i32, ptr %add.ptr.i29, align 4
78   %add.ptr.i = getelementptr inbounds i32, ptr %src, i64 2
79   %c.2.min = icmp slt ptr %add.ptr.i, %min
80   br i1 %c.2.min, label %trap, label %check.2.max
82 check.2.max:
83   %c.2.max = icmp slt ptr %add.ptr.i, %max
84   br i1 %c.2.max, label %exit, label %trap
86 exit:
87   %l3 = load i32, ptr %add.ptr.i, align 4
88   %add = add nsw i32 %l1, %l0
89   %add8 = add nsw i32 %add, %l2
90   %add9 = add nsw i32 %add8, %l3
91   ret i32 %add9
94 ; Same as test.slt, but without inbounds.
95 define i32 @test.slt_no_inbounds(ptr readonly %src, ptr readnone %min, ptr readnone %max) {
96 ; CHECK-LABEL: @test.slt_no_inbounds(
97 ; CHECK-NEXT:  check.0.min:
98 ; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp slt ptr [[SRC:%.*]], [[MIN:%.*]]
99 ; CHECK-NEXT:    br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
100 ; CHECK:       trap:
101 ; CHECK-NEXT:    ret i32 10
102 ; CHECK:       check.0.max:
103 ; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[SRC]], [[MAX:%.*]]
104 ; CHECK-NEXT:    br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]]
105 ; CHECK:       check.3.min:
106 ; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[SRC]], align 4
107 ; CHECK-NEXT:    [[ADD_PTR_I36:%.*]] = getelementptr i32, ptr [[SRC]], i64 3
108 ; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MIN]]
109 ; CHECK-NEXT:    br i1 [[C_3_MIN]], label [[TRAP]], label [[CHECK_3_MAX:%.*]]
110 ; CHECK:       check.3.max:
111 ; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MAX]]
112 ; CHECK-NEXT:    br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]]
113 ; CHECK:       check.1.min:
114 ; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4
115 ; CHECK-NEXT:    [[ADD_PTR_I29:%.*]] = getelementptr i32, ptr [[SRC]], i64 1
116 ; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MIN]]
117 ; CHECK-NEXT:    br i1 [[C_1_MIN]], label [[TRAP]], label [[CHECK_1_MAX:%.*]]
118 ; CHECK:       check.1.max:
119 ; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MAX]]
120 ; CHECK-NEXT:    br i1 [[C_1_MAX]], label [[CHECK_2_MIN:%.*]], label [[TRAP]]
121 ; CHECK:       check.2.min:
122 ; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4
123 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[SRC]], i64 2
124 ; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MIN]]
125 ; CHECK-NEXT:    br i1 [[C_2_MIN]], label [[TRAP]], label [[CHECK_2_MAX:%.*]]
126 ; CHECK:       check.2.max:
127 ; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MAX]]
128 ; CHECK-NEXT:    br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]]
129 ; CHECK:       exit:
130 ; CHECK-NEXT:    [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4
131 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]]
132 ; CHECK-NEXT:    [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]]
133 ; CHECK-NEXT:    [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]]
134 ; CHECK-NEXT:    ret i32 [[ADD9]]
136 check.0.min:
137   %c.min.0 = icmp slt ptr %src, %min
138   br i1 %c.min.0, label %trap, label %check.0.max
140 trap:
141   ret i32 10
143 check.0.max:
144   %c.max.0 = icmp slt ptr %src, %max
145   br i1 %c.max.0, label %check.3.min, label %trap
147 check.3.min:
148   %l0 = load i32, ptr %src, align 4
149   %add.ptr.i36 = getelementptr i32, ptr %src, i64 3
150   %c.3.min = icmp slt ptr %add.ptr.i36, %min
151   br i1 %c.3.min, label %trap, label %check.3.max
153 check.3.max:
154   %c.3.max = icmp slt ptr %add.ptr.i36, %max
155   br i1 %c.3.max, label %check.1.min, label %trap
157 check.1.min:
158   %l1 = load i32, ptr %add.ptr.i36, align 4
159   %add.ptr.i29 = getelementptr i32, ptr %src, i64 1
160   %c.1.min = icmp slt ptr %add.ptr.i29, %min
161   br i1 %c.1.min, label %trap, label %check.1.max
163 check.1.max:
164   %c.1.max = icmp slt ptr %add.ptr.i29, %max
165   br i1 %c.1.max, label %check.2.min, label %trap
167 check.2.min:
168   %l2 = load i32, ptr %add.ptr.i29, align 4
169   %add.ptr.i = getelementptr i32, ptr %src, i64 2
170   %c.2.min = icmp slt ptr %add.ptr.i, %min
171   br i1 %c.2.min, label %trap, label %check.2.max
173 check.2.max:
174   %c.2.max = icmp slt ptr %add.ptr.i, %max
175   br i1 %c.2.max, label %exit, label %trap
177 exit:
178   %l3 = load i32, ptr %add.ptr.i, align 4
179   %add = add nsw i32 %l1, %l0
180   %add8 = add nsw i32 %add, %l2
181   %add9 = add nsw i32 %add8, %l3
182   ret i32 %add9
185 define void @test.not.sge.slt(ptr %start, ptr %low, ptr %high) {
186 ; CHECK-LABEL: @test.not.sge.slt(
187 ; CHECK-NEXT:  entry:
188 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
189 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
190 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
191 ; CHECK:       if.then:
192 ; CHECK-NEXT:    ret void
193 ; CHECK:       if.end:
194 ; CHECK-NEXT:    [[T_0:%.*]] = icmp slt ptr [[START]], [[HIGH]]
195 ; CHECK-NEXT:    call void @use(i1 [[T_0]])
196 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
197 ; CHECK-NEXT:    [[T_1:%.*]] = icmp slt ptr [[START_1]], [[HIGH]]
198 ; CHECK-NEXT:    call void @use(i1 [[T_1]])
199 ; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
200 ; CHECK-NEXT:    [[T_2:%.*]] = icmp slt ptr [[START_2]], [[HIGH]]
201 ; CHECK-NEXT:    call void @use(i1 [[T_2]])
202 ; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
203 ; CHECK-NEXT:    [[T_3:%.*]] = icmp slt ptr [[START_3]], [[HIGH]]
204 ; CHECK-NEXT:    call void @use(i1 [[T_3]])
205 ; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
206 ; CHECK-NEXT:    [[C_4:%.*]] = icmp slt ptr [[START_4]], [[HIGH]]
207 ; CHECK-NEXT:    call void @use(i1 [[C_4]])
208 ; CHECK-NEXT:    ret void
210 entry:
211   %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
212   %c.1 = icmp sge ptr %add.ptr.i, %high
213   br i1 %c.1, label %if.then, label %if.end
215 if.then:
216   ret void
218 if.end:
219   %t.0 = icmp slt ptr %start, %high
220   call void @use(i1 %t.0)
221   %start.1 = getelementptr inbounds i8, ptr %start, i64 1
222   %t.1 = icmp slt ptr %start.1, %high
223   call void @use(i1 %t.1)
224   %start.2 = getelementptr inbounds i8, ptr %start, i64 2
225   %t.2 = icmp slt ptr %start.2, %high
226   call void @use(i1 %t.2)
227   %start.3 = getelementptr inbounds i8, ptr %start, i64 3
228   %t.3 = icmp slt ptr %start.3, %high
229   call void @use(i1 %t.3)
230   %start.4 = getelementptr inbounds i8, ptr %start, i64 4
231   %c.4 = icmp slt ptr %start.4, %high
232   call void @use(i1 %c.4)
233   ret void
236 ; Same as test.not.sge.slt, but without inbounds GEPs.
237 define void @test.not.sge.slt_no_inbounds(ptr %start, ptr %low, ptr %high) {
238 ; CHECK-LABEL: @test.not.sge.slt_no_inbounds(
239 ; CHECK-NEXT:  entry:
240 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 3
241 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
242 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
243 ; CHECK:       if.then:
244 ; CHECK-NEXT:    ret void
245 ; CHECK:       if.end:
246 ; CHECK-NEXT:    [[T_0:%.*]] = icmp slt ptr [[START]], [[HIGH]]
247 ; CHECK-NEXT:    call void @use(i1 [[T_0]])
248 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr i8, ptr [[START]], i64 1
249 ; CHECK-NEXT:    [[T_1:%.*]] = icmp slt ptr [[START_1]], [[HIGH]]
250 ; CHECK-NEXT:    call void @use(i1 [[T_1]])
251 ; CHECK-NEXT:    [[START_2:%.*]] = getelementptr i8, ptr [[START]], i64 2
252 ; CHECK-NEXT:    [[T_2:%.*]] = icmp slt ptr [[START_2]], [[HIGH]]
253 ; CHECK-NEXT:    call void @use(i1 [[T_2]])
254 ; CHECK-NEXT:    [[START_3:%.*]] = getelementptr i8, ptr [[START]], i64 3
255 ; CHECK-NEXT:    [[T_3:%.*]] = icmp slt ptr [[START_3]], [[HIGH]]
256 ; CHECK-NEXT:    call void @use(i1 [[T_3]])
257 ; CHECK-NEXT:    [[START_4:%.*]] = getelementptr i8, ptr [[START]], i64 4
258 ; CHECK-NEXT:    [[C_4:%.*]] = icmp slt ptr [[START_4]], [[HIGH]]
259 ; CHECK-NEXT:    call void @use(i1 [[C_4]])
260 ; CHECK-NEXT:    ret void
262 entry:
263   %add.ptr.i = getelementptr i8, ptr %start, i64 3
264   %c.1 = icmp sge ptr %add.ptr.i, %high
265   br i1 %c.1, label %if.then, label %if.end
267 if.then:
268   ret void
270 if.end:
271   %t.0 = icmp slt ptr %start, %high
272   call void @use(i1 %t.0)
273   %start.1 = getelementptr i8, ptr %start, i64 1
274   %t.1 = icmp slt ptr %start.1, %high
275   call void @use(i1 %t.1)
276   %start.2 = getelementptr i8, ptr %start, i64 2
277   %t.2 = icmp slt ptr %start.2, %high
278   call void @use(i1 %t.2)
279   %start.3 = getelementptr i8, ptr %start, i64 3
280   %t.3 = icmp slt ptr %start.3, %high
281   call void @use(i1 %t.3)
282   %start.4 = getelementptr i8, ptr %start, i64 4
283   %c.4 = icmp slt ptr %start.4, %high
284   call void @use(i1 %c.4)
285   ret void
288 define void @test.not.sge.sle(ptr %start, ptr %low, ptr %high) {
289 ; CHECK-LABEL: @test.not.sge.sle(
290 ; CHECK-NEXT:  entry:
291 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
292 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
293 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
294 ; CHECK:       if.then:
295 ; CHECK-NEXT:    ret void
296 ; CHECK:       if.end:
297 ; CHECK-NEXT:    [[T_0:%.*]] = icmp sle ptr [[START]], [[HIGH]]
298 ; CHECK-NEXT:    call void @use(i1 [[T_0]])
299 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
300 ; CHECK-NEXT:    [[T_1:%.*]] = icmp sle ptr [[START_1]], [[HIGH]]
301 ; CHECK-NEXT:    call void @use(i1 [[T_1]])
302 ; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
303 ; CHECK-NEXT:    [[T_2:%.*]] = icmp sle ptr [[START_2]], [[HIGH]]
304 ; CHECK-NEXT:    call void @use(i1 [[T_2]])
305 ; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
306 ; CHECK-NEXT:    [[T_3:%.*]] = icmp sle ptr [[START_3]], [[HIGH]]
307 ; CHECK-NEXT:    call void @use(i1 [[T_3]])
308 ; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
309 ; CHECK-NEXT:    [[T_4:%.*]] = icmp sle ptr [[START_4]], [[HIGH]]
310 ; CHECK-NEXT:    call void @use(i1 [[T_4]])
311 ; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
312 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sle ptr [[START_5]], [[HIGH]]
313 ; CHECK-NEXT:    call void @use(i1 [[C_5]])
314 ; CHECK-NEXT:    ret void
316 entry:
317   %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
318   %c.1 = icmp sge ptr %add.ptr.i, %high
319   br i1 %c.1, label %if.then, label %if.end
321 if.then:
322   ret void
324 if.end:
325   %t.0 = icmp sle ptr %start, %high
326   call void @use(i1 %t.0)
327   %start.1 = getelementptr inbounds i8, ptr %start, i64 1
328   %t.1 = icmp sle ptr %start.1, %high
329   call void @use(i1 %t.1)
330   %start.2 = getelementptr inbounds i8, ptr %start, i64 2
331   %t.2 = icmp sle ptr %start.2, %high
332   call void @use(i1 %t.2)
333   %start.3 = getelementptr inbounds i8, ptr %start, i64 3
334   %t.3 = icmp sle ptr %start.3, %high
335   call void @use(i1 %t.3)
336   %start.4 = getelementptr inbounds i8, ptr %start, i64 4
337   %t.4 = icmp sle ptr %start.4, %high
338   call void @use(i1 %t.4)
339   %start.5 = getelementptr inbounds i8, ptr %start, i64 5
340   %c.5 = icmp sle ptr %start.5, %high
341   call void @use(i1 %c.5)
342   ret void
345 define void @test.not.sge.sgt(ptr %start, ptr %low, ptr %high) {
346 ; CHECK-LABEL: @test.not.sge.sgt(
347 ; CHECK-NEXT:  entry:
348 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
349 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
350 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
351 ; CHECK:       if.then:
352 ; CHECK-NEXT:    ret void
353 ; CHECK:       if.end:
354 ; CHECK-NEXT:    [[F_0:%.*]] = icmp sgt ptr [[START]], [[HIGH]]
355 ; CHECK-NEXT:    call void @use(i1 [[F_0]])
356 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
357 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sgt ptr [[START_1]], [[HIGH]]
358 ; CHECK-NEXT:    call void @use(i1 [[F_1]])
359 ; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
360 ; CHECK-NEXT:    [[F_2:%.*]] = icmp sgt ptr [[START_2]], [[HIGH]]
361 ; CHECK-NEXT:    call void @use(i1 [[F_2]])
362 ; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
363 ; CHECK-NEXT:    [[F_3:%.*]] = icmp sgt ptr [[START_3]], [[HIGH]]
364 ; CHECK-NEXT:    call void @use(i1 [[F_3]])
365 ; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
366 ; CHECK-NEXT:    [[F_4:%.*]] = icmp sgt ptr [[START_4]], [[HIGH]]
367 ; CHECK-NEXT:    call void @use(i1 [[F_4]])
368 ; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
369 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sgt ptr [[START_5]], [[HIGH]]
370 ; CHECK-NEXT:    call void @use(i1 [[C_5]])
371 ; CHECK-NEXT:    ret void
373 entry:
374   %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
375   %c.1 = icmp sge ptr %add.ptr.i, %high
376   br i1 %c.1, label %if.then, label %if.end
378 if.then:
379   ret void
381 if.end:
382   %f.0 = icmp sgt ptr %start, %high
383   call void @use(i1 %f.0)
384   %start.1 = getelementptr inbounds i8, ptr %start, i64 1
385   %f.1 = icmp sgt ptr %start.1, %high
386   call void @use(i1 %f.1)
387   %start.2 = getelementptr inbounds i8, ptr %start, i64 2
388   %f.2 = icmp sgt ptr %start.2, %high
389   call void @use(i1 %f.2)
390   %start.3 = getelementptr inbounds i8, ptr %start, i64 3
391   %f.3 = icmp sgt ptr %start.3, %high
392   call void @use(i1 %f.3)
393   %start.4 = getelementptr inbounds i8, ptr %start, i64 4
394   %f.4 = icmp sgt ptr %start.4, %high
395   call void @use(i1 %f.4)
396   %start.5 = getelementptr inbounds i8, ptr %start, i64 5
397   %c.5 = icmp sgt ptr %start.5, %high
398   call void @use(i1 %c.5)
399   ret void
402 define void @test.not.sge.sge(ptr %start, ptr %low, ptr %high) {
403 ; CHECK-LABEL: @test.not.sge.sge(
404 ; CHECK-NEXT:  entry:
405 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
406 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
407 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
408 ; CHECK:       if.then:
409 ; CHECK-NEXT:    ret void
410 ; CHECK:       if.end:
411 ; CHECK-NEXT:    [[F_0:%.*]] = icmp sgt ptr [[START]], [[HIGH]]
412 ; CHECK-NEXT:    call void @use(i1 [[F_0]])
413 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
414 ; CHECK-NEXT:    [[F_1:%.*]] = icmp sge ptr [[START_1]], [[HIGH]]
415 ; CHECK-NEXT:    call void @use(i1 [[F_1]])
416 ; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
417 ; CHECK-NEXT:    [[F_2:%.*]] = icmp sge ptr [[START_2]], [[HIGH]]
418 ; CHECK-NEXT:    call void @use(i1 [[F_2]])
419 ; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
420 ; CHECK-NEXT:    [[F_3:%.*]] = icmp sge ptr [[START_3]], [[HIGH]]
421 ; CHECK-NEXT:    call void @use(i1 [[F_3]])
422 ; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
423 ; CHECK-NEXT:    [[C_4:%.*]] = icmp sge ptr [[START_4]], [[HIGH]]
424 ; CHECK-NEXT:    call void @use(i1 [[C_4]])
425 ; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
426 ; CHECK-NEXT:    [[C_5:%.*]] = icmp sge ptr [[START_5]], [[HIGH]]
427 ; CHECK-NEXT:    call void @use(i1 [[C_5]])
428 ; CHECK-NEXT:    ret void
430 entry:
431   %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
432   %c.1 = icmp sge ptr %add.ptr.i, %high
433   br i1 %c.1, label %if.then, label %if.end
435 if.then:
436   ret void
438 if.end:
439   %f.0 = icmp sgt ptr %start, %high
440   call void @use(i1 %f.0)
441   %start.1 = getelementptr inbounds i8, ptr %start, i64 1
442   %f.1 = icmp sge ptr %start.1, %high
443   call void @use(i1 %f.1)
444   %start.2 = getelementptr inbounds i8, ptr %start, i64 2
445   %f.2 = icmp sge ptr %start.2, %high
446   call void @use(i1 %f.2)
447   %start.3 = getelementptr inbounds i8, ptr %start, i64 3
448   %f.3 = icmp sge ptr %start.3, %high
449   call void @use(i1 %f.3)
450   %start.4 = getelementptr inbounds i8, ptr %start, i64 4
451   %c.4 = icmp sge ptr %start.4, %high
452   call void @use(i1 %c.4)
453   %start.5 = getelementptr inbounds i8, ptr %start, i64 5
454   %c.5 = icmp sge ptr %start.5, %high
455   call void @use(i1 %c.5)
456   ret void
459 define void @test.not.sge.sge.nonconst(ptr %start, ptr %low, ptr %high, i8 %off) {
460 ; CHECK-LABEL: @test.not.sge.sge.nonconst(
461 ; CHECK-NEXT:  entry:
462 ; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i8 [[OFF:%.*]]
463 ; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
464 ; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
465 ; CHECK:       if.then:
466 ; CHECK-NEXT:    [[START_OFF_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]]
467 ; CHECK-NEXT:    [[T_0:%.*]] = icmp sge ptr [[START_OFF_2]], [[HIGH]]
468 ; CHECK-NEXT:    call void @use(i1 [[T_0]])
469 ; CHECK-NEXT:    ret void
470 ; CHECK:       if.end:
471 ; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
472 ; CHECK-NEXT:    [[C_0:%.*]] = icmp sge ptr [[START_1]], [[HIGH]]
473 ; CHECK-NEXT:    call void @use(i1 [[C_0]])
474 ; CHECK-NEXT:    [[START_OFF:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]]
475 ; CHECK-NEXT:    [[F_0:%.*]] = icmp sge ptr [[START_OFF]], [[HIGH]]
476 ; CHECK-NEXT:    call void @use(i1 [[F_0]])
477 ; CHECK-NEXT:    ret void
479 entry:
480   %add.ptr.i = getelementptr inbounds i8, ptr %start, i8 %off
481   %c.1 = icmp sge ptr %add.ptr.i, %high
482   br i1 %c.1, label %if.then, label %if.end
484 if.then:
485   %start.off.2 = getelementptr inbounds i8, ptr %start, i8 %off
486   %t.0 = icmp sge ptr %start.off.2, %high
487   call void @use(i1 %t.0)
488   ret void
490 if.end:
491   %start.1 = getelementptr inbounds i8, ptr %start, i64 1
492   %c.0 = icmp sge ptr %start.1, %high
493   call void @use(i1 %c.0)
494   %start.off = getelementptr inbounds i8, ptr %start, i8 %off
495   %f.0 = icmp sge ptr %start.off, %high
496   call void @use(i1 %f.0)
497   ret void
500 ; Test which requires decomposing GEP %ptr, SHL().
501 define void @test.slt.gep.shl(ptr readonly %src, ptr readnone %max, i8 %idx) {
502 ; CHECK-LABEL: @test.slt.gep.shl(
503 ; CHECK-NEXT:  check.0.min:
504 ; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10
505 ; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
506 ; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
507 ; CHECK:       trap:
508 ; CHECK-NEXT:    ret void
509 ; CHECK:       check.idx:
510 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX:%.*]], 5
511 ; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
512 ; CHECK:       check.max:
513 ; CHECK-NEXT:    [[IDX_SHL_1:%.*]] = shl nuw i8 [[IDX]], 1
514 ; CHECK-NEXT:    [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_1]]
515 ; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[ADD_PTR_SHL_1]], [[MAX]]
516 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_0]])
517 ; CHECK-NEXT:    [[IDX_SHL_2:%.*]] = shl nuw i8 [[IDX]], 2
518 ; CHECK-NEXT:    [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_2]]
519 ; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_2]], [[MAX]]
520 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_1]])
521 ; CHECK-NEXT:    [[IDX_SHL_NOT_NUW:%.*]] = shl i8 [[IDX]], 1
522 ; CHECK-NEXT:    [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_NOT_NUW]]
523 ; CHECK-NEXT:    [[C_MAX_2:%.*]] = icmp slt ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
524 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_2]])
525 ; CHECK-NEXT:    [[IDX_SHL_3:%.*]] = shl nuw i8 [[IDX]], 3
526 ; CHECK-NEXT:    [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_3]]
527 ; CHECK-NEXT:    [[C_MAX_3:%.*]] = icmp slt ptr [[ADD_PTR_SHL_3]], [[MAX]]
528 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_3]])
529 ; CHECK-NEXT:    ret void
531 check.0.min:
532   %add.10 = getelementptr inbounds i32, ptr %src, i32 10
533   %c.add.10.max = icmp sgt ptr %add.10, %max
534   br i1 %c.add.10.max, label %trap, label %check.idx
536 trap:
537   ret void
539 check.idx:
540   %cmp = icmp slt i8 %idx, 5
541   br i1 %cmp, label %check.max, label %trap
543 check.max:
544   %idx.shl.1 = shl nuw i8 %idx, 1
545   %add.ptr.shl.1 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.1
546   %c.max.0 = icmp slt ptr %add.ptr.shl.1, %max
547   call void @use(i1 %c.max.0)
548   %idx.shl.2 = shl nuw i8 %idx, 2
549   %add.ptr.shl.2 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.2
550   %c.max.1 = icmp slt ptr %add.ptr.shl.2, %max
551   call void @use(i1 %c.max.1)
552   %idx.shl.not.nuw = shl i8 %idx, 1
553   %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i8 %idx.shl.not.nuw
554   %c.max.2 = icmp slt ptr %add.ptr.shl.not.nuw, %max
555   call void @use(i1 %c.max.2)
556   %idx.shl.3 = shl nuw i8 %idx, 3
557   %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.3
558   %c.max.3 = icmp slt ptr %add.ptr.shl.3, %max
559   call void @use(i1 %c.max.3)
560   ret void
563 ; Test which requires decomposing GEP %ptr, ZEXT(SHL()).
564 define void @test.slt.gep.shl.zext(ptr readonly %src, ptr readnone %max, i32 %idx, i32 %j) {
565 ; CHECK-LABEL: @test.slt.gep.shl.zext(
566 ; CHECK-NEXT:  check.0.min:
567 ; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10
568 ; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
569 ; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
570 ; CHECK:       trap:
571 ; CHECK-NEXT:    ret void
572 ; CHECK:       check.idx:
573 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IDX:%.*]], 5
574 ; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
575 ; CHECK:       check.max:
576 ; CHECK-NEXT:    [[IDX_SHL:%.*]] = shl nuw i32 [[IDX]], 1
577 ; CHECK-NEXT:    [[EXT_1:%.*]] = zext i32 [[IDX_SHL]] to i64
578 ; CHECK-NEXT:    [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_1]]
579 ; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[ADD_PTR_SHL]], [[MAX]]
580 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_0]])
581 ; CHECK-NEXT:    [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1
582 ; CHECK-NEXT:    [[EXT_2:%.*]] = zext i32 [[IDX_SHL_NOT_NUW]] to i64
583 ; CHECK-NEXT:    [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_2]]
584 ; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
585 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_1]])
586 ; CHECK-NEXT:    [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 2
587 ; CHECK-NEXT:    [[EXT_3:%.*]] = zext i32 [[IDX_SHL_3]] to i64
588 ; CHECK-NEXT:    [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_3]]
589 ; CHECK-NEXT:    [[C_MAX_2:%.*]] = icmp slt ptr [[ADD_PTR_SHL_3]], [[MAX]]
590 ; CHECK-NEXT:    call void @use(i1 [[C_MAX_2]])
591 ; CHECK-NEXT:    ret void
593 check.0.min:
594   %add.10 = getelementptr inbounds i32, ptr %src, i32 10
595   %c.add.10.max = icmp sgt ptr %add.10, %max
596   br i1 %c.add.10.max, label %trap, label %check.idx
598 trap:
599   ret void
601 check.idx:
602   %cmp = icmp slt i32 %idx, 5
603   br i1 %cmp, label %check.max, label %trap
605 check.max:
606   %idx.shl = shl nuw i32 %idx, 1
607   %ext.1 = zext i32 %idx.shl to i64
608   %add.ptr.shl = getelementptr inbounds i32, ptr %src, i64 %ext.1
609   %c.max.0 = icmp slt ptr %add.ptr.shl, %max
610   call void @use(i1 %c.max.0)
611   %idx.shl.not.nuw = shl i32 %idx, 1
612   %ext.2 = zext i32 %idx.shl.not.nuw to i64
613   %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i64 %ext.2
614   %c.max.1 = icmp slt ptr %add.ptr.shl.not.nuw, %max
615   call void @use(i1 %c.max.1)
616   %idx.shl.3 = shl nuw i32 %idx, 2
617   %ext.3 = zext i32 %idx.shl.3 to i64
618   %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i64 %ext.3
619   %c.max.2 = icmp slt ptr %add.ptr.shl.3, %max
620   call void @use(i1 %c.max.2)
621   ret void
624 ; Make sure non-constant shift amounts are handled correctly.
625 define i1 @test.slt.gep.shl.nonconst.zext(i16 %B, ptr readonly %src, ptr readnone %max, i16 %idx, i16 %j) {
626 ; CHECK-LABEL: @test.slt.gep.shl.nonconst.zext(
627 ; CHECK-NEXT:  check.0.min:
628 ; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i16, ptr [[SRC:%.*]], i16 10
629 ; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
630 ; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[EXIT_1:%.*]], label [[CHECK_IDX:%.*]]
631 ; CHECK:       exit.1:
632 ; CHECK-NEXT:    ret i1 true
633 ; CHECK:       check.idx:
634 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[IDX:%.*]], 5
635 ; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP:%.*]]
636 ; CHECK:       check.max:
637 ; CHECK-NEXT:    [[IDX_SHL:%.*]] = shl nuw i16 [[IDX]], [[B:%.*]]
638 ; CHECK-NEXT:    [[EXT:%.*]] = zext i16 [[IDX_SHL]] to i64
639 ; CHECK-NEXT:    [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT]]
640 ; CHECK-NEXT:    [[C_MAX:%.*]] = icmp slt ptr [[ADD_PTR_SHL]], [[MAX]]
641 ; CHECK-NEXT:    ret i1 [[C_MAX]]
642 ; CHECK:       trap:
643 ; CHECK-NEXT:    [[IDX_SHL_1:%.*]] = shl nuw i16 [[IDX]], [[B]]
644 ; CHECK-NEXT:    [[EXT_1:%.*]] = zext i16 [[IDX_SHL_1]] to i64
645 ; CHECK-NEXT:    [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT_1]]
646 ; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_1]], [[MAX]]
647 ; CHECK-NEXT:    ret i1 [[C_MAX_1]]
649 check.0.min:
650   %add.10 = getelementptr inbounds i16, ptr %src, i16 10
651   %c.add.10.max = icmp sgt ptr %add.10, %max
652   br i1 %c.add.10.max, label %exit.1, label %check.idx
654 exit.1:
655   ret i1 true
657 check.idx:
658   %cmp = icmp slt i16 %idx, 5
659   br i1 %cmp, label %check.max, label %trap
661 check.max:
662   %idx.shl = shl nuw i16 %idx, %B
663   %ext = zext i16 %idx.shl to i64
664   %add.ptr.shl = getelementptr inbounds i16, ptr %src, i64 %ext
665   %c.max = icmp slt ptr %add.ptr.shl, %max
666   ret i1 %c.max
668 trap:
669   %idx.shl.1 = shl nuw i16 %idx, %B
670   %ext.1 = zext i16 %idx.shl.1 to i64
671   %add.ptr.shl.1 = getelementptr inbounds i16, ptr %src, i64 %ext.1
672   %c.max.1 = icmp slt ptr %add.ptr.shl.1, %max
673   ret i1 %c.max.1
676 declare void @use(i1)