[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / IndVarSimplify / lftr-multi-exit.ll
blob9b720b0758fdb97fee9705078a80e46d2ca76fa8
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -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]], i32* @A
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, i32* @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, i32* @A
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]], i32* @A
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, i32* @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, i32* @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]], i32* @A
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]], i32* @A
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, i32* @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, i32* @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:    br label [[LOOP:%.*]]
132 ; CHECK:       loop:
133 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
134 ; CHECK-NEXT:    [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
135 ; CHECK-NEXT:    [[EARLYCND2:%.*]] = icmp ult i32 [[IV]], [[M:%.*]]
136 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[EARLYCND]], [[EARLYCND2]]
137 ; CHECK-NEXT:    br i1 [[AND]], label [[LATCH]], label [[EXIT:%.*]]
138 ; CHECK:       latch:
139 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
140 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
141 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
142 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
143 ; CHECK:       exit:
144 ; CHECK-NEXT:    ret void
146 entry:
147   br label %loop
149 loop:
150   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
151   %earlycnd = icmp ult i32 %iv, %n
152   %earlycnd2 = icmp ult i32 %iv, %m
153   %and = and i1 %earlycnd, %earlycnd2
154   br i1 %and, label %latch, label %exit
156 latch:
157   %iv.next = add i32 %iv, 1
158   store volatile i32 %iv, i32* @A
159   %c = icmp ult i32 %iv.next, 1000
160   br i1 %c, label %loop, label %exit
162 exit:
163   ret void
167 define void @unanalyzeable_latch(i32 %n) {
168 ; CHECK-LABEL: @unanalyzeable_latch(
169 ; CHECK-NEXT:  entry:
170 ; CHECK-NEXT:    br label [[LOOP:%.*]]
171 ; CHECK:       loop:
172 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
173 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
174 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
175 ; CHECK:       latch:
176 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
177 ; CHECK-NEXT:    store i32 [[IV]], i32* @A
178 ; CHECK-NEXT:    [[VOL:%.*]] = load volatile i32, i32* @A
179 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[VOL]], 1000
180 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT]]
181 ; CHECK:       exit:
182 ; CHECK-NEXT:    ret void
184 entry:
185   br label %loop
187 loop:
188   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
189   %earlycnd = icmp ult i32 %iv, %n
190   br i1 %earlycnd, label %latch, label %exit
192 latch:
193   %iv.next = add i32 %iv, 1
194   store i32 %iv, i32* @A
195   %vol = load volatile i32, i32* @A
196   %c = icmp ult i32 %vol, 1000
197   br i1 %c, label %loop, label %exit
199 exit:
200   ret void
203 define void @single_exit_no_latch(i32 %n) {
204 ; CHECK-LABEL: @single_exit_no_latch(
205 ; CHECK-NEXT:  entry:
206 ; CHECK-NEXT:    br label [[LOOP:%.*]]
207 ; CHECK:       loop:
208 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
209 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
210 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
211 ; CHECK:       latch:
212 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
213 ; CHECK-NEXT:    store i32 [[IV]], i32* @A
214 ; CHECK-NEXT:    br label [[LOOP]]
215 ; CHECK:       exit:
216 ; CHECK-NEXT:    ret void
218 entry:
219   br label %loop
221 loop:
222   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
223   %earlycnd = icmp ult i32 %iv, %n
224   br i1 %earlycnd, label %latch, label %exit
226 latch:
227   %iv.next = add i32 %iv, 1
228   store i32 %iv, i32* @A
229   br label %loop
231 exit:
232   ret void
235 ; Multiple exits which could be LFTRed, but the latch itself is not an
236 ; exiting block.
237 define void @no_latch_exit(i32 %n, i32 %m) {
238 ; CHECK-LABEL: @no_latch_exit(
239 ; CHECK-NEXT:  entry:
240 ; CHECK-NEXT:    br label [[LOOP:%.*]]
241 ; CHECK:       loop:
242 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
243 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
244 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
245 ; CHECK:       continue:
246 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
247 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
248 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
249 ; CHECK:       latch:
250 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
251 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
252 ; CHECK-NEXT:    br label [[LOOP]]
253 ; CHECK:       exit:
254 ; CHECK-NEXT:    ret void
256 entry:
257   br label %loop
259 loop:
260   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
261   %earlycnd = icmp ult i32 %iv, %n
262   br i1 %earlycnd, label %continue, label %exit
264 continue:
265   store volatile i32 %iv, i32* @A
266   %earlycnd2 = icmp ult i32 %iv, %m
267   br i1 %earlycnd2, label %latch, label %exit
269 latch:
270   store volatile i32 %iv, i32* @A
271   %iv.next = add i32 %iv, 1
272   br label %loop
274 exit:
275   ret void
278 ;; Show the value of multiple exit LFTR (being able to eliminate all but
279 ;; one IV when exit tests involve multiple IVs).
280 define void @combine_ivs(i32 %n) {
281 ; CHECK-LABEL: @combine_ivs(
282 ; CHECK-NEXT:  entry:
283 ; CHECK-NEXT:    br label [[LOOP:%.*]]
284 ; CHECK:       loop:
285 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
286 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
287 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
288 ; CHECK:       latch:
289 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
290 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
291 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
292 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
293 ; CHECK:       exit:
294 ; CHECK-NEXT:    ret void
296 entry:
297   br label %loop
299 loop:
300   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
301   %iv2 = phi i32 [ 1, %entry], [ %iv2.next, %latch]
302   %earlycnd = icmp ult i32 %iv, %n
303   br i1 %earlycnd, label %latch, label %exit
305 latch:
306   %iv.next = add i32 %iv, 1
307   %iv2.next = add i32 %iv2, 1
308   store volatile i32 %iv, i32* @A
309   %c = icmp ult i32 %iv2.next, 1000
310   br i1 %c, label %loop, label %exit
312 exit:
313   ret void
316 ; We can remove the decrementing IV entirely
317 define void @combine_ivs2(i32 %n) {
318 ; CHECK-LABEL: @combine_ivs2(
319 ; CHECK-NEXT:  entry:
320 ; CHECK-NEXT:    br label [[LOOP:%.*]]
321 ; CHECK:       loop:
322 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
323 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
324 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
325 ; CHECK:       latch:
326 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
327 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
328 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
329 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
330 ; CHECK:       exit:
331 ; CHECK-NEXT:    ret void
333 entry:
334   br label %loop
336 loop:
337   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
338   %iv2 = phi i32 [ 1000, %entry], [ %iv2.next, %latch]
339   %earlycnd = icmp ult i32 %iv, %n
340   br i1 %earlycnd, label %latch, label %exit
342 latch:
343   %iv.next = add i32 %iv, 1
344   %iv2.next = sub i32 %iv2, 1
345   store volatile i32 %iv, i32* @A
346   %c = icmp ugt i32 %iv2.next, 0
347   br i1 %c, label %loop, label %exit
349 exit:
350   ret void
353 ; An example where we can eliminate an f(i) computation entirely
354 ; from a multiple exit loop with LFTR.
355 define void @simplify_exit_test(i32 %n) {
356 ; CHECK-LABEL: @simplify_exit_test(
357 ; CHECK-NEXT:  entry:
358 ; CHECK-NEXT:    br label [[LOOP:%.*]]
359 ; CHECK:       loop:
360 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
361 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
362 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
363 ; CHECK:       latch:
364 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
365 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
366 ; CHECK-NEXT:    [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
367 ; CHECK-NEXT:    br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
368 ; CHECK:       exit:
369 ; CHECK-NEXT:    ret void
371 entry:
372   br label %loop
374 loop:
375   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
376   %earlycnd = icmp ult i32 %iv, %n
377   br i1 %earlycnd, label %latch, label %exit
379 latch:
380   %iv.next = add i32 %iv, 1
381   %fx = shl i32 %iv, 4
382   store volatile i32 %iv, i32* @A
383   %c = icmp ult i32 %fx, 1024
384   br i1 %c, label %loop, label %exit
386 exit:
387   ret void
391 ; Another example where we can remove an f(i) type computation, but this
392 ; time in a loop w/o a statically computable exit count.
393 define void @simplify_exit_test2(i32 %n) {
394 ; CHECK-LABEL: @simplify_exit_test2(
395 ; CHECK-NEXT:  entry:
396 ; CHECK-NEXT:    br label [[LOOP:%.*]]
397 ; CHECK:       loop:
398 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
399 ; CHECK-NEXT:    [[VOL:%.*]] = load volatile i32, i32* @A
400 ; CHECK-NEXT:    [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
401 ; CHECK-NEXT:    br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
402 ; CHECK:       latch:
403 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
404 ; CHECK-NEXT:    [[FX:%.*]] = udiv i32 [[IV]], 4
405 ; CHECK-NEXT:    store volatile i32 [[IV]], i32* @A
406 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[FX]], 1024
407 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT]]
408 ; CHECK:       exit:
409 ; CHECK-NEXT:    ret void
411 entry:
412   br label %loop
414 loop:
415   %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
416   %vol = load volatile i32, i32* @A
417   %earlycnd = icmp ne i32 %vol, 0
418   br i1 %earlycnd, label %latch, label %exit
420 latch:
421   %iv.next = add i32 %iv, 1
422   %fx = udiv i32 %iv, 4
423   store volatile i32 %iv, i32* @A
424   %c = icmp ult i32 %fx, 1024
425   br i1 %c, label %loop, label %exit
427 exit:
428   ret void
431 ; Demonstrate a case where two nested loops share a single exiting block.
432 ; The key point is that the exit count is *different* for the two loops, and
433 ; thus we can't rewrite the exit for the outer one.  There are three sub-cases
434 ; which can happen here: a) the outer loop has a backedge taken count of zero
435 ; (for the case where we know the inner exit is known taken), b) the exit is
436 ; known never taken (but may have an exit count outside the range of the IV)
437 ; or c) the outer loop has an unanalyzable exit count (where we can't tell).
438 define void @nested(i32 %n) {
439 ; CHECK-LABEL: @nested(
440 ; CHECK-NEXT:  entry:
441 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1
442 ; CHECK-NEXT:    br label [[OUTER:%.*]]
443 ; CHECK:       outer:
444 ; CHECK-NEXT:    [[IV1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV1_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
445 ; CHECK-NEXT:    store volatile i32 [[IV1]], i32* @A
446 ; CHECK-NEXT:    [[IV1_NEXT]] = add nuw nsw i32 [[IV1]], 1
447 ; CHECK-NEXT:    br label [[INNER:%.*]]
448 ; CHECK:       inner:
449 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, [[OUTER]] ], [ [[IV2_NEXT:%.*]], [[INNER_LATCH:%.*]] ]
450 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* @A
451 ; CHECK-NEXT:    [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
452 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], 20
453 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[INNER_LATCH]], label [[EXIT_LOOPEXIT:%.*]]
454 ; CHECK:       inner_latch:
455 ; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp ne i32 [[IV2_NEXT]], [[TMP0]]
456 ; CHECK-NEXT:    br i1 [[EXITCOND2]], label [[INNER]], label [[OUTER_LATCH]]
457 ; CHECK:       outer_latch:
458 ; CHECK-NEXT:    [[EXITCOND3:%.*]] = icmp ne i32 [[IV1_NEXT]], 21
459 ; CHECK-NEXT:    br i1 [[EXITCOND3]], label [[OUTER]], label [[EXIT_LOOPEXIT1:%.*]]
460 ; CHECK:       exit.loopexit:
461 ; CHECK-NEXT:    br label [[EXIT:%.*]]
462 ; CHECK:       exit.loopexit1:
463 ; CHECK-NEXT:    br label [[EXIT]]
464 ; CHECK:       exit:
465 ; CHECK-NEXT:    ret void
467 entry:
468   br label %outer
470 outer:
471   %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer_latch ]
472   store volatile i32 %iv1, i32* @A
473   %iv1.next = add i32 %iv1, 1
474   br label %inner
476 inner:
477   %iv2 = phi i32 [ 0, %outer ], [ %iv2.next, %inner_latch ]
478   store volatile i32 %iv2, i32* @A
479   %iv2.next = add i32 %iv2, 1
480   %innertest = icmp ult i32 %iv2, 20
481   br i1 %innertest, label %inner_latch, label %exit
483 inner_latch:
484   %innertestb = icmp ult i32 %iv2, %n
485   br i1 %innertestb, label %inner, label %outer_latch
487 outer_latch:
488   %outertest = icmp ult i32 %iv1, 20
489   br i1 %outertest, label %outer, label %exit
491 exit:
492   ret void