[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / lftr-multi-exit.ll
blob0898c6c2dae34235e17a2eb4a1f1b6c1d2e8a82c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=indvars -S | FileCheck %s
3 ; This is a collection of tests specifically for LFTR of multiple exit loops.
4 ; The actual LFTR performed is trivial so as to focus on the loop structure
5 ; aspects.
7 ; Provide legal integer types.
8 target datalayout = "n8:16:32:64"
10 @A = external global i32
12 define void @analyzeable_early_exit(i32 %n) {
13 ; CHECK-LABEL: @analyzeable_early_exit(
14 ; CHECK-NEXT:  entry:
15 ; CHECK-NEXT:    br label [[LOOP:%.*]]
16 ; CHECK:       loop:
17 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
18 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
19 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
20 ; CHECK:       latch:
21 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
22 ; CHECK-NEXT:    store i32 [[IV]], ptr @A, align 4
23 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
24 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
25 ; CHECK:       exit:
26 ; CHECK-NEXT:    ret void
28 entry:
29   br label %loop
31 loop:
32   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
33   %earlycnd = icmp ult i32 %iv, %n
34   br i1 %earlycnd, label %latch, label %exit
36 latch:
37   %iv.next = add i32 %iv, 1
38   store i32 %iv, ptr @A
39   %c = icmp ult i32 %iv.next, 1000
40   br i1 %c, label %loop, label %exit
42 exit:
43   ret void
46 define void @unanalyzeable_early_exit() {
47 ; CHECK-LABEL: @unanalyzeable_early_exit(
48 ; CHECK-NEXT:  entry:
49 ; CHECK-NEXT:    br label [[LOOP:%.*]]
50 ; CHECK:       loop:
51 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
52 ; CHECK-NEXT:    [[VOL:%.*]] = load volatile i32, ptr @A, align 4
53 ; CHECK-NEXT:    [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
54 ; CHECK-NEXT:    br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
55 ; CHECK:       latch:
56 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
57 ; CHECK-NEXT:    store i32 [[IV]], ptr @A, align 4
58 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
59 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
60 ; CHECK:       exit:
61 ; CHECK-NEXT:    ret void
63 entry:
64   br label %loop
66 loop:
67   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
68   %vol = load volatile i32, ptr @A
69   %earlycnd = icmp ne i32 %vol, 0
70   br i1 %earlycnd, label %latch, label %exit
72 latch:
73   %iv.next = add i32 %iv, 1
74   store i32 %iv, ptr @A
75   %c = icmp ult i32 %iv.next, 1000
76   br i1 %c, label %loop, label %exit
78 exit:
79   ret void
83 define void @multiple_early_exits(i32 %n, i32 %m) {
84 ; CHECK-LABEL: @multiple_early_exits(
85 ; CHECK-NEXT:  entry:
86 ; CHECK-NEXT:    br label [[LOOP:%.*]]
87 ; CHECK:       loop:
88 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
89 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
90 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
91 ; CHECK:       continue:
92 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
93 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
94 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
95 ; CHECK:       latch:
96 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
97 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
98 ; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
99 ; CHECK-NEXT:    br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
100 ; CHECK:       exit:
101 ; CHECK-NEXT:    ret void
103 entry:
104   br label %loop
106 loop:
107   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
108   %earlycnd = icmp ult i32 %iv, %n
109   br i1 %earlycnd, label %continue, label %exit
111 continue:
112   store volatile i32 %iv, ptr @A
113   %earlycnd2 = icmp ult i32 %iv, %m
114   br i1 %earlycnd2, label %latch, label %exit
116 latch:
117   %iv.next = add i32 %iv, 1
118   store volatile i32 %iv, ptr @A
119   %c = icmp ult i32 %iv.next, 1000
120   br i1 %c, label %loop, label %exit
122 exit:
123   ret void
126 ; Note: This slightly odd form is what indvars itself produces for multiple
127 ; exits without a side effect between them.
128 define void @compound_early_exit(i32 %n, i32 %m) {
129 ; CHECK-LABEL: @compound_early_exit(
130 ; CHECK-NEXT:  entry:
131 ; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
132 ; CHECK-NEXT:    br label [[LOOP:%.*]]
133 ; CHECK:       loop:
134 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
135 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[UMIN]]
136 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
137 ; CHECK:       latch:
138 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
139 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
140 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
141 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
142 ; CHECK:       exit:
143 ; CHECK-NEXT:    ret void
145 entry:
146   br label %loop
148 loop:
149   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
150   %earlycnd = icmp ult i32 %iv, %n
151   %earlycnd2 = icmp ult i32 %iv, %m
152   %and = and i1 %earlycnd, %earlycnd2
153   br i1 %and, label %latch, label %exit
155 latch:
156   %iv.next = add i32 %iv, 1
157   store volatile i32 %iv, ptr @A
158   %c = icmp ult i32 %iv.next, 1000
159   br i1 %c, label %loop, label %exit
161 exit:
162   ret void
166 define void @unanalyzeable_latch(i32 %n) {
167 ; CHECK-LABEL: @unanalyzeable_latch(
168 ; CHECK-NEXT:  entry:
169 ; CHECK-NEXT:    br label [[LOOP:%.*]]
170 ; CHECK:       loop:
171 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
172 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
173 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
174 ; CHECK:       latch:
175 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
176 ; CHECK-NEXT:    store i32 [[IV]], ptr @A, align 4
177 ; CHECK-NEXT:    [[VOL:%.*]] = load volatile i32, ptr @A, align 4
178 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[VOL]], 1000
179 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT]]
180 ; CHECK:       exit:
181 ; CHECK-NEXT:    ret void
183 entry:
184   br label %loop
186 loop:
187   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
188   %earlycnd = icmp ult i32 %iv, %n
189   br i1 %earlycnd, label %latch, label %exit
191 latch:
192   %iv.next = add i32 %iv, 1
193   store i32 %iv, ptr @A
194   %vol = load volatile i32, ptr @A
195   %c = icmp ult i32 %vol, 1000
196   br i1 %c, label %loop, label %exit
198 exit:
199   ret void
202 define void @single_exit_no_latch(i32 %n) {
203 ; CHECK-LABEL: @single_exit_no_latch(
204 ; CHECK-NEXT:  entry:
205 ; CHECK-NEXT:    br label [[LOOP:%.*]]
206 ; CHECK:       loop:
207 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
208 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
209 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
210 ; CHECK:       latch:
211 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
212 ; CHECK-NEXT:    store i32 [[IV]], ptr @A, align 4
213 ; CHECK-NEXT:    br label [[LOOP]]
214 ; CHECK:       exit:
215 ; CHECK-NEXT:    ret void
217 entry:
218   br label %loop
220 loop:
221   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
222   %earlycnd = icmp ult i32 %iv, %n
223   br i1 %earlycnd, label %latch, label %exit
225 latch:
226   %iv.next = add i32 %iv, 1
227   store i32 %iv, ptr @A
228   br label %loop
230 exit:
231   ret void
234 ; Multiple exits which could be LFTRed, but the latch itself is not an
235 ; exiting block.
236 define void @no_latch_exit(i32 %n, i32 %m) {
237 ; CHECK-LABEL: @no_latch_exit(
238 ; CHECK-NEXT:  entry:
239 ; CHECK-NEXT:    br label [[LOOP:%.*]]
240 ; CHECK:       loop:
241 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
242 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
243 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
244 ; CHECK:       continue:
245 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
246 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
247 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
248 ; CHECK:       latch:
249 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
250 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
251 ; CHECK-NEXT:    br label [[LOOP]]
252 ; CHECK:       exit:
253 ; CHECK-NEXT:    ret void
255 entry:
256   br label %loop
258 loop:
259   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
260   %earlycnd = icmp ult i32 %iv, %n
261   br i1 %earlycnd, label %continue, label %exit
263 continue:
264   store volatile i32 %iv, ptr @A
265   %earlycnd2 = icmp ult i32 %iv, %m
266   br i1 %earlycnd2, label %latch, label %exit
268 latch:
269   store volatile i32 %iv, ptr @A
270   %iv.next = add i32 %iv, 1
271   br label %loop
273 exit:
274   ret void
277 ;; Show the value of multiple exit LFTR (being able to eliminate all but
278 ;; one IV when exit tests involve multiple IVs).
279 define void @combine_ivs(i32 %n) {
280 ; CHECK-LABEL: @combine_ivs(
281 ; CHECK-NEXT:  entry:
282 ; CHECK-NEXT:    br label [[LOOP:%.*]]
283 ; CHECK:       loop:
284 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
285 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
286 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
287 ; CHECK:       latch:
288 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
289 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
290 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
291 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
292 ; CHECK:       exit:
293 ; CHECK-NEXT:    ret void
295 entry:
296   br label %loop
298 loop:
299   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
300   %iv2 = phi i32 [ 1, %entry], [ %iv2.next, %latch]
301   %earlycnd = icmp ult i32 %iv, %n
302   br i1 %earlycnd, label %latch, label %exit
304 latch:
305   %iv.next = add i32 %iv, 1
306   %iv2.next = add i32 %iv2, 1
307   store volatile i32 %iv, ptr @A
308   %c = icmp ult i32 %iv2.next, 1000
309   br i1 %c, label %loop, label %exit
311 exit:
312   ret void
315 ; We can remove the decrementing IV entirely
316 define void @combine_ivs2(i32 %n) {
317 ; CHECK-LABEL: @combine_ivs2(
318 ; CHECK-NEXT:  entry:
319 ; CHECK-NEXT:    br label [[LOOP:%.*]]
320 ; CHECK:       loop:
321 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
322 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
323 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
324 ; CHECK:       latch:
325 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
326 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
327 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
328 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
329 ; CHECK:       exit:
330 ; CHECK-NEXT:    ret void
332 entry:
333   br label %loop
335 loop:
336   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
337   %iv2 = phi i32 [ 1000, %entry], [ %iv2.next, %latch]
338   %earlycnd = icmp ult i32 %iv, %n
339   br i1 %earlycnd, label %latch, label %exit
341 latch:
342   %iv.next = add i32 %iv, 1
343   %iv2.next = sub i32 %iv2, 1
344   store volatile i32 %iv, ptr @A
345   %c = icmp ugt i32 %iv2.next, 0
346   br i1 %c, label %loop, label %exit
348 exit:
349   ret void
352 ; An example where we can eliminate an f(i) computation entirely
353 ; from a multiple exit loop with LFTR.
354 define void @simplify_exit_test(i32 %n) {
355 ; CHECK-LABEL: @simplify_exit_test(
356 ; CHECK-NEXT:  entry:
357 ; CHECK-NEXT:    br label [[LOOP:%.*]]
358 ; CHECK:       loop:
359 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
360 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
361 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
362 ; CHECK:       latch:
363 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
364 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
365 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
366 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
367 ; CHECK:       exit:
368 ; CHECK-NEXT:    ret void
370 entry:
371   br label %loop
373 loop:
374   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
375   %earlycnd = icmp ult i32 %iv, %n
376   br i1 %earlycnd, label %latch, label %exit
378 latch:
379   %iv.next = add i32 %iv, 1
380   %fx = shl i32 %iv, 4
381   store volatile i32 %iv, ptr @A
382   %c = icmp ult i32 %fx, 1024
383   br i1 %c, label %loop, label %exit
385 exit:
386   ret void
390 ; Another example where we can remove an f(i) type computation, but this
391 ; time in a loop w/o a statically computable exit count.
392 define void @simplify_exit_test2(i32 %n) {
393 ; CHECK-LABEL: @simplify_exit_test2(
394 ; CHECK-NEXT:  entry:
395 ; CHECK-NEXT:    br label [[LOOP:%.*]]
396 ; CHECK:       loop:
397 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
398 ; CHECK-NEXT:    [[VOL:%.*]] = load volatile i32, ptr @A, align 4
399 ; CHECK-NEXT:    [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
400 ; CHECK-NEXT:    br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
401 ; CHECK:       latch:
402 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
403 ; CHECK-NEXT:    [[FX:%.*]] = udiv i32 [[IV]], 4
404 ; CHECK-NEXT:    store volatile i32 [[IV]], ptr @A, align 4
405 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[FX]], 1024
406 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT]]
407 ; CHECK:       exit:
408 ; CHECK-NEXT:    ret void
410 entry:
411   br label %loop
413 loop:
414   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
415   %vol = load volatile i32, ptr @A
416   %earlycnd = icmp ne i32 %vol, 0
417   br i1 %earlycnd, label %latch, label %exit
419 latch:
420   %iv.next = add i32 %iv, 1
421   %fx = udiv i32 %iv, 4
422   store volatile i32 %iv, ptr @A
423   %c = icmp ult i32 %fx, 1024
424   br i1 %c, label %loop, label %exit
426 exit:
427   ret void
430 ; Demonstrate a case where two nested loops share a single exiting block.
431 ; The key point is that the exit count is *different* for the two loops, and
432 ; thus we can't rewrite the exit for the outer one.  There are three sub-cases
433 ; which can happen here: a) the outer loop has a backedge taken count of zero
434 ; (for the case where we know the inner exit is known taken), b) the exit is
435 ; known never taken (but may have an exit count outside the range of the IV)
436 ; or c) the outer loop has an unanalyzable exit count (where we can't tell).
437 define void @nested(i32 %n) {
438 ; CHECK-LABEL: @nested(
439 ; CHECK-NEXT:  entry:
440 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
441 ; CHECK-NEXT:    br label [[OUTER:%.*]]
442 ; CHECK:       outer:
443 ; CHECK-NEXT:    [[IV1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV1_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
444 ; CHECK-NEXT:    store volatile i32 [[IV1]], ptr @A, align 4
445 ; CHECK-NEXT:    [[IV1_NEXT]] = add nuw nsw i32 [[IV1]], 1
446 ; CHECK-NEXT:    br label [[INNER:%.*]]
447 ; CHECK:       inner:
448 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, [[OUTER]] ], [ [[IV2_NEXT:%.*]], [[INNER_LATCH:%.*]] ]
449 ; CHECK-NEXT:    store volatile i32 [[IV2]], ptr @A, align 4
450 ; CHECK-NEXT:    [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
451 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], 20
452 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[INNER_LATCH]], label [[EXIT_LOOPEXIT:%.*]]
453 ; CHECK:       inner_latch:
454 ; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp ne i32 [[IV2_NEXT]], [[TMP0]]
455 ; CHECK-NEXT:    br i1 [[EXITCOND2]], label [[INNER]], label [[OUTER_LATCH]]
456 ; CHECK:       outer_latch:
457 ; CHECK-NEXT:    [[EXITCOND3:%.*]] = icmp ne i32 [[IV1_NEXT]], 21
458 ; CHECK-NEXT:    br i1 [[EXITCOND3]], label [[OUTER]], label [[EXIT_LOOPEXIT1:%.*]]
459 ; CHECK:       exit.loopexit:
460 ; CHECK-NEXT:    br label [[EXIT:%.*]]
461 ; CHECK:       exit.loopexit1:
462 ; CHECK-NEXT:    br label [[EXIT]]
463 ; CHECK:       exit:
464 ; CHECK-NEXT:    ret void
466 entry:
467   br label %outer
469 outer:
470   %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer_latch ]
471   store volatile i32 %iv1, ptr @A
472   %iv1.next = add i32 %iv1, 1
473   br label %inner
475 inner:
476   %iv2 = phi i32 [ 0, %outer ], [ %iv2.next, %inner_latch ]
477   store volatile i32 %iv2, ptr @A
478   %iv2.next = add i32 %iv2, 1
479   %innertest = icmp ult i32 %iv2, 20
480   br i1 %innertest, label %inner_latch, label %exit
482 inner_latch:
483   %innertestb = icmp ult i32 %iv2, %n
484   br i1 %innertestb, label %inner, label %outer_latch
486 outer_latch:
487   %outertest = icmp ult i32 %iv1, 20
488   br i1 %outertest, label %outer, label %exit
490 exit:
491   ret void