1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
8 declare void @use.i1(i1)
9 declare void @llvm.assume(i1)
12 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
13 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(
15 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
16 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
17 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
19 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
21 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
22 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
23 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
25 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
26 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
28 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
29 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
31 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
32 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
33 ; CHECK-NEXT: br label [[LOOP_HEADER]]
35 ; CHECK-NEXT: ret void
38 %upper = getelementptr inbounds i32, ptr %start, i16 %len
39 %len.neg = icmp slt i16 %len, 0
40 br i1 %len.neg, label %exit, label %loop.ph
46 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
47 %c = icmp eq ptr %ptr.iv, %upper
48 br i1 %c, label %exit, label %for.body
51 %c.1 = call i1 @cond()
52 br i1 %c.1, label %loop.next, label %exit
55 %t.1 = icmp uge ptr %ptr.iv, %start
56 %t.2 = icmp ult ptr %ptr.iv, %upper
57 %and = and i1 %t.1, %t.2
58 br i1 %and, label %loop.latch, label %exit
61 call void @use(ptr %ptr.iv)
62 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
69 define void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
70 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(
72 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
73 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
74 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
76 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
78 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
79 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
80 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
82 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
83 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
85 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
86 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
87 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
89 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
90 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
91 ; CHECK-NEXT: br label [[LOOP_HEADER]]
93 ; CHECK-NEXT: ret void
96 %upper = getelementptr inbounds i8, ptr %start, i16 %len
97 %len.neg = icmp slt i16 %len, 0
98 br i1 %len.neg, label %exit, label %loop.ph
101 br label %loop.header
104 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
105 %c = icmp eq ptr %ptr.iv, %upper
106 br i1 %c, label %exit, label %for.body
109 %c.1 = call i1 @cond()
110 br i1 %c.1, label %loop.next, label %exit
113 %t.1 = icmp uge ptr %ptr.iv, %start
114 %t.2 = icmp ult ptr %ptr.iv, %upper
115 %and = and i1 %t.1, %t.2
116 br i1 %and, label %loop.latch, label %exit
119 call void @use(ptr %ptr.iv)
120 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
121 br label %loop.header
127 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
128 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(
130 ; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
131 ; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
133 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
134 ; CHECK: loop.header:
135 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
136 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
137 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
139 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
140 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
142 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
143 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
145 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
146 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
147 ; CHECK-NEXT: br label [[LOOP_HEADER]]
149 ; CHECK-NEXT: ret void
152 %start.ult.end = icmp uge ptr %start, %end
153 br i1 %start.ult.end, label %exit, label %loop.ph
156 br label %loop.header
159 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
160 %c = icmp eq ptr %ptr.iv, %end
161 br i1 %c, label %exit, label %for.body
164 %c.1 = call i1 @cond()
165 br i1 %c.1, label %loop.next, label %exit
168 %t.1 = icmp uge ptr %ptr.iv, %start
169 %t.2 = icmp ult ptr %ptr.iv, %end
170 %and = and i1 %t.1, %t.2
171 br i1 %and, label %loop.latch, label %exit
174 call void @use(ptr %ptr.iv)
175 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
176 br label %loop.header
182 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
183 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(
185 ; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
186 ; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
188 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
189 ; CHECK: loop.header:
190 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
191 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
192 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
194 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
195 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
197 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
198 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
199 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
201 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
202 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
203 ; CHECK-NEXT: br label [[LOOP_HEADER]]
205 ; CHECK-NEXT: ret void
208 %start.ult.end = icmp uge ptr %start, %end
209 br i1 %start.ult.end, label %exit, label %loop.ph
212 br label %loop.header
215 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
216 %c = icmp eq ptr %ptr.iv, %end
217 br i1 %c, label %exit, label %for.body
220 %c.1 = call i1 @cond()
221 br i1 %c.1, label %loop.next, label %exit
224 %t.1 = icmp uge ptr %ptr.iv, %start
225 %t.2 = icmp ult ptr %ptr.iv, %end
226 %and = and i1 %t.1, %t.2
227 br i1 %and, label %loop.latch, label %exit
230 call void @use(ptr %ptr.iv)
231 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
232 br label %loop.header
238 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) {
239 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(
241 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]]
242 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
243 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
245 ; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]]
246 ; CHECK-NEXT: call void @llvm.assume(i1 [[START_ULT_END]])
247 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
248 ; CHECK: loop.header:
249 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
250 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
251 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
253 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
254 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
256 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
257 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
258 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
260 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
261 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
262 ; CHECK-NEXT: br label [[LOOP_HEADER]]
264 ; CHECK-NEXT: ret void
267 %upper = getelementptr inbounds i32, ptr %end, i16 %len
268 %len.neg = icmp slt i16 %len, 0
269 br i1 %len.neg, label %exit, label %loop.ph
272 %start.ult.end = icmp ult ptr %start, %upper
273 call void @llvm.assume(i1 %start.ult.end)
274 br label %loop.header
277 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
278 %c = icmp eq ptr %ptr.iv, %upper
279 br i1 %c, label %exit, label %for.body
282 %c.1 = call i1 @cond()
283 br i1 %c.1, label %loop.next, label %exit
286 %t.1 = icmp uge ptr %ptr.iv, %start
287 %t.2 = icmp ult ptr %ptr.iv, %upper
288 %and = and i1 %t.1, %t.2
289 br i1 %and, label %loop.latch, label %exit
292 call void @use(ptr %ptr.iv)
293 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
294 br label %loop.header
300 define void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) {
301 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(
303 ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
304 ; CHECK-NEXT: call void @llvm.assume(i1 [[STEP_POS]])
305 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
306 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
307 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
309 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
310 ; CHECK: loop.header:
311 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
312 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
313 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
315 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
316 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]]
318 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
319 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
320 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
321 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
323 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
324 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
325 ; CHECK-NEXT: br label [[LOOP_HEADER]]
327 ; CHECK-NEXT: ret void
330 %step.pos = icmp sge i16 %step, 0
331 call void @llvm.assume(i1 %step.pos)
332 %upper = getelementptr inbounds i32, ptr %start, i16 %len
333 %len.neg = icmp slt i16 %len, 0
334 br i1 %len.neg, label %exit, label %loop.ph
337 br label %loop.header
340 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
341 %c = icmp eq ptr %ptr.iv, %upper
342 br i1 %c, label %exit, label %for.body
345 %c.1 = call i1 @cond()
346 br i1 %c.1, label %then, label %exit
349 %c.2 = icmp uge ptr %ptr.iv, %start
350 %c.3 = icmp ult ptr %ptr.iv, %upper
351 %and = and i1 %c.2, %c.3
352 br i1 %and, label %loop.latch, label %exit
355 call void @use(ptr %ptr.iv)
356 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
357 br label %loop.header
363 define void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) {
364 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit(
366 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
367 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
368 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
370 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
371 ; CHECK: loop.header:
372 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
373 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
374 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
376 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
377 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
379 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
380 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
381 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
382 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
383 ; CHECK-NEXT: br label [[LOOP_LATCH]]
385 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
386 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
387 ; CHECK-NEXT: br label [[LOOP_HEADER]]
389 ; CHECK-NEXT: ret void
392 %upper = getelementptr inbounds i32, ptr %start, i16 %len
393 %len.neg = icmp slt i16 %len, 0
394 br i1 %len.neg, label %exit, label %loop.ph
397 br label %loop.header
400 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
401 %c.0 = call i1 @cond()
402 br i1 %c.0, label %exit, label %for.body
405 %c.1 = icmp ne ptr %ptr.iv, %upper
406 br i1 %c.1, label %then, label %loop.latch
409 %t.1 = icmp uge ptr %ptr.iv, %start
410 %t.2 = icmp ult ptr %ptr.iv, %upper
411 %and = and i1 %t.1, %t.2
412 call void @use.i1(i1 %and)
416 call void @use(ptr %ptr.iv)
417 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
418 br label %loop.header
424 define void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) {
425 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2(
427 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
428 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
429 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
431 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
432 ; CHECK: loop.header:
433 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
434 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
435 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
437 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
438 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]]
440 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
441 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
442 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
443 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
444 ; CHECK-NEXT: br label [[LOOP_LATCH]]
446 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
447 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
448 ; CHECK-NEXT: br label [[LOOP_HEADER]]
450 ; CHECK-NEXT: ret void
453 %upper = getelementptr inbounds i32, ptr %start, i16 %len
454 %len.neg = icmp slt i16 %len, 0
455 br i1 %len.neg, label %exit, label %loop.ph
458 br label %loop.header
461 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
462 %c.1 = icmp ne ptr %ptr.iv, %upper
463 br i1 %c.1, label %then, label %for.body
466 %c.0 = call i1 @cond()
467 br i1 %c.0, label %exit, label %loop.latch
470 %t.1 = icmp uge ptr %ptr.iv, %start
471 %t.2 = icmp ult ptr %ptr.iv, %upper
472 %and = and i1 %t.1, %t.2
473 call void @use.i1(i1 %and)
477 call void @use(ptr %ptr.iv)
478 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
479 br label %loop.header
485 define void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) {
486 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(
488 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
489 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
490 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
492 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
493 ; CHECK: loop.header:
494 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
495 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
496 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
498 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
499 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
501 ; CHECK-NEXT: br label [[LOOP_LATCH]]
503 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
504 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
505 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
506 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
507 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
508 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
509 ; CHECK-NEXT: br label [[LOOP_HEADER]]
511 ; CHECK-NEXT: ret void
514 %upper = getelementptr inbounds i32, ptr %start, i16 %len
515 %len.neg = icmp slt i16 %len, 0
516 br i1 %len.neg, label %exit, label %loop.ph
519 br label %loop.header
522 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
523 %c.0 = call i1 @cond()
524 br i1 %c.0, label %exit, label %for.body
527 %c.1 = icmp ne ptr %ptr.iv, %upper
528 br i1 %c.1, label %then, label %loop.latch
534 %c.2 = icmp uge ptr %ptr.iv, %start
535 %c.3 = icmp ult ptr %ptr.iv, %upper
536 %and = and i1 %c.2, %c.3
537 call void @use.i1(i1 %and)
538 call void @use(ptr %ptr.iv)
539 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
540 br label %loop.header
546 define void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) {
547 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit(
549 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
550 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
551 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
553 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
554 ; CHECK: loop.header:
555 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
556 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
557 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
559 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
560 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
562 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
563 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_3]]
564 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
565 ; CHECK-NEXT: br label [[LOOP_LATCH]]
567 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
568 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
569 ; CHECK-NEXT: br label [[LOOP_HEADER]]
571 ; CHECK-NEXT: ret void
574 %upper = getelementptr inbounds i32, ptr %start, i16 %len
575 %len.neg = icmp slt i16 %len, 0
576 br i1 %len.neg, label %exit, label %loop.ph
579 br label %loop.header
582 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
583 %c.1 = icmp eq ptr %ptr.iv, %upper
584 br i1 %c.1, label %exit, label %for.body
587 %c.0 = call i1 @cond()
588 br i1 %c.0, label %exit, label %then
591 %c.2 = icmp uge ptr %ptr.iv, %start
592 %c.3 = icmp ult ptr %ptr.iv, %upper
593 %and = and i1 %c.2, %c.3
594 call void @use.i1(i1 %and)
598 call void @use(ptr %ptr.iv)
599 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
600 br label %loop.header
606 define void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) {
607 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(
609 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
610 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
611 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
613 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
614 ; CHECK: loop.header:
615 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
616 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
617 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
619 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
620 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
622 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
623 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
624 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
625 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
626 ; CHECK-NEXT: br label [[LOOP_LATCH]]
628 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
629 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
630 ; CHECK-NEXT: br label [[LOOP_HEADER]]
632 ; CHECK-NEXT: ret void
635 %upper = getelementptr inbounds i32, ptr %start, i16 %len
636 %len.neg = icmp slt i16 %len, 0
637 br i1 %len.neg, label %exit, label %loop.ph
640 br label %loop.header
643 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
644 %c.0 = call i1 @cond()
645 br i1 %c.0, label %exit, label %for.body
648 %c.1 = icmp ne ptr %ptr.iv, %upper
649 br i1 %c.1, label %then, label %loop.latch
652 %c.2 = icmp uge ptr %ptr.iv, %start
653 %c.3 = icmp ult ptr %ptr.iv, %upper
654 %and = and i1 %c.2, %c.3
655 call void @use.i1(i1 %and)
659 call void @use(ptr %ptr.iv)
660 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
661 br label %loop.header
667 define void @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(ptr %start, i16 %len) {
668 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(
670 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
671 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
672 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
674 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
675 ; CHECK: loop.header:
676 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
677 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
678 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
680 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
681 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
683 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
684 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
685 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
686 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
687 ; CHECK-NEXT: br label [[LOOP_LATCH]]
689 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
690 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 4
691 ; CHECK-NEXT: br label [[LOOP_HEADER]]
693 ; CHECK-NEXT: ret void
696 %upper = getelementptr inbounds i64, ptr %start, i16 %len
697 %len.neg = icmp slt i16 %len, 0
698 br i1 %len.neg, label %exit, label %loop.ph
701 br label %loop.header
704 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
705 %c.0 = call i1 @cond()
706 br i1 %c.0, label %exit, label %for.body
709 %c.1 = icmp ne ptr %ptr.iv, %upper
710 br i1 %c.1, label %then, label %loop.latch
713 %c.2 = icmp uge ptr %ptr.iv, %start
714 %c.3 = icmp ult ptr %ptr.iv, %upper
715 %and = and i1 %c.2, %c.3
716 call void @use.i1(i1 %and)
720 call void @use(ptr %ptr.iv)
721 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 4
722 br label %loop.header
728 define void @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(ptr %start, i16 %len) {
729 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(
731 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
732 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
733 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
735 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
736 ; CHECK: loop.header:
737 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
738 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
739 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
741 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
742 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
744 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
745 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
746 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
747 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
748 ; CHECK-NEXT: br label [[LOOP_LATCH]]
750 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
751 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 5
752 ; CHECK-NEXT: br label [[LOOP_HEADER]]
754 ; CHECK-NEXT: ret void
757 %upper = getelementptr inbounds i64, ptr %start, i16 %len
758 %len.neg = icmp slt i16 %len, 0
759 br i1 %len.neg, label %exit, label %loop.ph
762 br label %loop.header
765 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
766 %c.0 = call i1 @cond()
767 br i1 %c.0, label %exit, label %for.body
770 %c.1 = icmp ne ptr %ptr.iv, %upper
771 br i1 %c.1, label %then, label %loop.latch
774 %c.2 = icmp uge ptr %ptr.iv, %start
775 %c.3 = icmp ult ptr %ptr.iv, %upper
776 %and = and i1 %c.2, %c.3
777 call void @use.i1(i1 %and)
781 call void @use(ptr %ptr.iv)
782 %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 5
783 br label %loop.header
789 define void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) {
790 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop(
792 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
793 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
794 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_NEG]])
795 ; CHECK-NEXT: br label [[LOOP_PH:%.*]]
797 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
798 ; CHECK: loop.header:
799 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
800 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
801 ; CHECK-NEXT: br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
803 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
804 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
805 ; CHECK-NEXT: br label [[LOOP_HEADER]]
807 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
808 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
810 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
811 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
812 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
813 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
814 ; CHECK-NEXT: br label [[EXIT_2]]
816 ; CHECK-NEXT: ret void
819 %upper = getelementptr inbounds i32, ptr %start, i16 %len
820 %len.neg = icmp sge i16 %len, 0
821 call void @llvm.assume(i1 %len.neg)
825 br label %loop.header
828 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
829 %c.0 = call i1 @cond()
830 br i1 %c.0, label %exit, label %loop.latch
833 call void @use(ptr %ptr.iv)
834 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
835 br label %loop.header
838 %c.1 = icmp ne ptr %ptr.iv, %upper
839 br i1 %c.1, label %then, label %exit.2
842 %c.2 = icmp uge ptr %ptr.iv, %start
843 %c.3 = icmp ult ptr %ptr.iv, %upper
844 %and = and i1 %c.2, %c.3
845 call void @use.i1(i1 %and)
852 define void @test_step_gep_doesnt_use_ptr_iv_phi(ptr %start, ptr %other, i16 %len) {
853 ; CHECK-LABEL: @test_step_gep_doesnt_use_ptr_iv_phi(
855 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
856 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
857 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
859 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
860 ; CHECK: loop.header:
861 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
862 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
863 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
865 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
866 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
868 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
869 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
870 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
871 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
873 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
874 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[OTHER:%.*]], i16 1
875 ; CHECK-NEXT: br label [[LOOP_HEADER]]
877 ; CHECK-NEXT: ret void
880 %upper = getelementptr inbounds float, ptr %start, i16 %len
881 %len.neg = icmp slt i16 %len, 0
882 br i1 %len.neg, label %exit, label %loop.ph
885 br label %loop.header
888 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
889 %c = icmp eq ptr %ptr.iv, %upper
890 br i1 %c, label %exit, label %for.body
893 %c.1 = call i1 @cond()
894 br i1 %c.1, label %loop.next, label %exit
897 %t.1 = icmp uge ptr %ptr.iv, %start
898 %t.2 = icmp ult ptr %ptr.iv, %upper
899 %and = and i1 %t.1, %t.2
900 br i1 %and, label %loop.latch, label %exit
903 call void @use(ptr %ptr.iv)
904 %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1
905 br label %loop.header
911 define void @test_step_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
912 ; CHECK-LABEL: @test_step_gep_not_inbounds(
914 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
915 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
916 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
918 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
919 ; CHECK: loop.header:
920 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
921 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
922 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
924 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
925 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
927 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
928 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
930 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
931 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr float, ptr [[PTR_IV]], i16 1
932 ; CHECK-NEXT: br label [[LOOP_HEADER]]
934 ; CHECK-NEXT: ret void
937 %upper = getelementptr inbounds float, ptr %start, i16 %len
938 %len.neg = icmp slt i16 %len, 0
939 br i1 %len.neg, label %exit, label %loop.ph
942 br label %loop.header
945 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
946 %c = icmp eq ptr %ptr.iv, %upper
947 br i1 %c, label %exit, label %for.body
950 %c.1 = call i1 @cond()
951 br i1 %c.1, label %loop.next, label %exit
954 %t.1 = icmp uge ptr %ptr.iv, %start
955 %t.2 = icmp ult ptr %ptr.iv, %upper
956 %and = and i1 %t.1, %t.2
957 br i1 %and, label %loop.latch, label %exit
960 call void @use(ptr %ptr.iv)
961 %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1
962 br label %loop.header
968 define void @test_upper_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
969 ; CHECK-LABEL: @test_upper_gep_not_inbounds(
971 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr float, ptr [[START:%.*]], i16 [[LEN:%.*]]
972 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
973 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
975 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
976 ; CHECK: loop.header:
977 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
978 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
979 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
981 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
982 ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
984 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
985 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
986 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
988 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
989 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1
990 ; CHECK-NEXT: br label [[LOOP_HEADER]]
992 ; CHECK-NEXT: ret void
995 %upper = getelementptr float, ptr %start, i16 %len
996 %len.neg = icmp slt i16 %len, 0
997 br i1 %len.neg, label %exit, label %loop.ph
1000 br label %loop.header
1003 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1004 %c = icmp eq ptr %ptr.iv, %upper
1005 br i1 %c, label %exit, label %for.body
1008 %c.1 = call i1 @cond()
1009 br i1 %c.1, label %loop.next, label %exit
1012 %t.1 = icmp uge ptr %ptr.iv, %start
1013 %t.2 = icmp ult ptr %ptr.iv, %upper
1014 %and = and i1 %t.1, %t.2
1015 br i1 %and, label %loop.latch, label %exit
1018 call void @use(ptr %ptr.iv)
1019 %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i16 1
1020 br label %loop.header