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.ult(i32* readonly %src, i32* readnone %min, i32* readnone %max) {
5 ; CHECK-LABEL: @test.ult(
6 ; CHECK-NEXT: check.0.min:
7 ; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult i32* [[SRC:%.*]], [[MIN:%.*]]
8 ; CHECK-NEXT: br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
10 ; CHECK-NEXT: ret i32 10
12 ; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[SRC]], [[MAX:%.*]]
13 ; CHECK-NEXT: br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]]
15 ; CHECK-NEXT: [[L0:%.*]] = load i32, i32* [[SRC]], align 4
16 ; CHECK-NEXT: [[ADD_PTR_I36:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3
17 ; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult i32* [[ADD_PTR_I36]], [[MIN]]
18 ; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_3_MAX:%.*]]
20 ; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult i32* [[ADD_PTR_I36]], [[MAX]]
21 ; CHECK-NEXT: br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]]
23 ; CHECK-NEXT: [[L1:%.*]] = load i32, i32* [[ADD_PTR_I36]], align 4
24 ; CHECK-NEXT: [[ADD_PTR_I29:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1
25 ; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult i32* [[ADD_PTR_I29]], [[MIN]]
26 ; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_1_MAX:%.*]]
28 ; CHECK-NEXT: [[C_1_MAX:%.*]] = icmp ult i32* [[ADD_PTR_I29]], [[MAX]]
29 ; CHECK-NEXT: br i1 true, label [[CHECK_2_MIN:%.*]], label [[TRAP]]
31 ; CHECK-NEXT: [[L2:%.*]] = load i32, i32* [[ADD_PTR_I29]], align 4
32 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2
33 ; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult i32* [[ADD_PTR_I]], [[MIN]]
34 ; CHECK-NEXT: br i1 false, label [[TRAP]], label [[CHECK_2_MAX:%.*]]
36 ; CHECK-NEXT: [[C_2_MAX:%.*]] = icmp ult i32* [[ADD_PTR_I]], [[MAX]]
37 ; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[TRAP]]
39 ; CHECK-NEXT: [[L3:%.*]] = load i32, i32* [[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]]
46 %c.min.0 = icmp ult i32* %src, %min
47 br i1 %c.min.0, label %trap, label %check.0.max
49 trap: ; preds = %check.2.max, %check.2.min, %check.1.max, %check.1.min, %check.3.max, %check.3.min, %check.0.max, %check.0.min
52 check.0.max: ; preds = %check.0.min
53 %c.max.0 = icmp ult i32* %src, %max
54 br i1 %c.max.0, label %check.3.min, label %trap
56 check.3.min: ; preds = %check.0.max
57 %l0 = load i32, i32* %src, align 4
58 %add.ptr.i36 = getelementptr inbounds i32, i32* %src, i64 3
59 %c.3.min = icmp ult i32* %add.ptr.i36, %min
60 br i1 %c.3.min, label %trap, label %check.3.max
62 check.3.max: ; preds = %check.3.min
63 %c.3.max = icmp ult i32* %add.ptr.i36, %max
64 br i1 %c.3.max, label %check.1.min, label %trap
66 check.1.min: ; preds = %check.3.max
67 %l1 = load i32, i32* %add.ptr.i36, align 4
68 %add.ptr.i29 = getelementptr inbounds i32, i32* %src, i64 1
69 %c.1.min = icmp ult i32* %add.ptr.i29, %min
70 br i1 %c.1.min, label %trap, label %check.1.max
72 check.1.max: ; preds = %check.1.min
73 %c.1.max = icmp ult i32* %add.ptr.i29, %max
74 br i1 %c.1.max, label %check.2.min, label %trap
76 check.2.min: ; preds = %check.1.max
77 %l2 = load i32, i32* %add.ptr.i29, align 4
78 %add.ptr.i = getelementptr inbounds i32, i32* %src, i64 2
79 %c.2.min = icmp ult i32* %add.ptr.i, %min
80 br i1 %c.2.min, label %trap, label %check.2.max
82 check.2.max: ; preds = %check.2.min
83 %c.2.max = icmp ult i32* %add.ptr.i, %max
84 br i1 %c.2.max, label %exit, label %trap
86 exit: ; preds = %check.2.max
87 %l3 = load i32, i32* %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
94 ; Same as test.ult, but without inbounds.
95 define i32 @test.ult_no_inbounds(i32* readonly %src, i32* readnone %min, i32* readnone %max) {
96 ; CHECK-LABEL: @test.ult_no_inbounds(
97 ; CHECK-NEXT: check.0.min:
98 ; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult i32* [[SRC:%.*]], [[MIN:%.*]]
99 ; CHECK-NEXT: br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
101 ; CHECK-NEXT: ret i32 10
102 ; CHECK: check.0.max:
103 ; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[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, i32* [[SRC]], align 4
107 ; CHECK-NEXT: [[ADD_PTR_I36:%.*]] = getelementptr i32, i32* [[SRC]], i64 3
108 ; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult i32* [[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 ult i32* [[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, i32* [[ADD_PTR_I36]], align 4
115 ; CHECK-NEXT: [[ADD_PTR_I29:%.*]] = getelementptr i32, i32* [[SRC]], i64 1
116 ; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult i32* [[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 ult i32* [[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, i32* [[ADD_PTR_I29]], align 4
123 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, i32* [[SRC]], i64 2
124 ; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult i32* [[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 ult i32* [[ADD_PTR_I]], [[MAX]]
128 ; CHECK-NEXT: br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]]
130 ; CHECK-NEXT: [[L3:%.*]] = load i32, i32* [[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]]
137 %c.min.0 = icmp ult i32* %src, %min
138 br i1 %c.min.0, label %trap, label %check.0.max
140 trap: ; preds = %check.2.max, %check.2.min, %check.1.max, %check.1.min, %check.3.max, %check.3.min, %check.0.max, %check.0.min
143 check.0.max: ; preds = %check.0.min
144 %c.max.0 = icmp ult i32* %src, %max
145 br i1 %c.max.0, label %check.3.min, label %trap
147 check.3.min: ; preds = %check.0.max
148 %l0 = load i32, i32* %src, align 4
149 %add.ptr.i36 = getelementptr i32, i32* %src, i64 3
150 %c.3.min = icmp ult i32* %add.ptr.i36, %min
151 br i1 %c.3.min, label %trap, label %check.3.max
153 check.3.max: ; preds = %check.3.min
154 %c.3.max = icmp ult i32* %add.ptr.i36, %max
155 br i1 %c.3.max, label %check.1.min, label %trap
157 check.1.min: ; preds = %check.3.max
158 %l1 = load i32, i32* %add.ptr.i36, align 4
159 %add.ptr.i29 = getelementptr i32, i32* %src, i64 1
160 %c.1.min = icmp ult i32* %add.ptr.i29, %min
161 br i1 %c.1.min, label %trap, label %check.1.max
163 check.1.max: ; preds = %check.1.min
164 %c.1.max = icmp ult i32* %add.ptr.i29, %max
165 br i1 %c.1.max, label %check.2.min, label %trap
167 check.2.min: ; preds = %check.1.max
168 %l2 = load i32, i32* %add.ptr.i29, align 4
169 %add.ptr.i = getelementptr i32, i32* %src, i64 2
170 %c.2.min = icmp ult i32* %add.ptr.i, %min
171 br i1 %c.2.min, label %trap, label %check.2.max
173 check.2.max: ; preds = %check.2.min
174 %c.2.max = icmp ult i32* %add.ptr.i, %max
175 br i1 %c.2.max, label %exit, label %trap
177 exit: ; preds = %check.2.max
178 %l3 = load i32, i32* %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
186 define void @test.not.uge.ult(i8* %start, i8* %low, i8* %high) {
187 ; CHECK-LABEL: @test.not.uge.ult(
189 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i64 3
190 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
191 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
193 ; CHECK-NEXT: ret void
195 ; CHECK-NEXT: [[T_0:%.*]] = icmp ult i8* [[START]], [[HIGH]]
196 ; CHECK-NEXT: call void @use(i1 true)
197 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
198 ; CHECK-NEXT: [[T_1:%.*]] = icmp ult i8* [[START_1]], [[HIGH]]
199 ; CHECK-NEXT: call void @use(i1 true)
200 ; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 2
201 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult i8* [[START_2]], [[HIGH]]
202 ; CHECK-NEXT: call void @use(i1 true)
203 ; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 3
204 ; CHECK-NEXT: [[T_3:%.*]] = icmp ult i8* [[START_3]], [[HIGH]]
205 ; CHECK-NEXT: call void @use(i1 true)
206 ; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 4
207 ; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8* [[START_4]], [[HIGH]]
208 ; CHECK-NEXT: call void @use(i1 [[C_4]])
209 ; CHECK-NEXT: ret void
212 %add.ptr.i = getelementptr inbounds i8, i8* %start, i64 3
213 %c.1 = icmp uge i8* %add.ptr.i, %high
214 br i1 %c.1, label %if.then, label %if.end
216 if.then: ; preds = %entry
219 if.end: ; preds = %entry
220 %t.0 = icmp ult i8* %start, %high
221 call void @use(i1 %t.0)
222 %start.1 = getelementptr inbounds i8, i8* %start, i64 1
223 %t.1 = icmp ult i8* %start.1, %high
224 call void @use(i1 %t.1)
225 %start.2 = getelementptr inbounds i8, i8* %start, i64 2
226 %t.2 = icmp ult i8* %start.2, %high
227 call void @use(i1 %t.2)
228 %start.3 = getelementptr inbounds i8, i8* %start, i64 3
229 %t.3 = icmp ult i8* %start.3, %high
230 call void @use(i1 %t.3)
231 %start.4 = getelementptr inbounds i8, i8* %start, i64 4
232 %c.4 = icmp ult i8* %start.4, %high
233 call void @use(i1 %c.4)
237 ; Same as test.not.uge.ult, but without inbounds GEPs.
238 define void @test.not.uge.ult_no_inbounds(i8* %start, i8* %low, i8* %high) {
239 ; CHECK-LABEL: @test.not.uge.ult_no_inbounds(
241 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i8, i8* [[START:%.*]], i64 3
242 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
243 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
245 ; CHECK-NEXT: ret void
247 ; CHECK-NEXT: [[T_0:%.*]] = icmp ult i8* [[START]], [[HIGH]]
248 ; CHECK-NEXT: call void @use(i1 [[T_0]])
249 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr i8, i8* [[START]], i64 1
250 ; CHECK-NEXT: [[T_1:%.*]] = icmp ult i8* [[START_1]], [[HIGH]]
251 ; CHECK-NEXT: call void @use(i1 [[T_1]])
252 ; CHECK-NEXT: [[START_2:%.*]] = getelementptr i8, i8* [[START]], i64 2
253 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult i8* [[START_2]], [[HIGH]]
254 ; CHECK-NEXT: call void @use(i1 [[T_2]])
255 ; CHECK-NEXT: [[START_3:%.*]] = getelementptr i8, i8* [[START]], i64 3
256 ; CHECK-NEXT: [[T_3:%.*]] = icmp ult i8* [[START_3]], [[HIGH]]
257 ; CHECK-NEXT: call void @use(i1 [[T_3]])
258 ; CHECK-NEXT: [[START_4:%.*]] = getelementptr i8, i8* [[START]], i64 4
259 ; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8* [[START_4]], [[HIGH]]
260 ; CHECK-NEXT: call void @use(i1 [[C_4]])
261 ; CHECK-NEXT: ret void
264 %add.ptr.i = getelementptr i8, i8* %start, i64 3
265 %c.1 = icmp uge i8* %add.ptr.i, %high
266 br i1 %c.1, label %if.then, label %if.end
268 if.then: ; preds = %entry
271 if.end: ; preds = %entry
272 %t.0 = icmp ult i8* %start, %high
273 call void @use(i1 %t.0)
274 %start.1 = getelementptr i8, i8* %start, i64 1
275 %t.1 = icmp ult i8* %start.1, %high
276 call void @use(i1 %t.1)
277 %start.2 = getelementptr i8, i8* %start, i64 2
278 %t.2 = icmp ult i8* %start.2, %high
279 call void @use(i1 %t.2)
280 %start.3 = getelementptr i8, i8* %start, i64 3
281 %t.3 = icmp ult i8* %start.3, %high
282 call void @use(i1 %t.3)
283 %start.4 = getelementptr i8, i8* %start, i64 4
284 %c.4 = icmp ult i8* %start.4, %high
285 call void @use(i1 %c.4)
289 define void @test.not.uge.ule(i8* %start, i8* %low, i8* %high) {
290 ; CHECK-LABEL: @test.not.uge.ule(
292 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i64 3
293 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
294 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
296 ; CHECK-NEXT: ret void
298 ; CHECK-NEXT: [[T_0:%.*]] = icmp ule i8* [[START]], [[HIGH]]
299 ; CHECK-NEXT: call void @use(i1 true)
300 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
301 ; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8* [[START_1]], [[HIGH]]
302 ; CHECK-NEXT: call void @use(i1 true)
303 ; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 2
304 ; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8* [[START_2]], [[HIGH]]
305 ; CHECK-NEXT: call void @use(i1 true)
306 ; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 3
307 ; CHECK-NEXT: [[T_3:%.*]] = icmp ule i8* [[START_3]], [[HIGH]]
308 ; CHECK-NEXT: call void @use(i1 true)
309 ; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 4
310 ; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8* [[START_4]], [[HIGH]]
311 ; CHECK-NEXT: call void @use(i1 true)
312 ; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 5
313 ; CHECK-NEXT: [[C_5:%.*]] = icmp ule i8* [[START_5]], [[HIGH]]
314 ; CHECK-NEXT: call void @use(i1 [[C_5]])
315 ; CHECK-NEXT: ret void
318 %add.ptr.i = getelementptr inbounds i8, i8* %start, i64 3
319 %c.1 = icmp uge i8* %add.ptr.i, %high
320 br i1 %c.1, label %if.then, label %if.end
322 if.then: ; preds = %entry
325 if.end: ; preds = %entry
326 %t.0 = icmp ule i8* %start, %high
327 call void @use(i1 %t.0)
328 %start.1 = getelementptr inbounds i8, i8* %start, i64 1
329 %t.1 = icmp ule i8* %start.1, %high
330 call void @use(i1 %t.1)
331 %start.2 = getelementptr inbounds i8, i8* %start, i64 2
332 %t.2 = icmp ule i8* %start.2, %high
333 call void @use(i1 %t.2)
334 %start.3 = getelementptr inbounds i8, i8* %start, i64 3
335 %t.3 = icmp ule i8* %start.3, %high
336 call void @use(i1 %t.3)
337 %start.4 = getelementptr inbounds i8, i8* %start, i64 4
338 %t.4 = icmp ule i8* %start.4, %high
339 call void @use(i1 %t.4)
341 %start.5 = getelementptr inbounds i8, i8* %start, i64 5
342 %c.5 = icmp ule i8* %start.5, %high
343 call void @use(i1 %c.5)
348 define void @test.not.uge.ugt(i8* %start, i8* %low, i8* %high) {
349 ; CHECK-LABEL: @test.not.uge.ugt(
351 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i64 3
352 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
353 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
355 ; CHECK-NEXT: ret void
357 ; CHECK-NEXT: [[F_0:%.*]] = icmp ugt i8* [[START]], [[HIGH]]
358 ; CHECK-NEXT: call void @use(i1 false)
359 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
360 ; CHECK-NEXT: [[F_1:%.*]] = icmp ugt i8* [[START_1]], [[HIGH]]
361 ; CHECK-NEXT: call void @use(i1 false)
362 ; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 2
363 ; CHECK-NEXT: [[F_2:%.*]] = icmp ugt i8* [[START_2]], [[HIGH]]
364 ; CHECK-NEXT: call void @use(i1 false)
365 ; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 3
366 ; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i8* [[START_3]], [[HIGH]]
367 ; CHECK-NEXT: call void @use(i1 false)
368 ; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 4
369 ; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i8* [[START_4]], [[HIGH]]
370 ; CHECK-NEXT: call void @use(i1 false)
371 ; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 5
372 ; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i8* [[START_5]], [[HIGH]]
373 ; CHECK-NEXT: call void @use(i1 [[C_5]])
374 ; CHECK-NEXT: ret void
377 %add.ptr.i = getelementptr inbounds i8, i8* %start, i64 3
378 %c.1 = icmp uge i8* %add.ptr.i, %high
379 br i1 %c.1, label %if.then, label %if.end
381 if.then: ; preds = %entry
384 if.end: ; preds = %entry
385 %f.0 = icmp ugt i8* %start, %high
386 call void @use(i1 %f.0)
388 %start.1 = getelementptr inbounds i8, i8* %start, i64 1
389 %f.1 = icmp ugt i8* %start.1, %high
390 call void @use(i1 %f.1)
392 %start.2 = getelementptr inbounds i8, i8* %start, i64 2
393 %f.2 = icmp ugt i8* %start.2, %high
394 call void @use(i1 %f.2)
396 %start.3 = getelementptr inbounds i8, i8* %start, i64 3
397 %f.3 = icmp ugt i8* %start.3, %high
398 call void @use(i1 %f.3)
400 %start.4 = getelementptr inbounds i8, i8* %start, i64 4
401 %f.4 = icmp ugt i8* %start.4, %high
402 call void @use(i1 %f.4)
404 %start.5 = getelementptr inbounds i8, i8* %start, i64 5
405 %c.5 = icmp ugt i8* %start.5, %high
406 call void @use(i1 %c.5)
411 define void @test.not.uge.uge(i8* %start, i8* %low, i8* %high) {
412 ; CHECK-LABEL: @test.not.uge.uge(
414 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i64 3
415 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
416 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
418 ; CHECK-NEXT: ret void
420 ; CHECK-NEXT: [[F_0:%.*]] = icmp ugt i8* [[START]], [[HIGH]]
421 ; CHECK-NEXT: call void @use(i1 false)
422 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
423 ; CHECK-NEXT: [[F_1:%.*]] = icmp uge i8* [[START_1]], [[HIGH]]
424 ; CHECK-NEXT: call void @use(i1 false)
425 ; CHECK-NEXT: [[START_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 2
426 ; CHECK-NEXT: [[F_2:%.*]] = icmp uge i8* [[START_2]], [[HIGH]]
427 ; CHECK-NEXT: call void @use(i1 false)
428 ; CHECK-NEXT: [[START_3:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 3
429 ; CHECK-NEXT: [[F_3:%.*]] = icmp uge i8* [[START_3]], [[HIGH]]
430 ; CHECK-NEXT: call void @use(i1 false)
431 ; CHECK-NEXT: [[START_4:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 4
432 ; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8* [[START_4]], [[HIGH]]
433 ; CHECK-NEXT: call void @use(i1 [[C_4]])
434 ; CHECK-NEXT: [[START_5:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 5
435 ; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8* [[START_5]], [[HIGH]]
436 ; CHECK-NEXT: call void @use(i1 [[C_5]])
437 ; CHECK-NEXT: ret void
440 %add.ptr.i = getelementptr inbounds i8, i8* %start, i64 3
441 %c.1 = icmp uge i8* %add.ptr.i, %high
442 br i1 %c.1, label %if.then, label %if.end
444 if.then: ; preds = %entry
447 if.end: ; preds = %entry
448 %f.0 = icmp ugt i8* %start, %high
449 call void @use(i1 %f.0)
451 %start.1 = getelementptr inbounds i8, i8* %start, i64 1
452 %f.1 = icmp uge i8* %start.1, %high
453 call void @use(i1 %f.1)
455 %start.2 = getelementptr inbounds i8, i8* %start, i64 2
456 %f.2 = icmp uge i8* %start.2, %high
457 call void @use(i1 %f.2)
459 %start.3 = getelementptr inbounds i8, i8* %start, i64 3
460 %f.3 = icmp uge i8* %start.3, %high
461 call void @use(i1 %f.3)
463 %start.4 = getelementptr inbounds i8, i8* %start, i64 4
464 %c.4 = icmp uge i8* %start.4, %high
465 call void @use(i1 %c.4)
467 %start.5 = getelementptr inbounds i8, i8* %start, i64 5
468 %c.5 = icmp uge i8* %start.5, %high
469 call void @use(i1 %c.5)
474 define void @test.not.uge.uge.nonconst(i8* %start, i8* %low, i8* %high, i8 %off) {
475 ; CHECK-LABEL: @test.not.uge.uge.nonconst(
477 ; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, i8* [[START:%.*]], i8 [[OFF:%.*]]
478 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[ADD_PTR_I]], [[HIGH:%.*]]
479 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
481 ; CHECK-NEXT: [[START_OFF_2:%.*]] = getelementptr inbounds i8, i8* [[START]], i8 [[OFF]]
482 ; CHECK-NEXT: [[T_0:%.*]] = icmp uge i8* [[START_OFF_2]], [[HIGH]]
483 ; CHECK-NEXT: call void @use(i1 true)
484 ; CHECK-NEXT: ret void
486 ; CHECK-NEXT: [[START_1:%.*]] = getelementptr inbounds i8, i8* [[START]], i64 1
487 ; CHECK-NEXT: [[C_0:%.*]] = icmp uge i8* [[START_1]], [[HIGH]]
488 ; CHECK-NEXT: call void @use(i1 [[C_0]])
489 ; CHECK-NEXT: [[START_OFF:%.*]] = getelementptr inbounds i8, i8* [[START]], i8 [[OFF]]
490 ; CHECK-NEXT: [[F_0:%.*]] = icmp uge i8* [[START_OFF]], [[HIGH]]
491 ; CHECK-NEXT: call void @use(i1 false)
492 ; CHECK-NEXT: ret void
495 %add.ptr.i = getelementptr inbounds i8, i8* %start, i8 %off
496 %c.1 = icmp uge i8* %add.ptr.i, %high
497 br i1 %c.1, label %if.then, label %if.end
499 if.then: ; preds = %entry
500 %start.off.2 = getelementptr inbounds i8, i8* %start, i8 %off
501 %t.0 = icmp uge i8* %start.off.2, %high
502 call void @use(i1 %t.0)
506 if.end: ; preds = %entry
507 %start.1 = getelementptr inbounds i8, i8* %start, i64 1
508 %c.0 = icmp uge i8* %start.1, %high
509 call void @use(i1 %c.0)
511 %start.off = getelementptr inbounds i8, i8* %start, i8 %off
512 %f.0 = icmp uge i8* %start.off, %high
513 call void @use(i1 %f.0)
518 ; Test which requires decomposing GEP %ptr, SHL().
519 define void @test.ult.gep.shl(i32* readonly %src, i32* readnone %max, i8 %idx) {
520 ; CHECK-LABEL: @test.ult.gep.shl(
521 ; CHECK-NEXT: check.0.min:
522 ; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i32 10
523 ; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt i32* [[ADD_10]], [[MAX:%.*]]
524 ; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
526 ; CHECK-NEXT: ret void
528 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IDX:%.*]], 5
529 ; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
531 ; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw i8 [[IDX]], 1
532 ; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_1]]
533 ; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[ADD_PTR_SHL_1]], [[MAX]]
534 ; CHECK-NEXT: call void @use(i1 true)
535 ; CHECK-NEXT: [[IDX_SHL_2:%.*]] = shl nuw i8 [[IDX]], 2
536 ; CHECK-NEXT: [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_2]]
537 ; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i32* [[ADD_PTR_SHL_2]], [[MAX]]
538 ; CHECK-NEXT: call void @use(i1 [[C_MAX_1]])
539 ; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i8 [[IDX]], 1
540 ; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_NOT_NUW]]
541 ; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult i32* [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
542 ; CHECK-NEXT: call void @use(i1 [[C_MAX_2]])
543 ; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i8 [[IDX]], 3
544 ; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i8 [[IDX_SHL_3]]
545 ; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ult i32* [[ADD_PTR_SHL_3]], [[MAX]]
546 ; CHECK-NEXT: call void @use(i1 [[C_MAX_3]])
547 ; CHECK-NEXT: ret void
550 %add.10 = getelementptr inbounds i32, i32* %src, i32 10
551 %c.add.10.max = icmp ugt i32* %add.10, %max
552 br i1 %c.add.10.max, label %trap, label %check.idx
557 check.idx: ; preds = %check.0.min
558 %cmp = icmp ult i8 %idx, 5
559 br i1 %cmp, label %check.max, label %trap
561 check.max: ; preds = %check.0.min
562 %idx.shl.1 = shl nuw i8 %idx, 1
563 %add.ptr.shl.1 = getelementptr inbounds i32, i32* %src, i8 %idx.shl.1
564 %c.max.0 = icmp ult i32* %add.ptr.shl.1, %max
565 call void @use(i1 %c.max.0)
567 %idx.shl.2 = shl nuw i8 %idx, 2
568 %add.ptr.shl.2 = getelementptr inbounds i32, i32* %src, i8 %idx.shl.2
569 %c.max.1 = icmp ult i32* %add.ptr.shl.2, %max
570 call void @use(i1 %c.max.1)
572 %idx.shl.not.nuw = shl i8 %idx, 1
573 %add.ptr.shl.not.nuw = getelementptr inbounds i32, i32* %src, i8 %idx.shl.not.nuw
574 %c.max.2 = icmp ult i32* %add.ptr.shl.not.nuw, %max
575 call void @use(i1 %c.max.2)
577 %idx.shl.3 = shl nuw i8 %idx, 3
578 %add.ptr.shl.3 = getelementptr inbounds i32, i32* %src, i8 %idx.shl.3
579 %c.max.3 = icmp ult i32* %add.ptr.shl.3, %max
580 call void @use(i1 %c.max.3)
585 ; Test which requires decomposing GEP %ptr, ZEXT(SHL()).
586 define void @test.ult.gep.shl.zext(i32* readonly %src, i32* readnone %max, i32 %idx, i32 %j) {
587 ; CHECK-LABEL: @test.ult.gep.shl.zext(
588 ; CHECK-NEXT: check.0.min:
589 ; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i32 10
590 ; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt i32* [[ADD_10]], [[MAX:%.*]]
591 ; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
593 ; CHECK-NEXT: ret void
595 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 5
596 ; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
598 ; CHECK-NEXT: [[IDX_SHL:%.*]] = shl nuw i32 [[IDX]], 1
599 ; CHECK-NEXT: [[EXT_1:%.*]] = zext i32 [[IDX_SHL]] to i64
600 ; CHECK-NEXT: [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_1]]
601 ; CHECK-NEXT: [[C_MAX_0:%.*]] = icmp ult i32* [[ADD_PTR_SHL]], [[MAX]]
602 ; CHECK-NEXT: call void @use(i1 true)
603 ; CHECK-NEXT: [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1
604 ; CHECK-NEXT: [[EXT_2:%.*]] = zext i32 [[IDX_SHL_NOT_NUW]] to i64
605 ; CHECK-NEXT: [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_2]]
606 ; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i32* [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
607 ; CHECK-NEXT: call void @use(i1 [[C_MAX_1]])
608 ; CHECK-NEXT: [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 2
609 ; CHECK-NEXT: [[EXT_3:%.*]] = zext i32 [[IDX_SHL_3]] to i64
610 ; CHECK-NEXT: [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[EXT_3]]
611 ; CHECK-NEXT: [[C_MAX_2:%.*]] = icmp ult i32* [[ADD_PTR_SHL_3]], [[MAX]]
612 ; CHECK-NEXT: call void @use(i1 [[C_MAX_2]])
613 ; CHECK-NEXT: ret void
616 %add.10 = getelementptr inbounds i32, i32* %src, i32 10
617 %c.add.10.max = icmp ugt i32* %add.10, %max
618 br i1 %c.add.10.max, label %trap, label %check.idx
623 check.idx: ; preds = %check.0.min
624 %cmp = icmp ult i32 %idx, 5
625 br i1 %cmp, label %check.max, label %trap
627 check.max: ; preds = %check.0.min
628 %idx.shl = shl nuw i32 %idx, 1
629 %ext.1 = zext i32 %idx.shl to i64
630 %add.ptr.shl = getelementptr inbounds i32, i32* %src, i64 %ext.1
631 %c.max.0 = icmp ult i32* %add.ptr.shl, %max
632 call void @use(i1 %c.max.0)
634 %idx.shl.not.nuw = shl i32 %idx, 1
635 %ext.2 = zext i32 %idx.shl.not.nuw to i64
636 %add.ptr.shl.not.nuw = getelementptr inbounds i32, i32* %src, i64 %ext.2
637 %c.max.1 = icmp ult i32* %add.ptr.shl.not.nuw, %max
638 call void @use(i1 %c.max.1)
640 %idx.shl.3 = shl nuw i32 %idx, 2
641 %ext.3 = zext i32 %idx.shl.3 to i64
642 %add.ptr.shl.3 = getelementptr inbounds i32, i32* %src, i64 %ext.3
643 %c.max.2 = icmp ult i32* %add.ptr.shl.3, %max
644 call void @use(i1 %c.max.2)
649 ; Make sure non-constant shift amounts are handled correctly.
650 define i1 @test.ult.gep.shl.nonconst.zext(i16 %B, i16* readonly %src, i16* readnone %max, i16 %idx, i16 %j) {
651 ; CHECK-LABEL: @test.ult.gep.shl.nonconst.zext(
652 ; CHECK-NEXT: check.0.min:
653 ; CHECK-NEXT: [[ADD_10:%.*]] = getelementptr inbounds i16, i16* [[SRC:%.*]], i16 10
654 ; CHECK-NEXT: [[C_ADD_10_MAX:%.*]] = icmp ugt i16* [[ADD_10]], [[MAX:%.*]]
655 ; CHECK-NEXT: br i1 [[C_ADD_10_MAX]], label [[EXIT_1:%.*]], label [[CHECK_IDX:%.*]]
657 ; CHECK-NEXT: ret i1 true
659 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[IDX:%.*]], 5
660 ; CHECK-NEXT: br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP:%.*]]
662 ; CHECK-NEXT: [[IDX_SHL:%.*]] = shl nuw i16 [[IDX]], [[B:%.*]]
663 ; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[IDX_SHL]] to i64
664 ; CHECK-NEXT: [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i16, i16* [[SRC]], i64 [[EXT]]
665 ; CHECK-NEXT: [[C_MAX:%.*]] = icmp ult i16* [[ADD_PTR_SHL]], [[MAX]]
666 ; CHECK-NEXT: ret i1 [[C_MAX]]
668 ; CHECK-NEXT: [[IDX_SHL_1:%.*]] = shl nuw i16 [[IDX]], [[B]]
669 ; CHECK-NEXT: [[EXT_1:%.*]] = zext i16 [[IDX_SHL_1]] to i64
670 ; CHECK-NEXT: [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i16, i16* [[SRC]], i64 [[EXT_1]]
671 ; CHECK-NEXT: [[C_MAX_1:%.*]] = icmp ult i16* [[ADD_PTR_SHL_1]], [[MAX]]
672 ; CHECK-NEXT: ret i1 [[C_MAX_1]]
675 %add.10 = getelementptr inbounds i16, i16* %src, i16 10
676 %c.add.10.max = icmp ugt i16* %add.10, %max
677 br i1 %c.add.10.max, label %exit.1, label %check.idx
683 check.idx: ; preds = %check.0.min
684 %cmp = icmp ult i16 %idx, 5
685 br i1 %cmp, label %check.max, label %trap
687 check.max: ; preds = %check.idx
688 %idx.shl = shl nuw i16 %idx, %B
689 %ext = zext i16 %idx.shl to i64
690 %add.ptr.shl = getelementptr inbounds i16, i16* %src, i64 %ext
691 %c.max = icmp ult i16* %add.ptr.shl, %max
694 trap: ; preds = %check.idx, %check.0.min
695 %idx.shl.1 = shl nuw i16 %idx, %B
696 %ext.1 = zext i16 %idx.shl.1 to i64
697 %add.ptr.shl.1 = getelementptr inbounds i16, i16* %src, i64 %ext.1
698 %c.max.1 = icmp ult i16* %add.ptr.shl.1, %max
702 declare void @use(i1)