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_eq_to_uge(ptr %start, i16 %len) {
13 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge(
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: [[AND:%.*]] = and i1 true, true
26 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
28 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
29 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
30 ; CHECK-NEXT: br label [[LOOP_HEADER]]
32 ; CHECK-NEXT: ret void
35 %upper = getelementptr inbounds i32, ptr %start, i16 %len
36 %len.neg = icmp slt i16 %len, 0
37 br i1 %len.neg, label %exit, label %loop.ph
43 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
44 %c = icmp eq ptr %ptr.iv, %upper
45 br i1 %c, label %exit, label %for.body
48 %t.1 = icmp uge ptr %ptr.iv, %start
49 %t.2 = icmp ult ptr %ptr.iv, %upper
50 %and = and i1 %t.1, %t.2
51 br i1 %and, label %loop.latch, label %exit
54 call void @use(ptr %ptr.iv)
55 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
62 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_incoming_values_reordered(ptr %start, i16 %len) {
63 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_incoming_values_reordered(
65 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
66 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
67 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
69 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
71 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ [[START]], [[LOOP_PH]] ]
72 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
73 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
75 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
76 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
78 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
79 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
80 ; CHECK-NEXT: br label [[LOOP_HEADER]]
82 ; CHECK-NEXT: ret void
85 %upper = getelementptr inbounds i32, ptr %start, i16 %len
86 %len.neg = icmp slt i16 %len, 0
87 br i1 %len.neg, label %exit, label %loop.ph
93 %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %loop.ph ]
94 %c = icmp eq ptr %ptr.iv, %upper
95 br i1 %c, label %exit, label %for.body
98 %t.1 = icmp uge ptr %ptr.iv, %start
99 %t.2 = icmp ult ptr %ptr.iv, %upper
100 %and = and i1 %t.1, %t.2
101 br i1 %and, label %loop.latch, label %exit
104 call void @use(ptr %ptr.iv)
105 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
106 br label %loop.header
112 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_preheader(ptr %start, i16 %len) {
113 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_preheader(
115 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
116 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
117 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
118 ; CHECK: loop.header:
119 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
120 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
121 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
123 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
124 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
126 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
127 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
128 ; CHECK-NEXT: br label [[LOOP_HEADER]]
130 ; CHECK-NEXT: ret void
133 %upper = getelementptr inbounds i32, ptr %start, i16 %len
134 %len.neg = icmp slt i16 %len, 0
135 br i1 %len.neg, label %exit, label %loop.header
138 %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
139 %c = icmp eq ptr %ptr.iv, %upper
140 br i1 %c, label %exit, label %for.body
143 %t.1 = icmp uge ptr %ptr.iv, %start
144 %t.2 = icmp ult ptr %ptr.iv, %upper
145 %and = and i1 %t.1, %t.2
146 br i1 %and, label %loop.latch, label %exit
149 call void @use(ptr %ptr.iv)
150 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
151 br label %loop.header
157 define void @test_monotonic_ptr_iv_inc_1_different_element_types(ptr %start, i16 %len) {
158 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types(
160 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
161 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
162 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
164 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
165 ; CHECK: loop.header:
166 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
167 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
168 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
170 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
171 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
173 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
174 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
175 ; CHECK-NEXT: br label [[LOOP_HEADER]]
177 ; CHECK-NEXT: ret void
180 %upper = getelementptr inbounds i32, ptr %start, i16 %len
181 %len.neg = icmp slt i16 %len, 0
182 br i1 %len.neg, label %exit, label %loop.ph
185 br label %loop.header
188 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
189 %c = icmp eq ptr %ptr.iv, %upper
190 br i1 %c, label %exit, label %for.body
193 %t.1 = icmp uge ptr %ptr.iv, %start
194 %t.2 = icmp ult ptr %ptr.iv, %upper
195 %and = and i1 %t.1, %t.2
196 br i1 %and, label %loop.latch, label %exit
199 call void @use(ptr %ptr.iv)
200 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
201 br label %loop.header
207 define void @test_monotonic_ptr_iv_inc_1_different_element_types_2(ptr %start, i16 %len) {
208 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_2(
210 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
211 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
212 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
214 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
215 ; CHECK: loop.header:
216 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
217 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
218 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
220 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
221 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
222 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
224 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
225 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
226 ; CHECK-NEXT: br label [[LOOP_HEADER]]
228 ; CHECK-NEXT: ret void
231 %upper = getelementptr inbounds i8, ptr %start, i16 %len
232 %len.neg = icmp slt i16 %len, 0
233 br i1 %len.neg, label %exit, label %loop.ph
236 br label %loop.header
239 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
240 %c = icmp eq ptr %ptr.iv, %upper
241 br i1 %c, label %exit, label %for.body
244 %t.1 = icmp uge ptr %ptr.iv, %start
245 %t.2 = icmp ult ptr %ptr.iv, %upper
246 %and = and i1 %t.1, %t.2
247 br i1 %and, label %loop.latch, label %exit
250 call void @use(ptr %ptr.iv)
251 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
252 br label %loop.header
258 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(ptr %start, ptr %end) {
259 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(
261 ; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
262 ; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
264 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
265 ; CHECK: loop.header:
266 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
267 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
268 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
270 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
271 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
273 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
274 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
275 ; CHECK-NEXT: br label [[LOOP_HEADER]]
277 ; CHECK-NEXT: ret void
280 %start.ult.end = icmp uge ptr %start, %end
281 br i1 %start.ult.end, label %exit, label %loop.ph
284 br label %loop.header
287 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
288 %c = icmp eq ptr %ptr.iv, %end
289 br i1 %c, label %exit, label %for.body
292 %t.1 = icmp uge ptr %ptr.iv, %start
293 %t.2 = icmp ult ptr %ptr.iv, %end
294 %and = and i1 %t.1, %t.2
295 br i1 %and, label %loop.latch, label %exit
298 call void @use(ptr %ptr.iv)
299 %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
300 br label %loop.header
306 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr(ptr %start, ptr %end) {
307 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr(
309 ; CHECK-NEXT: [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
310 ; CHECK-NEXT: br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
312 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
313 ; CHECK: loop.header:
314 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
315 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
316 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
318 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
319 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
320 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
322 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
323 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
324 ; CHECK-NEXT: br label [[LOOP_HEADER]]
326 ; CHECK-NEXT: ret void
329 %start.ult.end = icmp uge ptr %start, %end
330 br i1 %start.ult.end, label %exit, label %loop.ph
333 br label %loop.header
336 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
337 %c = icmp eq ptr %ptr.iv, %end
338 br i1 %c, label %exit, label %for.body
341 %t.1 = icmp uge ptr %ptr.iv, %start
342 %t.2 = icmp ult ptr %ptr.iv, %end
343 %and = and i1 %t.1, %t.2
344 br i1 %and, label %loop.latch, label %exit
347 call void @use(ptr %ptr.iv)
348 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
349 br label %loop.header
355 define void @test_ptr_iv_upper_may_be_less_than_start(ptr %start, i16 %len) {
356 ; CHECK-LABEL: @test_ptr_iv_upper_may_be_less_than_start(
358 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
359 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
360 ; CHECK: loop.header:
361 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
362 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
363 ; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
365 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
366 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_2]]
367 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
369 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
370 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
371 ; CHECK-NEXT: br label [[LOOP_HEADER]]
373 ; CHECK-NEXT: ret void
376 %upper = getelementptr inbounds i32, ptr %start, i16 %len
377 br label %loop.header
380 %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
381 %c = icmp eq ptr %ptr.iv, %upper
382 br i1 %c, label %exit, label %for.body
385 %c.1 = icmp uge ptr %ptr.iv, %start
386 %c.2 = icmp ult ptr %ptr.iv, %upper
387 %and = and i1 %c.1, %c.2
388 br i1 %and, label %loop.latch, label %exit
391 call void @use(ptr %ptr.iv)
392 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
393 br label %loop.header
399 define void @test_no_ptr_iv_step_inst_doesnt_use_phi(ptr %start, ptr %p, i16 %len) {
400 ; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi(
402 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
403 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
404 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
406 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
407 ; CHECK: loop.header:
408 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
409 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
410 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
412 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
413 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
414 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
415 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
417 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
418 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[P:%.*]], i16 1
419 ; CHECK-NEXT: br label [[LOOP_HEADER]]
421 ; CHECK-NEXT: ret void
424 %upper = getelementptr inbounds i32, ptr %start, i16 %len
425 %len.neg = icmp slt i16 %len, 0
426 br i1 %len.neg, label %exit, label %loop.ph
429 br label %loop.header
432 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
433 %c = icmp eq ptr %ptr.iv, %upper
434 br i1 %c, label %exit, label %for.body
437 %t.1 = icmp uge ptr %ptr.iv, %start
438 %t.2 = icmp ult ptr %ptr.iv, %upper
439 %and = and i1 %t.1, %t.2
440 br i1 %and, label %loop.latch, label %exit
443 call void @use(ptr %ptr.iv)
444 %ptr.iv.next = getelementptr inbounds i32, ptr %p, i16 1
445 br label %loop.header
451 define void @test_no_ptr_iv_step_inst_doesnt_use_phi_2(ptr %start, ptr %end, i16 %len) {
452 ; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi_2(
454 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
455 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
456 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
458 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
459 ; CHECK: loop.header:
460 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
461 ; CHECK-NEXT: [[PTR_IV_2:%.*]] = phi ptr [ [[END:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT]], [[LOOP_LATCH]] ]
462 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
463 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[LOOP_NEXT:%.*]]
465 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
466 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
467 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
468 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
470 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
471 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV_2]], i16 1
472 ; CHECK-NEXT: br label [[LOOP_HEADER]]
474 ; CHECK-NEXT: ret void
477 %upper = getelementptr inbounds float, ptr %start, i16 %len
478 %len.neg = icmp slt i16 %len, 0
479 br i1 %len.neg, label %exit, label %loop.ph
482 br label %loop.header
485 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
486 %ptr.iv.2 = phi ptr [ %end, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
487 %c = icmp eq ptr %ptr.iv, %upper
488 br i1 %c, label %exit, label %loop.next
491 %t.1 = icmp uge ptr %ptr.iv, %start
492 %t.2 = icmp ult ptr %ptr.iv, %upper
493 %and = and i1 %t.1, %t.2
494 br i1 %and, label %loop.latch, label %exit
497 call void @use(ptr %ptr.iv)
498 %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv.2, i16 1
499 br label %loop.header
505 define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
506 ; CHECK-LABEL: @test_no_ptr_iv_different_start(
508 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
509 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
510 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
512 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
513 ; CHECK: loop.header:
514 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[P:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
515 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
516 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
518 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
519 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
520 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
521 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
523 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
524 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
525 ; CHECK-NEXT: br label [[LOOP_HEADER]]
527 ; CHECK-NEXT: ret void
530 %upper = getelementptr inbounds i32, ptr %start, i16 %len
531 %len.neg = icmp slt i16 %len, 0
532 br i1 %len.neg, label %exit, label %loop.ph
535 br label %loop.header
538 %ptr.iv = phi ptr [ %p, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
539 %c = icmp eq ptr %ptr.iv, %upper
540 br i1 %c, label %exit, label %for.body
543 %c.1 = icmp uge ptr %ptr.iv, %start
544 %c.2 = icmp ult ptr %ptr.iv, %upper
545 %and = and i1 %c.1, %c.2
546 br i1 %and, label %loop.latch, label %exit
549 call void @use(ptr %ptr.iv)
550 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
551 br label %loop.header
557 define void @test_ptr_iv_not_inbounds(ptr %start, i16 %len) {
558 ; CHECK-LABEL: @test_ptr_iv_not_inbounds(
560 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
561 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
562 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
564 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
565 ; CHECK: loop.header:
566 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
567 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
568 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
570 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, true
571 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
573 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
574 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
575 ; CHECK-NEXT: br label [[LOOP_HEADER]]
577 ; CHECK-NEXT: ret void
580 %upper = getelementptr inbounds i32, ptr %start, i16 %len
581 %len.neg = icmp slt i16 %len, 0
582 br i1 %len.neg, label %exit, label %loop.ph
585 br label %loop.header
588 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
589 %c = icmp eq ptr %ptr.iv, %upper
590 br i1 %c, label %exit, label %for.body
593 %c.1 = icmp uge ptr %ptr.iv, %start
594 %c.2 = icmp ult ptr %ptr.iv, %upper
595 %and = and i1 %c.1, %c.2
596 br i1 %and, label %loop.latch, label %exit
599 call void @use(ptr %ptr.iv)
600 %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
601 br label %loop.header
607 define void @test_var_step_not_monotonic(ptr %start, i16 %len, i16 %step) {
608 ; CHECK-LABEL: @test_var_step_not_monotonic(
610 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
611 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
612 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
614 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
615 ; CHECK: loop.header:
616 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
617 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
618 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
620 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
621 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
622 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
623 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
625 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
626 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
627 ; CHECK-NEXT: br label [[LOOP_HEADER]]
629 ; CHECK-NEXT: ret void
632 %upper = getelementptr inbounds i32, ptr %start, i16 %len
633 %len.neg = icmp slt i16 %len, 0
634 br i1 %len.neg, label %exit, label %loop.ph
637 br label %loop.header
640 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
641 %c = icmp eq ptr %ptr.iv, %upper
642 br i1 %c, label %exit, label %for.body
645 %c.1 = icmp uge ptr %ptr.iv, %start
646 %c.2 = icmp ult ptr %ptr.iv, %upper
647 %and = and i1 %c.1, %c.2
648 br i1 %and, label %loop.latch, label %exit
651 call void @use(ptr %ptr.iv)
652 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
653 br label %loop.header
659 define void @test_monotonic_ptr_iv_step_neg_1(ptr %start, i16 %len) {
660 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_neg_1(
662 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
663 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
664 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
666 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
667 ; CHECK: loop.header:
668 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
669 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
670 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
672 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
673 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
674 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
675 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
677 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
678 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 -1
679 ; CHECK-NEXT: br label [[LOOP_HEADER]]
681 ; CHECK-NEXT: ret void
684 %upper = getelementptr inbounds i32, ptr %start, i16 %len
685 %len.neg = icmp slt i16 %len, 0
686 br i1 %len.neg, label %exit, label %loop.ph
689 br label %loop.header
692 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
693 %c = icmp eq ptr %ptr.iv, %upper
694 br i1 %c, label %exit, label %for.body
697 %c.1 = icmp uge ptr %ptr.iv, %start
698 %c.2 = icmp ult ptr %ptr.iv, %upper
699 %and = and i1 %c.1, %c.2
700 br i1 %and, label %loop.latch, label %exit
703 call void @use(ptr %ptr.iv)
704 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 -1
705 br label %loop.header
711 define void @test_monotonic_ptr_iv_step_sign_unknown(ptr %start, i16 %len, i16 %step) {
712 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_unknown(
714 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
715 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
716 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
718 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
719 ; CHECK: loop.header:
720 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
721 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
722 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
724 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
725 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
726 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
727 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
729 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
730 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
731 ; CHECK-NEXT: br label [[LOOP_HEADER]]
733 ; CHECK-NEXT: ret void
736 %upper = getelementptr inbounds i32, ptr %start, i16 %len
737 %len.neg = icmp slt i16 %len, 0
738 br i1 %len.neg, label %exit, label %loop.ph
741 br label %loop.header
744 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
745 %c = icmp eq ptr %ptr.iv, %upper
746 br i1 %c, label %exit, label %for.body
749 %c.1 = icmp uge ptr %ptr.iv, %start
750 %c.2 = icmp ult ptr %ptr.iv, %upper
751 %and = and i1 %c.1, %c.2
752 br i1 %and, label %loop.latch, label %exit
755 call void @use(ptr %ptr.iv)
756 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
757 br label %loop.header
763 define void @test_monotonic_ptr_iv_step_sign_positive_through_assume(ptr %start, i16 %len, i16 %step) {
764 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume(
766 ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
767 ; CHECK-NEXT: call void @llvm.assume(i1 [[STEP_POS]])
768 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
769 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
770 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
772 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
773 ; CHECK: loop.header:
774 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
775 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
776 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
778 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
779 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
780 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
781 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
783 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
784 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
785 ; CHECK-NEXT: br label [[LOOP_HEADER]]
787 ; CHECK-NEXT: ret void
790 %step.pos = icmp sge i16 %step, 0
791 call void @llvm.assume(i1 %step.pos)
792 %upper = getelementptr inbounds i32, ptr %start, i16 %len
793 %len.neg = icmp slt i16 %len, 0
794 br i1 %len.neg, label %exit, label %loop.ph
797 br label %loop.header
800 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
801 %c = icmp eq ptr %ptr.iv, %upper
802 br i1 %c, label %exit, label %for.body
805 %t.1 = icmp uge ptr %ptr.iv, %start
806 %t.2 = icmp ult ptr %ptr.iv, %upper
807 %and = and i1 %t.1, %t.2
808 br i1 %and, label %loop.latch, label %exit
811 call void @use(ptr %ptr.iv)
812 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
813 br label %loop.header
819 define void @test_monotonic_ptr_iv_step_sign_negative_through_assume(ptr %start, i16 %len, i16 %step) {
820 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_negative_through_assume(
822 ; CHECK-NEXT: [[STEP_POS:%.*]] = icmp sle i16 [[STEP:%.*]], 0
823 ; CHECK-NEXT: call void @llvm.assume(i1 [[STEP_POS]])
824 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
825 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
826 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
828 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
829 ; CHECK: loop.header:
830 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
831 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
832 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
834 ; CHECK-NEXT: [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
835 ; CHECK-NEXT: [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
836 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
837 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
839 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
840 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
841 ; CHECK-NEXT: br label [[LOOP_HEADER]]
843 ; CHECK-NEXT: ret void
846 %step.pos = icmp sle i16 %step, 0
847 call void @llvm.assume(i1 %step.pos)
848 %upper = getelementptr inbounds i32, ptr %start, i16 %len
849 %len.neg = icmp slt i16 %len, 0
850 br i1 %len.neg, label %exit, label %loop.ph
853 br label %loop.header
856 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
857 %c = icmp eq ptr %ptr.iv, %upper
858 br i1 %c, label %exit, label %for.body
861 %c.1 = icmp uge ptr %ptr.iv, %start
862 %c.2 = icmp ult ptr %ptr.iv, %upper
863 %and = and i1 %c.1, %c.2
864 br i1 %and, label %loop.latch, label %exit
867 call void @use(ptr %ptr.iv)
868 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
869 br label %loop.header
875 define void @test_monotonic_ptr_iv_inc_2(ptr %start, i16 %len) {
876 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2(
878 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
879 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
880 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
882 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
883 ; CHECK: loop.header:
884 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
885 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
886 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
888 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
889 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
890 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
892 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
893 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
894 ; CHECK-NEXT: br label [[LOOP_HEADER]]
896 ; CHECK-NEXT: ret void
899 %upper = getelementptr inbounds i32, ptr %start, i16 %len
900 %len.neg = icmp slt i16 %len, 0
901 br i1 %len.neg, label %exit, label %loop.ph
904 br label %loop.header
907 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
908 %c = icmp eq ptr %ptr.iv, %upper
909 br i1 %c, label %exit, label %for.body
912 %t.1 = icmp uge ptr %ptr.iv, %start
913 %t.2 = icmp ult ptr %ptr.iv, %upper
914 %and = and i1 %t.1, %t.2
915 br i1 %and, label %loop.latch, label %exit
918 call void @use(ptr %ptr.iv)
919 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
920 br label %loop.header
926 define void @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(ptr %start, i16 %len) {
927 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(
929 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
930 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
931 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
933 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
934 ; CHECK: loop.header:
935 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
936 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
937 ; CHECK-NEXT: br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
939 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
940 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[T_2]]
941 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
942 ; CHECK-NEXT: br label [[LOOP_LATCH]]
944 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
945 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
946 ; CHECK-NEXT: br label [[LOOP_HEADER]]
948 ; CHECK-NEXT: ret void
951 %upper = getelementptr inbounds i32, ptr %start, i16 %len
952 %len.neg = icmp slt i16 %len, 0
953 br i1 %len.neg, label %exit, label %loop.ph
956 br label %loop.header
959 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
960 %c.1 = icmp eq ptr %ptr.iv, %upper
961 br i1 %c.1, label %exit, label %for.body
964 %t.1 = icmp uge ptr %ptr.iv, %start
965 %t.2 = icmp ult ptr %ptr.iv, %upper
966 %and = and i1 %t.1, %t.2
967 call void @use.i1(i1 %and)
971 call void @use(ptr %ptr.iv)
972 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
973 br label %loop.header
979 define void @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(ptr %start, i16 %len) {
980 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(
982 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
983 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
984 ; CHECK-NEXT: call void @llvm.assume(i1 [[LEN_NEG]])
985 ; CHECK-NEXT: br label [[LOOP_PH:%.*]]
987 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
988 ; CHECK: loop.header:
989 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
990 ; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
991 ; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
993 ; CHECK-NEXT: br label [[LOOP_LATCH]]
995 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
996 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
997 ; CHECK-NEXT: br label [[LOOP_HEADER]]
999 ; CHECK-NEXT: [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
1000 ; CHECK-NEXT: [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1001 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
1002 ; CHECK-NEXT: call void @use.i1(i1 [[AND]])
1003 ; CHECK-NEXT: ret void
1006 %upper = getelementptr inbounds i32, ptr %start, i16 %len
1007 %len.neg = icmp sge i16 %len, 0
1008 call void @llvm.assume(i1 %len.neg)
1012 br label %loop.header
1015 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1016 %c = icmp ne ptr %ptr.iv, %upper
1017 br i1 %c, label %exit, label %for.body
1020 br label %loop.latch
1023 call void @use(ptr %ptr.iv)
1024 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
1025 br label %loop.header
1028 %c.2 = icmp uge ptr %ptr.iv, %start
1029 %c.3 = icmp ult ptr %ptr.iv, %upper
1030 %and = and i1 %c.2, %c.3
1031 call void @use.i1(i1 %and)
1035 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_inbounds(ptr %start, i16 %len) {
1036 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_inbounds(
1037 ; CHECK-NEXT: entry:
1038 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
1039 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1040 ; CHECK-NEXT: br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1042 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
1043 ; CHECK: loop.header:
1044 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1045 ; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1046 ; CHECK-NEXT: br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1048 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
1049 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1050 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
1051 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1052 ; CHECK: loop.latch:
1053 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
1054 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
1055 ; CHECK-NEXT: br label [[LOOP_HEADER]]
1057 ; CHECK-NEXT: ret void
1060 %upper = getelementptr i32, ptr %start, i16 %len
1061 %len.neg = icmp slt i16 %len, 0
1062 br i1 %len.neg, label %exit, label %loop.ph
1065 br label %loop.header
1068 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1069 %c = icmp eq ptr %ptr.iv, %upper
1070 br i1 %c, label %exit, label %for.body
1073 %t.1 = icmp uge ptr %ptr.iv, %start
1074 %t.2 = icmp ult ptr %ptr.iv, %upper
1075 %and = and i1 %t.1, %t.2
1076 br i1 %and, label %loop.latch, label %exit
1079 call void @use(ptr %ptr.iv)
1080 %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
1081 br label %loop.header