1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=indvars -S < %s | FileCheck %s
6 ; Range check here can be turned into invariant check.
7 define i32 @test_simple_case(i32 %start, i32 %len) {
8 ; CHECK-LABEL: @test_simple_case(
10 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
11 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
12 ; CHECK-NEXT: br label [[LOOP:%.*]]
14 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
15 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
16 ; CHECK-NEXT: br i1 [[ZERO_CHECK]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
17 ; CHECK: range_check_block:
18 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
20 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
21 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
22 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
24 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
25 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
27 ; CHECK-NEXT: ret i32 -1
29 ; CHECK-NEXT: ret i32 -2
35 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
36 %zero_check = icmp ne i32 %iv, 0
37 br i1 %zero_check, label %range_check_block, label %failed_1
40 %iv.minus.1 = add i32 %iv, -1
41 %range_check = icmp ult i32 %iv.minus.1, %len
42 br i1 %range_check, label %backedge, label %failed_2
45 %iv.next = add i32 %iv, -1
46 %loop_cond = call i1 @cond()
47 br i1 %loop_cond, label %done, label %loop
59 ; This example is equivalent to @test_simple_case, with only difference that
60 ; both checks are littered with extra irrelevant conditions. We should be able
61 ; to replace it with invariant despite this fact.
62 ; https://alive2.llvm.org/ce/z/G4iW8c
63 define i32 @test_litter_conditions(i32 %start, i32 %len) {
64 ; CHECK-LABEL: @test_litter_conditions(
66 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
67 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
68 ; CHECK-NEXT: br label [[LOOP:%.*]]
70 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
71 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
72 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
73 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
74 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
75 ; CHECK: range_check_block:
76 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
77 ; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[RANGE_CHECK_FIRST_ITER]], [[FAKE_2]]
78 ; CHECK-NEXT: br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
80 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
81 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
82 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
84 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
85 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
87 ; CHECK-NEXT: ret i32 -1
89 ; CHECK-NEXT: ret i32 -2
95 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
96 %zero_check = icmp ne i32 %iv, 0
97 %fake_1 = call i1 @cond()
98 %and_1 = and i1 %zero_check, %fake_1
99 br i1 %and_1, label %range_check_block, label %failed_1
102 %iv.minus.1 = add i32 %iv, -1
103 %range_check = icmp ult i32 %iv.minus.1, %len
104 %fake_2 = call i1 @cond()
105 %and_2 = and i1 %range_check, %fake_2
106 br i1 %and_2, label %backedge, label %failed_2
109 %iv.next = add i32 %iv, -1
110 %loop_cond = call i1 @cond()
111 br i1 %loop_cond, label %done, label %loop
123 ; Same as test_litter_conditions, but swapped exit block branches
124 ; and exit condition expressed by OR. Still optimizable.
125 define i32 @test_litter_conditions_inverse(i32 %start, i32 %len) {
126 ; CHECK-LABEL: @test_litter_conditions_inverse(
128 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
129 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
130 ; CHECK-NEXT: br label [[LOOP:%.*]]
132 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
133 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
134 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
135 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
136 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
137 ; CHECK: range_check_block:
138 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
139 ; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[RANGE_CHECK_FAILED_FIRST_ITER]], [[FAKE_2]]
140 ; CHECK-NEXT: br i1 [[OR_2]], label [[FAILED_2:%.*]], label [[BACKEDGE]]
142 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
143 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
144 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
146 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
147 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
149 ; CHECK-NEXT: ret i32 -1
151 ; CHECK-NEXT: ret i32 -2
157 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
158 %zero_check = icmp ne i32 %iv, 0
159 %fake_1 = call i1 @cond()
160 %and_1 = and i1 %zero_check, %fake_1
161 br i1 %and_1, label %range_check_block, label %failed_1
164 %iv.minus.1 = add i32 %iv, -1
165 %range_check_failed = icmp uge i32 %iv.minus.1, %len
166 %fake_2 = call i1 @cond()
167 %or_2 = or i1 %range_check_failed, %fake_2
168 br i1 %or_2, label %failed_2, label %backedge
171 %iv.next = add i32 %iv, -1
172 %loop_cond = call i1 @cond()
173 br i1 %loop_cond, label %done, label %loop
185 define i32 @test_litter_conditions_01(i32 %start, i32 %len) {
186 ; CHECK-LABEL: @test_litter_conditions_01(
188 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
189 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
190 ; CHECK-NEXT: br label [[LOOP:%.*]]
192 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
193 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
194 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
195 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
196 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
197 ; CHECK: range_check_block:
198 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
200 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
201 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
202 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
204 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
205 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
207 ; CHECK-NEXT: ret i32 -1
209 ; CHECK-NEXT: ret i32 -2
215 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
216 %zero_check = icmp ne i32 %iv, 0
217 %fake_1 = call i1 @cond()
218 %and_1 = and i1 %zero_check, %fake_1
219 br i1 %and_1, label %range_check_block, label %failed_1
222 %iv.minus.1 = add i32 %iv, -1
223 %range_check = icmp ult i32 %iv.minus.1, %len
224 br i1 %range_check, label %backedge, label %failed_2
227 %iv.next = add i32 %iv, -1
228 %loop_cond = call i1 @cond()
229 br i1 %loop_cond, label %done, label %loop
241 ; Same as test_litter_conditions_01, but swapped exit block branches
242 ; and condition expressed by OR. Still optimizable.
243 define i32 @test_litter_conditions_01_inverse(i32 %start, i32 %len) {
244 ; CHECK-LABEL: @test_litter_conditions_01_inverse(
246 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
247 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
248 ; CHECK-NEXT: br label [[LOOP:%.*]]
250 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
251 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
252 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
253 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
254 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
255 ; CHECK: range_check_block:
256 ; CHECK-NEXT: br i1 [[RANGE_CHECK_FAILED_FIRST_ITER]], label [[FAILED_2:%.*]], label [[BACKEDGE]]
258 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
259 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
260 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
262 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
263 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
265 ; CHECK-NEXT: ret i32 -1
267 ; CHECK-NEXT: ret i32 -2
273 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
274 %zero_check = icmp ne i32 %iv, 0
275 %fake_1 = call i1 @cond()
276 %and_1 = and i1 %zero_check, %fake_1
277 br i1 %and_1, label %range_check_block, label %failed_1
280 %iv.minus.1 = add i32 %iv, -1
281 %range_check_failed = icmp uge i32 %iv.minus.1, %len
282 br i1 %range_check_failed, label %failed_2, label %backedge
285 %iv.next = add i32 %iv, -1
286 %loop_cond = call i1 @cond()
287 br i1 %loop_cond, label %done, label %loop
299 ; TODO: Simplified version 2 of test_litter_conditions.
300 define i32 @test_litter_conditions_02(i32 %start, i32 %len) {
301 ; CHECK-LABEL: @test_litter_conditions_02(
303 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
304 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
305 ; CHECK-NEXT: br label [[LOOP:%.*]]
307 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
308 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
309 ; CHECK-NEXT: br i1 [[ZERO_CHECK]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
310 ; CHECK: range_check_block:
311 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
312 ; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[RANGE_CHECK_FIRST_ITER]], [[FAKE_2]]
313 ; CHECK-NEXT: br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
315 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
316 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
317 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
319 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
320 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
322 ; CHECK-NEXT: ret i32 -1
324 ; CHECK-NEXT: ret i32 -2
330 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
331 %zero_check = icmp ne i32 %iv, 0
332 br i1 %zero_check, label %range_check_block, label %failed_1
335 %iv.minus.1 = add i32 %iv, -1
336 %range_check = icmp ult i32 %iv.minus.1, %len
337 %fake_2 = call i1 @cond()
338 %and_2 = and i1 %range_check, %fake_2
339 br i1 %and_2, label %backedge, label %failed_2
342 %iv.next = add i32 %iv, -1
343 %loop_cond = call i1 @cond()
344 br i1 %loop_cond, label %done, label %loop
356 ; Same as test_litter_conditions_02, but swapped exit block branches,
357 ; and condition is expressed as OR. Still optimizable.
358 define i32 @test_litter_conditions_02_inverse(i32 %start, i32 %len) {
359 ; CHECK-LABEL: @test_litter_conditions_02_inverse(
361 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
362 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
363 ; CHECK-NEXT: br label [[LOOP:%.*]]
365 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
366 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
367 ; CHECK-NEXT: br i1 [[ZERO_CHECK]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
368 ; CHECK: range_check_block:
369 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
370 ; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[RANGE_CHECK_FAILED_FIRST_ITER]], [[FAKE_2]]
371 ; CHECK-NEXT: br i1 [[OR_2]], label [[FAILED_2:%.*]], label [[BACKEDGE]]
373 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
374 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
375 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
377 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
378 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
380 ; CHECK-NEXT: ret i32 -1
382 ; CHECK-NEXT: ret i32 -2
388 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
389 %zero_check = icmp ne i32 %iv, 0
390 br i1 %zero_check, label %range_check_block, label %failed_1
393 %iv.minus.1 = add i32 %iv, -1
394 %range_check_failed = icmp uge i32 %iv.minus.1, %len
395 %fake_2 = call i1 @cond()
396 %or_2 = or i1 %range_check_failed, %fake_2
397 br i1 %or_2, label %failed_2, label %backedge
400 %iv.next = add i32 %iv, -1
401 %loop_cond = call i1 @cond()
402 br i1 %loop_cond, label %done, label %loop
414 ; Same as @test_litter_conditions, but all conditions are computed in
415 ; header block. Make sure we infer fact from the right context.
416 ; https://alive2.llvm.org/ce/z/JiD-Pw
417 define i32 @test_litter_conditions_bad_context(i32 %start, i32 %len) {
418 ; CHECK-LABEL: @test_litter_conditions_bad_context(
420 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
421 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
422 ; CHECK-NEXT: br label [[LOOP:%.*]]
424 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
425 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
426 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
427 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
428 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
429 ; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[RANGE_CHECK_FIRST_ITER]], [[FAKE_2]]
430 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
431 ; CHECK: range_check_block:
432 ; CHECK-NEXT: br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
434 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
435 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
436 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
438 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
439 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
441 ; CHECK-NEXT: ret i32 -1
443 ; CHECK-NEXT: ret i32 -2
449 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
450 %zero_check = icmp ne i32 %iv, 0
451 %fake_1 = call i1 @cond()
452 %and_1 = and i1 %zero_check, %fake_1
453 %iv.minus.1 = add i32 %iv, -1
454 %range_check = icmp ult i32 %iv.minus.1, %len
455 %fake_2 = call i1 @cond()
456 %and_2 = and i1 %range_check, %fake_2
457 br i1 %and_1, label %range_check_block, label %failed_1
460 br i1 %and_2, label %backedge, label %failed_2
463 %iv.next = add i32 %iv, -1
464 %loop_cond = call i1 @cond()
465 br i1 %loop_cond, label %done, label %loop
477 ; Same as @test_litter_conditions_bad_context, but swapped exit block branches,
478 ; and conditions expressed as OR. Still optimizable.
479 define i32 @test_litter_conditions_bad_context_inverse(i32 %start, i32 %len) {
480 ; CHECK-LABEL: @test_litter_conditions_bad_context_inverse(
482 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
483 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
484 ; CHECK-NEXT: br label [[LOOP:%.*]]
486 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
487 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
488 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
489 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
490 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
491 ; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[RANGE_CHECK_FAILED_FIRST_ITER]], [[FAKE_2]]
492 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
493 ; CHECK: range_check_block:
494 ; CHECK-NEXT: br i1 [[OR_2]], label [[FAILED_2:%.*]], label [[BACKEDGE]]
496 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
497 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
498 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
500 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
501 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
503 ; CHECK-NEXT: ret i32 -1
505 ; CHECK-NEXT: ret i32 -2
511 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
512 %zero_check = icmp ne i32 %iv, 0
513 %fake_1 = call i1 @cond()
514 %and_1 = and i1 %zero_check, %fake_1
515 %iv.minus.1 = add i32 %iv, -1
516 %range_check_failed = icmp uge i32 %iv.minus.1, %len
517 %fake_2 = call i1 @cond()
518 %or_2 = or i1 %range_check_failed, %fake_2
519 br i1 %and_1, label %range_check_block, label %failed_1
522 br i1 %or_2, label %failed_2, label %backedge
525 %iv.next = add i32 %iv, -1
526 %loop_cond = call i1 @cond()
527 br i1 %loop_cond, label %done, label %loop
539 ; This test is equivalent to @test_simple_case, with only difference
540 ; that both checks are merged together into one 'and' check. This
541 ; should not prevent turning the range check into invariant.
542 ; https://alive2.llvm.org/ce/z/G-2ERB
543 define i32 @test_and_conditions(i32 %start, i32 %len) {
544 ; CHECK-LABEL: @test_and_conditions(
546 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
547 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
548 ; CHECK-NEXT: br label [[LOOP:%.*]]
550 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
551 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
552 ; CHECK-NEXT: [[BOTH_CHECKS:%.*]] = and i1 [[ZERO_CHECK]], [[RANGE_CHECK_FIRST_ITER]]
553 ; CHECK-NEXT: br i1 [[BOTH_CHECKS]], label [[BACKEDGE]], label [[FAILED:%.*]]
555 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
556 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
557 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
559 ; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
560 ; CHECK-NEXT: ret i32 [[IV_LCSSA1]]
562 ; CHECK-NEXT: ret i32 -3
568 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
569 %zero_check = icmp ne i32 %iv, 0
570 %iv.minus.1 = add i32 %iv, -1
571 %range_check = icmp ult i32 %iv.minus.1, %len
572 %both_checks = and i1 %zero_check, %range_check
573 br i1 %both_checks, label %backedge, label %failed
576 %iv.next = add i32 %iv, -1
577 %loop_cond = call i1 @cond()
578 br i1 %loop_cond, label %done, label %loop
587 ; Same as test_and_conditions, but swapped exit block branches,
588 ; and condition is expressed as OR. Still optimizable.
589 define i32 @test_and_conditions_inverse(i32 %start, i32 %len) {
590 ; CHECK-LABEL: @test_and_conditions_inverse(
592 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
593 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
594 ; CHECK-NEXT: br label [[LOOP:%.*]]
596 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
597 ; CHECK-NEXT: [[ZERO_CHECK_FAILED:%.*]] = icmp eq i32 [[IV]], 0
598 ; CHECK-NEXT: [[EITHER_CHECK:%.*]] = or i1 [[ZERO_CHECK_FAILED]], [[RANGE_CHECK_FAILED_FIRST_ITER]]
599 ; CHECK-NEXT: br i1 [[EITHER_CHECK]], label [[FAILED:%.*]], label [[BACKEDGE]]
601 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
602 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
603 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
605 ; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
606 ; CHECK-NEXT: ret i32 [[IV_LCSSA1]]
608 ; CHECK-NEXT: ret i32 -3
614 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
615 %zero_check_failed = icmp eq i32 %iv, 0
616 %iv.minus.1 = add i32 %iv, -1
617 %range_check_failed = icmp uge i32 %iv.minus.1, %len
618 %either_check = or i1 %zero_check_failed, %range_check_failed
619 br i1 %either_check, label %failed, label %backedge
622 %iv.next = add i32 %iv, -1
623 %loop_cond = call i1 @cond()
624 br i1 %loop_cond, label %done, label %loop
633 ; Same as test_litter_conditions, but with logical AND.
634 define i32 @test_litter_conditions_logical_and(i32 %start, i32 %len) {
635 ; CHECK-LABEL: @test_litter_conditions_logical_and(
637 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
638 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
639 ; CHECK-NEXT: br label [[LOOP:%.*]]
641 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
642 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
643 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
644 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
645 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
646 ; CHECK: range_check_block:
647 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
648 ; CHECK-NEXT: [[AND_2:%.*]] = select i1 [[RANGE_CHECK_FIRST_ITER]], i1 [[FAKE_2]], i1 false
649 ; CHECK-NEXT: br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
651 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
652 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
653 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
655 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
656 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
658 ; CHECK-NEXT: ret i32 -1
660 ; CHECK-NEXT: ret i32 -2
666 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
667 %zero_check = icmp ne i32 %iv, 0
668 %fake_1 = call i1 @cond()
669 %and_1 = and i1 %zero_check, %fake_1
670 br i1 %and_1, label %range_check_block, label %failed_1
673 %iv.minus.1 = add i32 %iv, -1
674 %range_check = icmp ult i32 %iv.minus.1, %len
675 %fake_2 = call i1 @cond()
676 %and_2 = select i1 %range_check, i1 %fake_2, i1 false
677 br i1 %and_2, label %backedge, label %failed_2
680 %iv.next = add i32 %iv, -1
681 %loop_cond = call i1 @cond()
682 br i1 %loop_cond, label %done, label %loop
694 ; Same as test_litter_conditions_inverse, but with logical OR.
695 define i32 @test_litter_conditions_inverse_logical_or(i32 %start, i32 %len) {
696 ; CHECK-LABEL: @test_litter_conditions_inverse_logical_or(
698 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
699 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
700 ; CHECK-NEXT: br label [[LOOP:%.*]]
702 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
703 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
704 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
705 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
706 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
707 ; CHECK: range_check_block:
708 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
709 ; CHECK-NEXT: [[OR_2:%.*]] = select i1 [[RANGE_CHECK_FAILED_FIRST_ITER]], i1 true, i1 [[FAKE_2]]
710 ; CHECK-NEXT: br i1 [[OR_2]], label [[FAILED_2:%.*]], label [[BACKEDGE]]
712 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
713 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
714 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
716 ; CHECK-NEXT: [[IV_LCSSA2:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
717 ; CHECK-NEXT: ret i32 [[IV_LCSSA2]]
719 ; CHECK-NEXT: ret i32 -1
721 ; CHECK-NEXT: ret i32 -2
727 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
728 %zero_check = icmp ne i32 %iv, 0
729 %fake_1 = call i1 @cond()
730 %and_1 = and i1 %zero_check, %fake_1
731 br i1 %and_1, label %range_check_block, label %failed_1
734 %iv.minus.1 = add i32 %iv, -1
735 %range_check_failed = icmp uge i32 %iv.minus.1, %len
736 %fake_2 = call i1 @cond()
737 %or_2 = select i1 %range_check_failed, i1 true, i1 %fake_2
738 br i1 %or_2, label %failed_2, label %backedge
741 %iv.next = add i32 %iv, -1
742 %loop_cond = call i1 @cond()
743 br i1 %loop_cond, label %done, label %loop
755 ; Same as test_and_conditions, but with logical AND.
756 define i32 @test_and_conditions_logical_and(i32 %start, i32 %len) {
757 ; CHECK-LABEL: @test_and_conditions_logical_and(
759 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
760 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
761 ; CHECK-NEXT: br label [[LOOP:%.*]]
763 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
764 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
765 ; CHECK-NEXT: [[BOTH_CHECKS:%.*]] = select i1 [[ZERO_CHECK]], i1 [[RANGE_CHECK_FIRST_ITER]], i1 false
766 ; CHECK-NEXT: br i1 [[BOTH_CHECKS]], label [[BACKEDGE]], label [[FAILED:%.*]]
768 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
769 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
770 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
772 ; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
773 ; CHECK-NEXT: ret i32 [[IV_LCSSA1]]
775 ; CHECK-NEXT: ret i32 -3
781 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
782 %zero_check = icmp ne i32 %iv, 0
783 %iv.minus.1 = add i32 %iv, -1
784 %range_check = icmp ult i32 %iv.minus.1, %len
785 %both_checks = select i1 %zero_check, i1 %range_check, i1 false
786 br i1 %both_checks, label %backedge, label %failed
789 %iv.next = add i32 %iv, -1
790 %loop_cond = call i1 @cond()
791 br i1 %loop_cond, label %done, label %loop
800 ; Same as test_and_conditions_inverse, but with logical OR.
801 define i32 @test_and_conditions_inverse_logical_or(i32 %start, i32 %len) {
802 ; CHECK-LABEL: @test_and_conditions_inverse_logical_or(
804 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
805 ; CHECK-NEXT: [[RANGE_CHECK_FAILED_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN:%.*]]
806 ; CHECK-NEXT: br label [[LOOP:%.*]]
808 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
809 ; CHECK-NEXT: [[ZERO_CHECK_FAILED:%.*]] = icmp eq i32 [[IV]], 0
810 ; CHECK-NEXT: [[EITHER_CHECK:%.*]] = select i1 [[ZERO_CHECK_FAILED]], i1 true, i1 [[RANGE_CHECK_FAILED_FIRST_ITER]]
811 ; CHECK-NEXT: br i1 [[EITHER_CHECK]], label [[FAILED:%.*]], label [[BACKEDGE]]
813 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
814 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
815 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
817 ; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
818 ; CHECK-NEXT: ret i32 [[IV_LCSSA1]]
820 ; CHECK-NEXT: ret i32 -3
826 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
827 %zero_check_failed = icmp eq i32 %iv, 0
828 %iv.minus.1 = add i32 %iv, -1
829 %range_check_failed = icmp uge i32 %iv.minus.1, %len
830 %either_check = select i1 %zero_check_failed, i1 true, i1 %range_check_failed
831 br i1 %either_check, label %failed, label %backedge
834 %iv.next = add i32 %iv, -1
835 %loop_cond = call i1 @cond()
836 br i1 %loop_cond, label %done, label %loop
845 ; Same as test_litter_conditions, but an extra check with known exact exit count is preventing the opt.
846 define i32 @test_litter_conditions_constant(i32 %start, i32 %len) {
847 ; CHECK-LABEL: @test_litter_conditions_constant(
849 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1
850 ; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
851 ; CHECK-NEXT: br label [[LOOP:%.*]]
853 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
854 ; CHECK-NEXT: [[CANONICAL_IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[CANONICAL_IV_NEXT:%.*]], [[BACKEDGE]] ]
855 ; CHECK-NEXT: [[CONSTANT_CHECK:%.*]] = icmp ult i32 [[CANONICAL_IV]], 65635
856 ; CHECK-NEXT: br i1 [[CONSTANT_CHECK]], label [[CONSTANT_CHECK_PASSED:%.*]], label [[CONSTANT_CHECK_FAILED:%.*]]
857 ; CHECK: constant_check_passed:
858 ; CHECK-NEXT: [[ZERO_CHECK:%.*]] = icmp ne i32 [[IV]], 0
859 ; CHECK-NEXT: [[FAKE_1:%.*]] = call i1 @cond()
860 ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
861 ; CHECK-NEXT: br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
862 ; CHECK: range_check_block:
863 ; CHECK-NEXT: [[FAKE_2:%.*]] = call i1 @cond()
864 ; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[RANGE_CHECK_FIRST_ITER]], [[FAKE_2]]
865 ; CHECK-NEXT: br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
867 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
868 ; CHECK-NEXT: [[CANONICAL_IV_NEXT]] = add nuw nsw i32 [[CANONICAL_IV]], 1
869 ; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond()
870 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[DONE:%.*]], label [[LOOP]]
872 ; CHECK-NEXT: [[IV_LCSSA3:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
873 ; CHECK-NEXT: ret i32 [[IV_LCSSA3]]
875 ; CHECK-NEXT: ret i32 -1
877 ; CHECK-NEXT: ret i32 -2
878 ; CHECK: constant_check_failed:
879 ; CHECK-NEXT: ret i32 -3
885 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
886 %canonical_iv = phi i32 [0, %entry], [%canonical_iv.next, %backedge]
887 %constant_check = icmp ult i32 %canonical_iv, 65635
888 br i1 %constant_check, label %constant_check_passed, label %constant_check_failed
890 constant_check_passed:
891 %zero_check = icmp ne i32 %iv, 0
892 %fake_1 = call i1 @cond()
893 %and_1 = and i1 %zero_check, %fake_1
894 br i1 %and_1, label %range_check_block, label %failed_1
897 %iv.minus.1 = add i32 %iv, -1
898 %range_check = icmp ult i32 %iv.minus.1, %len
899 %fake_2 = call i1 @cond()
900 %and_2 = and i1 %range_check, %fake_2
901 br i1 %and_2, label %backedge, label %failed_2
904 %iv.next = add i32 %iv, -1
905 %canonical_iv.next = add i32 %canonical_iv, 1
906 %loop_cond = call i1 @cond()
907 br i1 %loop_cond, label %done, label %loop
918 constant_check_failed:
922 ; TODO: the backedge is predicated by iv.next <u len. It means that starting the
923 ; 2nd iteration, iv <u len is a known fact. We can replace %check with
924 ; %check.first.iter = icmp ult i32 0, %len.
925 define i32 @test_predicated_backedge_no_side_exit(i32 %len) {
926 ; CHECK-LABEL: @test_predicated_backedge_no_side_exit(
928 ; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN:%.*]], i32 1)
929 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
930 ; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LEN]], i32 [[TMP0]])
931 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[LEN]], [[UMIN]]
932 ; CHECK-NEXT: br label [[LOOP:%.*]]
934 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
935 ; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
936 ; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[FAILED:%.*]]
938 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]]
939 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
941 ; CHECK-NEXT: [[IV_NEXT_LCSSA1:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
942 ; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA1]]
944 ; CHECK-NEXT: ret i32 -1
950 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
951 %iv.next = add i32 %iv, 1
952 %check = icmp ult i32 %iv, %len
953 br i1 %check, label %backedge, label %failed
956 %loop.cond = icmp ult i32 %iv.next, %len
957 br i1 %loop.cond, label %loop, label %exit
966 ; TODO: the backedge is predicated by iv.next <u len. It means that starting the
967 ; 2nd iteration, iv <u len is a known fact. We can replace %check with
968 ; %check.first.iter = icmp ult i32 0, %len.
969 define i32 @test_predicated_backedge_with_side_exit(i32 %len) {
970 ; CHECK-LABEL: @test_predicated_backedge_with_side_exit(
972 ; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN:%.*]], i32 1)
973 ; CHECK-NEXT: br label [[LOOP:%.*]]
975 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
976 ; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
977 ; CHECK-NEXT: [[CHECK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
978 ; CHECK-NEXT: br i1 [[CHECK]], label [[INNER_BLOCK:%.*]], label [[FAILED:%.*]]
979 ; CHECK: inner_block:
980 ; CHECK-NEXT: [[COND_1:%.*]] = call i1 @cond()
981 ; CHECK-NEXT: br i1 [[COND_1]], label [[BACKEDGE]], label [[FAILED]]
983 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]]
984 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
986 ; CHECK-NEXT: ret i32 [[UMAX]]
988 ; CHECK-NEXT: ret i32 -1
994 %iv = phi i32 [0, %entry], [%iv.next, %backedge]
995 %iv.next = add i32 %iv, 1
996 %check = icmp ult i32 %iv, %len
997 br i1 %check, label %inner_block, label %failed
1000 %cond_1 = call i1 @cond()
1001 br i1 %cond_1, label %backedge, label %failed
1004 %loop.cond = icmp ult i32 %iv.next, %len
1005 br i1 %loop.cond, label %loop, label %exit
1014 ; TODO: the backedge is predicated by iv.next <u len. It means that starting the
1015 ; 2nd iteration, iv <u len is a known fact. We can replace %check with
1016 ; %check.first.iter = icmp ult i32 %start, %len.
1017 define i32 @test_predicated_backedge_with_side_exit_unknown_start(i32 %start, i32 %len) {
1018 ; CHECK-LABEL: @test_predicated_backedge_with_side_exit_unknown_start(
1019 ; CHECK-NEXT: entry:
1020 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], 1
1021 ; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN:%.*]], i32 [[TMP0]])
1022 ; CHECK-NEXT: br label [[LOOP:%.*]]
1024 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
1025 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
1026 ; CHECK-NEXT: [[CHECK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
1027 ; CHECK-NEXT: br i1 [[CHECK]], label [[INNER_BLOCK:%.*]], label [[FAILED:%.*]]
1028 ; CHECK: inner_block:
1029 ; CHECK-NEXT: [[COND_1:%.*]] = call i1 @cond()
1030 ; CHECK-NEXT: br i1 [[COND_1]], label [[BACKEDGE]], label [[FAILED]]
1032 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LEN]]
1033 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1035 ; CHECK-NEXT: ret i32 [[UMAX]]
1037 ; CHECK-NEXT: ret i32 -1
1043 %iv = phi i32 [%start, %entry], [%iv.next, %backedge]
1044 %iv.next = add i32 %iv, 1
1045 %check = icmp ult i32 %iv, %len
1046 br i1 %check, label %inner_block, label %failed
1049 %cond_1 = call i1 @cond()
1050 br i1 %cond_1, label %backedge, label %failed
1053 %loop.cond = icmp ult i32 %iv.next, %len
1054 br i1 %loop.cond, label %loop, label %exit