1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=indvars -S < %s | FileCheck %s
4 ; Check that we are able to remove the range check basing on the following facts:
5 ; 0 <= len <= MAX_INT [1];
6 ; iv starts from len and goes down stopping at zero and [1], therefore
8 ; 3. In range_check_block, iv != 0 and [2], therefore
10 ; 4. iv.next = iv - 1 and [3], therefore
12 define void @test_predicated_simple_unsigned(ptr %p, ptr %arr) {
13 ; CHECK-LABEL: @test_predicated_simple_unsigned(
14 ; CHECK-NEXT: preheader:
15 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0:![0-9]+]]
16 ; CHECK-NEXT: br label [[LOOP:%.*]]
18 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
19 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
20 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
21 ; CHECK: range_check_block:
22 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1
23 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
25 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
26 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
27 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
28 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
30 ; CHECK-NEXT: ret void
32 ; CHECK-NEXT: unreachable
35 %len = load i32, ptr %p, !range !0
39 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
40 %zero_cond = icmp eq i32 %iv, 0
41 br i1 %zero_cond, label %exit, label %range_check_block
44 %iv.next = sub i32 %iv, 1
45 %range_check = icmp ult i32 %iv.next, %len
46 br i1 %range_check, label %backedge, label %fail
49 %el.ptr = getelementptr i32, ptr %p, i32 %iv
50 %el = load i32, ptr %el.ptr
51 %loop.cond = icmp eq i32 %el, 0
52 br i1 %loop.cond, label %loop, label %exit
61 define void @test_predicated_simple_signed(ptr %p, ptr %arr) {
62 ; CHECK-LABEL: @test_predicated_simple_signed(
63 ; CHECK-NEXT: preheader:
64 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0]]
65 ; CHECK-NEXT: br label [[LOOP:%.*]]
67 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
68 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
69 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
70 ; CHECK: range_check_block:
71 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1
72 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
74 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
75 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
76 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
77 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
79 ; CHECK-NEXT: ret void
81 ; CHECK-NEXT: unreachable
84 %len = load i32, ptr %p, !range !0
88 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
89 %zero_cond = icmp eq i32 %iv, 0
90 br i1 %zero_cond, label %exit, label %range_check_block
93 %iv.next = sub i32 %iv, 1
94 %range_check = icmp slt i32 %iv.next, %len
95 br i1 %range_check, label %backedge, label %fail
98 %el.ptr = getelementptr i32, ptr %p, i32 %iv
99 %el = load i32, ptr %el.ptr
100 %loop.cond = icmp eq i32 %el, 0
101 br i1 %loop.cond, label %loop, label %exit
110 ; Cannot remove checks because the range check fails on the last iteration.
111 define void @predicated_outside_loop_signed_neg(i32 %arg) nounwind #0 {
112 ; CHECK-LABEL: @predicated_outside_loop_signed_neg(
114 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
115 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
116 ; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
117 ; CHECK: outer.preheader:
118 ; CHECK-NEXT: br label [[OUTER:%.*]]
120 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
121 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
122 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
123 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
124 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
126 ; CHECK-NEXT: br label [[INNER:%.*]]
128 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
129 ; CHECK: outer.inc.loopexit:
130 ; CHECK-NEXT: br label [[OUTER_INC]]
132 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
133 ; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
134 ; CHECK: exit.loopexit:
135 ; CHECK-NEXT: br label [[EXIT]]
137 ; CHECK-NEXT: ret void
140 %sub1 = sub nsw i32 %arg, 1
141 %cmp1 = icmp slt i32 0, %sub1
142 br i1 %cmp1, label %outer, label %exit
145 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
146 %sub2 = sub nsw i32 %arg, %i
147 %sub3 = sub nsw i32 %sub2, 1
148 %cmp2 = icmp slt i32 0, %sub3
149 br i1 %cmp2, label %inner.ph, label %outer.inc
155 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
156 %j.inc = add nsw i32 %j, 1
157 %cmp3 = icmp slt i32 %j.inc, %sub3
158 br i1 %cmp3, label %inner, label %outer.inc
161 %i.inc = add nsw i32 %i, 1
162 %cmp4 = icmp slt i32 %i.inc, %arg
163 br i1 %cmp4, label %outer, label %exit
169 ; Range check can be removed.
170 define void @predicated_outside_loop_signed_pos(i32 %arg) nounwind #0 {
171 ; CHECK-LABEL: @predicated_outside_loop_signed_pos(
173 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
174 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
175 ; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
176 ; CHECK: outer.preheader:
177 ; CHECK-NEXT: br label [[OUTER:%.*]]
179 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
180 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
181 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
182 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
183 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
185 ; CHECK-NEXT: br label [[INNER:%.*]]
187 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
188 ; CHECK: outer.inc.loopexit:
189 ; CHECK-NEXT: br label [[OUTER_INC]]
191 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
192 ; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
193 ; CHECK: exit.loopexit:
194 ; CHECK-NEXT: br label [[EXIT]]
196 ; CHECK-NEXT: ret void
199 %sub1 = sub nsw i32 %arg, 1
200 %cmp1 = icmp slt i32 0, %sub1
201 br i1 %cmp1, label %outer, label %exit
204 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
205 %sub2 = sub nsw i32 %arg, %i
206 %sub3 = sub nsw i32 %sub2, 1
207 %cmp2 = icmp slt i32 0, %sub3
208 br i1 %cmp2, label %inner.ph, label %outer.inc
214 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
215 %j.inc = add nsw i32 %j, 1
216 %cmp3 = icmp slt i32 %j.inc, %sub3
217 br i1 %cmp3, label %inner, label %outer.inc
220 %i.inc = add nsw i32 %i, 1
221 %cmp4 = icmp slt i32 %i.inc, %sub1
222 br i1 %cmp4, label %outer, label %exit
228 define void @predicated_outside_loop_unsigned(i32 %arg) nounwind #0 {
229 ; CHECK-LABEL: @predicated_outside_loop_unsigned(
231 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
232 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
233 ; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
234 ; CHECK: outer.preheader:
235 ; CHECK-NEXT: br label [[OUTER:%.*]]
237 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
238 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
239 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
240 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
241 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
243 ; CHECK-NEXT: br label [[INNER:%.*]]
245 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
246 ; CHECK: outer.inc.loopexit:
247 ; CHECK-NEXT: br label [[OUTER_INC]]
249 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
250 ; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
251 ; CHECK: exit.loopexit:
252 ; CHECK-NEXT: br label [[EXIT]]
254 ; CHECK-NEXT: ret void
257 %sub1 = sub nsw i32 %arg, 1
258 %cmp1 = icmp slt i32 0, %sub1
259 br i1 %cmp1, label %outer, label %exit
262 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
263 %sub2 = sub nsw i32 %arg, %i
264 %sub3 = sub nsw i32 %sub2, 1
265 %cmp2 = icmp ult i32 0, %sub3
266 br i1 %cmp2, label %inner.ph, label %outer.inc
272 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
273 %j.inc = add nsw i32 %j, 1
274 %cmp3 = icmp slt i32 %j.inc, %sub3
275 br i1 %cmp3, label %inner, label %outer.inc
278 %i.inc = add nsw i32 %i, 1
279 %cmp4 = icmp slt i32 %i.inc, %arg
280 br i1 %cmp4, label %outer, label %exit
286 ; Cannot remove checks because the range check fails on the last iteration.
287 define void @predicated_inside_loop_signed_neg(i32 %arg) nounwind #0 {
288 ; CHECK-LABEL: @predicated_inside_loop_signed_neg(
290 ; CHECK-NEXT: br label [[OUTER:%.*]]
292 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
293 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
294 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
295 ; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
297 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
298 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
299 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
300 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
302 ; CHECK-NEXT: br label [[INNER:%.*]]
304 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
305 ; CHECK: outer.inc.loopexit:
306 ; CHECK-NEXT: br label [[OUTER_INC]]
308 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
309 ; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
310 ; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
312 ; CHECK-NEXT: ret void
318 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
319 %sub1 = sub nsw i32 %arg, 1
320 %cmp1 = icmp slt i32 0, %sub1
321 br i1 %cmp1, label %guarded, label %exit
324 %sub2 = sub nsw i32 %arg, %i
325 %sub3 = sub nsw i32 %sub2, 1
326 %cmp2 = icmp slt i32 0, %sub3
327 br i1 %cmp2, label %inner.ph, label %outer.inc
333 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
334 %j.inc = add nsw i32 %j, 1
335 %cmp3 = icmp slt i32 %j.inc, %sub3
336 br i1 %cmp3, label %inner, label %outer.inc
339 %i.inc = add nsw i32 %i, 1
340 %cmp4 = icmp slt i32 %i.inc, %arg
341 br i1 %cmp4, label %outer, label %exit
347 ; Range check can be trivially removed.
348 define void @predicated_inside_loop_signed_pos(i32 %arg) nounwind #0 {
349 ; CHECK-LABEL: @predicated_inside_loop_signed_pos(
351 ; CHECK-NEXT: br label [[OUTER:%.*]]
353 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
354 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
355 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
356 ; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
358 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
359 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
360 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
361 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
363 ; CHECK-NEXT: br label [[INNER:%.*]]
365 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
366 ; CHECK: outer.inc.loopexit:
367 ; CHECK-NEXT: br label [[OUTER_INC]]
369 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
370 ; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[SUB1]]
371 ; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
373 ; CHECK-NEXT: ret void
379 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
380 %sub1 = sub nsw i32 %arg, 1
381 %cmp1 = icmp slt i32 0, %sub1
382 br i1 %cmp1, label %guarded, label %exit
385 %sub2 = sub nsw i32 %arg, %i
386 %sub3 = sub nsw i32 %sub2, 1
387 %cmp2 = icmp slt i32 0, %sub3
388 br i1 %cmp2, label %inner.ph, label %outer.inc
394 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
395 %j.inc = add nsw i32 %j, 1
396 %cmp3 = icmp slt i32 %j.inc, %sub3
397 br i1 %cmp3, label %inner, label %outer.inc
400 %i.inc = add nsw i32 %i, 1
401 %cmp4 = icmp slt i32 %i.inc, %sub1
402 br i1 %cmp4, label %outer, label %exit
408 define void @predicated_inside_loop_unsigned(i32 %arg) nounwind #0 {
409 ; CHECK-LABEL: @predicated_inside_loop_unsigned(
411 ; CHECK-NEXT: br label [[OUTER:%.*]]
413 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
414 ; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
415 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
416 ; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
418 ; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
419 ; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
420 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
421 ; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
423 ; CHECK-NEXT: br label [[INNER:%.*]]
425 ; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
426 ; CHECK: outer.inc.loopexit:
427 ; CHECK-NEXT: br label [[OUTER_INC]]
429 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
430 ; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
431 ; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
433 ; CHECK-NEXT: ret void
439 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
440 %sub1 = sub nsw i32 %arg, 1
441 %cmp1 = icmp slt i32 0, %sub1
442 br i1 %cmp1, label %guarded, label %exit
445 %sub2 = sub nsw i32 %arg, %i
446 %sub3 = sub nsw i32 %sub2, 1
447 %cmp2 = icmp ult i32 0, %sub3
448 br i1 %cmp2, label %inner.ph, label %outer.inc
454 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
455 %j.inc = add nsw i32 %j, 1
456 %cmp3 = icmp slt i32 %j.inc, %sub3
457 br i1 %cmp3, label %inner, label %outer.inc
460 %i.inc = add nsw i32 %i, 1
461 %cmp4 = icmp slt i32 %i.inc, %arg
462 br i1 %cmp4, label %outer, label %exit
468 define void @test_can_predicate_simple_unsigned(ptr %p, ptr %arr) {
469 ; CHECK-LABEL: @test_can_predicate_simple_unsigned(
470 ; CHECK-NEXT: preheader:
471 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
472 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1
473 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
474 ; CHECK-NEXT: br label [[LOOP:%.*]]
476 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
477 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
478 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
479 ; CHECK: range_check_block:
480 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
481 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
483 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
484 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
485 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
486 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
488 ; CHECK-NEXT: ret void
490 ; CHECK-NEXT: unreachable
493 %len = load i32, ptr %p
497 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
498 %zero_cond = icmp eq i32 %iv, 0
499 br i1 %zero_cond, label %exit, label %range_check_block
502 %iv.next = sub i32 %iv, 1
503 %range_check = icmp ult i32 %iv.next, %len
504 br i1 %range_check, label %backedge, label %fail
507 %el.ptr = getelementptr i32, ptr %p, i32 %iv
508 %el = load i32, ptr %el.ptr
509 %loop.cond = icmp eq i32 %el, 0
510 br i1 %loop.cond, label %loop, label %exit
519 define void @test_can_predicate_simple_unsigned_inverted(ptr %p, ptr %arr) {
520 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted(
521 ; CHECK-NEXT: preheader:
522 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
523 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1
524 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
525 ; CHECK-NEXT: br label [[LOOP:%.*]]
527 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
528 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
529 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
530 ; CHECK: range_check_block:
531 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
532 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
534 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
535 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
536 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
537 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
539 ; CHECK-NEXT: ret void
541 ; CHECK-NEXT: unreachable
544 %len = load i32, ptr %p
548 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
549 %zero_cond = icmp eq i32 %iv, 0
550 br i1 %zero_cond, label %exit, label %range_check_block
553 %iv.next = sub i32 %iv, 1
554 %range_check = icmp uge i32 %iv.next, %len
555 br i1 %range_check, label %fail, label %backedge
558 %el.ptr = getelementptr i32, ptr %p, i32 %iv
559 %el = load i32, ptr %el.ptr
560 %loop.cond = icmp eq i32 %el, 0
561 br i1 %loop.cond, label %loop, label %exit
571 define void @test_can_predicate_simple_signed(ptr %p, ptr %arr) {
572 ; CHECK-LABEL: @test_can_predicate_simple_signed(
573 ; CHECK-NEXT: preheader:
574 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
575 ; CHECK-NEXT: br label [[LOOP:%.*]]
577 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
578 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
579 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
580 ; CHECK: range_check_block:
581 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
582 ; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
583 ; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
585 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
586 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
587 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
588 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
590 ; CHECK-NEXT: ret void
592 ; CHECK-NEXT: unreachable
595 %len = load i32, ptr %p
599 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
600 %zero_cond = icmp eq i32 %iv, 0
601 br i1 %zero_cond, label %exit, label %range_check_block
604 %iv.next = sub i32 %iv, 1
605 %range_check = icmp slt i32 %iv.next, %len
606 br i1 %range_check, label %backedge, label %fail
609 %el.ptr = getelementptr i32, ptr %p, i32 %iv
610 %el = load i32, ptr %el.ptr
611 %loop.cond = icmp eq i32 %el, 0
612 br i1 %loop.cond, label %loop, label %exit
621 define void @test_can_predicate_trunc_unsigned(ptr %p, ptr %arr) {
622 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned(
623 ; CHECK-NEXT: preheader:
624 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
625 ; CHECK-NEXT: [[START:%.*]] = zext i32 [[LEN]] to i64
626 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1
627 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
628 ; CHECK-NEXT: br label [[LOOP:%.*]]
630 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
631 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
632 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
633 ; CHECK: range_check_block:
634 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i64 [[IV]], 1
635 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
637 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
638 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
639 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
640 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
642 ; CHECK-NEXT: ret void
644 ; CHECK-NEXT: unreachable
647 %len = load i32, ptr %p
648 %start = zext i32 %len to i64
652 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
653 %zero_cond = icmp eq i64 %iv, 0
654 br i1 %zero_cond, label %exit, label %range_check_block
657 %iv.next = sub i64 %iv, 1
658 %narrow = trunc i64 %iv.next to i32
659 %range_check = icmp ult i32 %narrow, %len
660 br i1 %range_check, label %backedge, label %fail
663 %el.ptr = getelementptr i32, ptr %arr, i64 %iv
664 %el = load i32, ptr %el.ptr
665 %loop.cond = icmp eq i32 %el, 0
666 br i1 %loop.cond, label %loop, label %exit
675 define void @test_can_predicate_trunc_unsigned_inverted(ptr %p, ptr %arr) {
676 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_inverted(
677 ; CHECK-NEXT: preheader:
678 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
679 ; CHECK-NEXT: [[START:%.*]] = zext i32 [[LEN]] to i64
680 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1
681 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
682 ; CHECK-NEXT: br label [[LOOP:%.*]]
684 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
685 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
686 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
687 ; CHECK: range_check_block:
688 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i64 [[IV]], 1
689 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
691 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
692 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
693 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
694 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
696 ; CHECK-NEXT: ret void
698 ; CHECK-NEXT: unreachable
701 %len = load i32, ptr %p
702 %start = zext i32 %len to i64
706 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
707 %zero_cond = icmp eq i64 %iv, 0
708 br i1 %zero_cond, label %exit, label %range_check_block
711 %iv.next = sub i64 %iv, 1
712 %narrow = trunc i64 %iv.next to i32
713 %range_check = icmp uge i32 %narrow, %len
714 br i1 %range_check, label %fail, label %backedge
717 %el.ptr = getelementptr i32, ptr %arr, i64 %iv
718 %el = load i32, ptr %el.ptr
719 %loop.cond = icmp eq i32 %el, 0
720 br i1 %loop.cond, label %loop, label %exit
729 define void @test_can_predicate_trunc_unsigned_different_start_and_len(ptr %p, i64 %start, ptr %arr) {
730 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len(
731 ; CHECK-NEXT: preheader:
732 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
733 ; CHECK-NEXT: br label [[LOOP:%.*]]
735 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
736 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
737 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
738 ; CHECK: range_check_block:
739 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i64 [[IV]], 1
740 ; CHECK-NEXT: [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
741 ; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[NARROW]], [[LEN]]
742 ; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
744 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
745 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
746 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
747 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
749 ; CHECK-NEXT: ret void
751 ; CHECK-NEXT: unreachable
754 %len = load i32, ptr %p
758 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
759 %zero_cond = icmp eq i64 %iv, 0
760 br i1 %zero_cond, label %exit, label %range_check_block
763 %iv.next = sub i64 %iv, 1
764 %narrow = trunc i64 %iv.next to i32
765 %range_check = icmp ult i32 %narrow, %len
766 br i1 %range_check, label %backedge, label %fail
769 %el.ptr = getelementptr i32, ptr %arr, i64 %iv
770 %el = load i32, ptr %el.ptr
771 %loop.cond = icmp eq i32 %el, 0
772 br i1 %loop.cond, label %loop, label %exit
781 define void @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(ptr %p, i64 %start, ptr %arr) {
782 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(
783 ; CHECK-NEXT: preheader:
784 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
785 ; CHECK-NEXT: br label [[LOOP:%.*]]
787 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
788 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
789 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
790 ; CHECK: range_check_block:
791 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i64 [[IV]], 1
792 ; CHECK-NEXT: [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
793 ; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp uge i32 [[NARROW]], [[LEN]]
794 ; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[FAIL:%.*]], label [[BACKEDGE]]
796 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
797 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
798 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
799 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
801 ; CHECK-NEXT: ret void
803 ; CHECK-NEXT: unreachable
806 %len = load i32, ptr %p
810 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
811 %zero_cond = icmp eq i64 %iv, 0
812 br i1 %zero_cond, label %exit, label %range_check_block
815 %iv.next = sub i64 %iv, 1
816 %narrow = trunc i64 %iv.next to i32
817 %range_check = icmp uge i32 %narrow, %len
818 br i1 %range_check, label %fail, label %backedge
821 %el.ptr = getelementptr i32, ptr %arr, i64 %iv
822 %el = load i32, ptr %el.ptr
823 %loop.cond = icmp eq i32 %el, 0
824 br i1 %loop.cond, label %loop, label %exit
833 define void @test_can_predicate_simple_unsigned_different_start(i32 %start, ptr %p, ptr %arr) {
834 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_different_start(
835 ; CHECK-NEXT: preheader:
836 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
837 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
838 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
839 ; CHECK-NEXT: br label [[LOOP:%.*]]
841 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
842 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
843 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
844 ; CHECK: range_check_block:
845 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
846 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
848 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
849 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
850 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
851 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
853 ; CHECK-NEXT: ret void
855 ; CHECK-NEXT: unreachable
858 %len = load i32, ptr %p
862 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
863 %zero_cond = icmp eq i32 %iv, 0
864 br i1 %zero_cond, label %exit, label %range_check_block
867 %iv.next = sub i32 %iv, 1
868 %range_check = icmp ult i32 %iv.next, %len
869 br i1 %range_check, label %backedge, label %fail
872 %el.ptr = getelementptr i32, ptr %p, i32 %iv
873 %el = load i32, ptr %el.ptr
874 %loop.cond = icmp eq i32 %el, 0
875 br i1 %loop.cond, label %loop, label %exit
884 define void @test_can_predicate_simple_unsigned_inverted_different_start(i32 %start, ptr %p, ptr %arr) {
885 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted_different_start(
886 ; CHECK-NEXT: preheader:
887 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
888 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
889 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
890 ; CHECK-NEXT: br label [[LOOP:%.*]]
892 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
893 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
894 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
895 ; CHECK: range_check_block:
896 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
897 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
899 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
900 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
901 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
902 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
904 ; CHECK-NEXT: ret void
906 ; CHECK-NEXT: unreachable
909 %len = load i32, ptr %p
913 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
914 %zero_cond = icmp eq i32 %iv, 0
915 br i1 %zero_cond, label %exit, label %range_check_block
918 %iv.next = sub i32 %iv, 1
919 %range_check = icmp uge i32 %iv.next, %len
920 br i1 %range_check, label %fail, label %backedge
923 %el.ptr = getelementptr i32, ptr %p, i32 %iv
924 %el = load i32, ptr %el.ptr
925 %loop.cond = icmp eq i32 %el, 0
926 br i1 %loop.cond, label %loop, label %exit
936 define void @test_can_predicate_simple_signed_different_start(i32 %start, ptr %p, ptr %arr) {
937 ; CHECK-LABEL: @test_can_predicate_simple_signed_different_start(
938 ; CHECK-NEXT: preheader:
939 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
940 ; CHECK-NEXT: br label [[LOOP:%.*]]
942 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
943 ; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
944 ; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
945 ; CHECK: range_check_block:
946 ; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1
947 ; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
948 ; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
950 ; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
951 ; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
952 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
953 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
955 ; CHECK-NEXT: ret void
957 ; CHECK-NEXT: unreachable
960 %len = load i32, ptr %p
964 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
965 %zero_cond = icmp eq i32 %iv, 0
966 br i1 %zero_cond, label %exit, label %range_check_block
969 %iv.next = sub i32 %iv, 1
970 %range_check = icmp slt i32 %iv.next, %len
971 br i1 %range_check, label %backedge, label %fail
974 %el.ptr = getelementptr i32, ptr %p, i32 %iv
975 %el = load i32, ptr %el.ptr
976 %loop.cond = icmp eq i32 %el, 0
977 br i1 %loop.cond, label %loop, label %exit
986 !0 = !{i32 0, i32 2147483647}