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
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(
15 ; CHECK-NEXT: br label [[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:%.*]]
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]]
26 ; CHECK-NEXT: ret void
32 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
33 %earlycnd = icmp ult i32 %iv, %n
34 br i1 %earlycnd, label %latch, label %exit
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
46 define void @unanalyzeable_early_exit() {
47 ; CHECK-LABEL: @unanalyzeable_early_exit(
49 ; CHECK-NEXT: br label [[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:%.*]]
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]]
61 ; CHECK-NEXT: ret void
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
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
83 define void @multiple_early_exits(i32 %n, i32 %m) {
84 ; CHECK-LABEL: @multiple_early_exits(
86 ; CHECK-NEXT: br label [[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:%.*]]
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]]
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]]
101 ; CHECK-NEXT: ret void
107 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
108 %earlycnd = icmp ult i32 %iv, %n
109 br i1 %earlycnd, label %continue, label %exit
112 store volatile i32 %iv, i32* @A
113 %earlycnd2 = icmp ult i32 %iv, %m
114 br i1 %earlycnd2, label %latch, label %exit
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
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(
131 ; CHECK-NEXT: br label [[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:%.*]]
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]]
144 ; CHECK-NEXT: ret void
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
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
167 define void @unanalyzeable_latch(i32 %n) {
168 ; CHECK-LABEL: @unanalyzeable_latch(
170 ; CHECK-NEXT: br label [[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:%.*]]
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]]
182 ; CHECK-NEXT: ret void
188 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
189 %earlycnd = icmp ult i32 %iv, %n
190 br i1 %earlycnd, label %latch, label %exit
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
203 define void @single_exit_no_latch(i32 %n) {
204 ; CHECK-LABEL: @single_exit_no_latch(
206 ; CHECK-NEXT: br label [[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:%.*]]
212 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
213 ; CHECK-NEXT: store i32 [[IV]], i32* @A
214 ; CHECK-NEXT: br label [[LOOP]]
216 ; CHECK-NEXT: ret void
222 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
223 %earlycnd = icmp ult i32 %iv, %n
224 br i1 %earlycnd, label %latch, label %exit
227 %iv.next = add i32 %iv, 1
228 store i32 %iv, i32* @A
235 ; Multiple exits which could be LFTRed, but the latch itself is not an
237 define void @no_latch_exit(i32 %n, i32 %m) {
238 ; CHECK-LABEL: @no_latch_exit(
240 ; CHECK-NEXT: br label [[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:%.*]]
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]]
250 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
251 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
252 ; CHECK-NEXT: br label [[LOOP]]
254 ; CHECK-NEXT: ret void
260 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
261 %earlycnd = icmp ult i32 %iv, %n
262 br i1 %earlycnd, label %continue, label %exit
265 store volatile i32 %iv, i32* @A
266 %earlycnd2 = icmp ult i32 %iv, %m
267 br i1 %earlycnd2, label %latch, label %exit
270 store volatile i32 %iv, i32* @A
271 %iv.next = add i32 %iv, 1
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(
283 ; CHECK-NEXT: br label [[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:%.*]]
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]]
294 ; CHECK-NEXT: ret void
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
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
316 ; We can remove the decrementing IV entirely
317 define void @combine_ivs2(i32 %n) {
318 ; CHECK-LABEL: @combine_ivs2(
320 ; CHECK-NEXT: br label [[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:%.*]]
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]]
331 ; CHECK-NEXT: ret void
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
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
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(
358 ; CHECK-NEXT: br label [[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:%.*]]
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]]
369 ; CHECK-NEXT: ret void
375 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
376 %earlycnd = icmp ult i32 %iv, %n
377 br i1 %earlycnd, label %latch, label %exit
380 %iv.next = add i32 %iv, 1
382 store volatile i32 %iv, i32* @A
383 %c = icmp ult i32 %fx, 1024
384 br i1 %c, label %loop, label %exit
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(
396 ; CHECK-NEXT: br label [[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:%.*]]
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]]
409 ; CHECK-NEXT: ret void
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
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
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(
441 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
442 ; CHECK-NEXT: br label [[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:%.*]]
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]]
465 ; CHECK-NEXT: ret void
471 %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer_latch ]
472 store volatile i32 %iv1, i32* @A
473 %iv1.next = add i32 %iv1, 1
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
484 %innertestb = icmp ult i32 %iv2, %n
485 br i1 %innertestb, label %inner, label %outer_latch
488 %outertest = icmp ult i32 %iv1, 20
489 br i1 %outertest, label %outer, label %exit