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, align 4
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, align 4
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, align 4
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, align 4
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, align 4
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: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[M:%.*]], i32 [[N:%.*]])
132 ; CHECK-NEXT: br label [[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:%.*]]
138 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
139 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
140 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
141 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
143 ; CHECK-NEXT: ret void
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
156 %iv.next = add i32 %iv, 1
157 store volatile i32 %iv, i32* @A
158 %c = icmp ult i32 %iv.next, 1000
159 br i1 %c, label %loop, label %exit
166 define void @unanalyzeable_latch(i32 %n) {
167 ; CHECK-LABEL: @unanalyzeable_latch(
169 ; CHECK-NEXT: br label [[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:%.*]]
175 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
176 ; CHECK-NEXT: store i32 [[IV]], i32* @A, align 4
177 ; CHECK-NEXT: [[VOL:%.*]] = load volatile i32, i32* @A, align 4
178 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[VOL]], 1000
179 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
181 ; CHECK-NEXT: ret void
187 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
188 %earlycnd = icmp ult i32 %iv, %n
189 br i1 %earlycnd, label %latch, label %exit
192 %iv.next = add i32 %iv, 1
193 store i32 %iv, i32* @A
194 %vol = load volatile i32, i32* @A
195 %c = icmp ult i32 %vol, 1000
196 br i1 %c, label %loop, label %exit
202 define void @single_exit_no_latch(i32 %n) {
203 ; CHECK-LABEL: @single_exit_no_latch(
205 ; CHECK-NEXT: br label [[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:%.*]]
211 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
212 ; CHECK-NEXT: store i32 [[IV]], i32* @A, align 4
213 ; CHECK-NEXT: br label [[LOOP]]
215 ; CHECK-NEXT: ret void
221 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
222 %earlycnd = icmp ult i32 %iv, %n
223 br i1 %earlycnd, label %latch, label %exit
226 %iv.next = add i32 %iv, 1
227 store i32 %iv, i32* @A
234 ; Multiple exits which could be LFTRed, but the latch itself is not an
236 define void @no_latch_exit(i32 %n, i32 %m) {
237 ; CHECK-LABEL: @no_latch_exit(
239 ; CHECK-NEXT: br label [[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:%.*]]
245 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
246 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
247 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
249 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
250 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
251 ; CHECK-NEXT: br label [[LOOP]]
253 ; CHECK-NEXT: ret void
259 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
260 %earlycnd = icmp ult i32 %iv, %n
261 br i1 %earlycnd, label %continue, label %exit
264 store volatile i32 %iv, i32* @A
265 %earlycnd2 = icmp ult i32 %iv, %m
266 br i1 %earlycnd2, label %latch, label %exit
269 store volatile i32 %iv, i32* @A
270 %iv.next = add i32 %iv, 1
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(
282 ; CHECK-NEXT: br label [[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:%.*]]
288 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
289 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
290 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
291 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
293 ; CHECK-NEXT: ret void
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
305 %iv.next = add i32 %iv, 1
306 %iv2.next = add i32 %iv2, 1
307 store volatile i32 %iv, i32* @A
308 %c = icmp ult i32 %iv2.next, 1000
309 br i1 %c, label %loop, label %exit
315 ; We can remove the decrementing IV entirely
316 define void @combine_ivs2(i32 %n) {
317 ; CHECK-LABEL: @combine_ivs2(
319 ; CHECK-NEXT: br label [[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:%.*]]
325 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
326 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
327 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
328 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
330 ; CHECK-NEXT: ret void
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
342 %iv.next = add i32 %iv, 1
343 %iv2.next = sub i32 %iv2, 1
344 store volatile i32 %iv, i32* @A
345 %c = icmp ugt i32 %iv2.next, 0
346 br i1 %c, label %loop, label %exit
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(
357 ; CHECK-NEXT: br label [[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:%.*]]
363 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
364 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
365 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
366 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
368 ; CHECK-NEXT: ret void
374 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
375 %earlycnd = icmp ult i32 %iv, %n
376 br i1 %earlycnd, label %latch, label %exit
379 %iv.next = add i32 %iv, 1
381 store volatile i32 %iv, i32* @A
382 %c = icmp ult i32 %fx, 1024
383 br i1 %c, label %loop, label %exit
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(
395 ; CHECK-NEXT: br label [[LOOP:%.*]]
397 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
398 ; CHECK-NEXT: [[VOL:%.*]] = load volatile i32, i32* @A, align 4
399 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ne i32 [[VOL]], 0
400 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
402 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
403 ; CHECK-NEXT: [[FX:%.*]] = udiv i32 [[IV]], 4
404 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A, align 4
405 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[FX]], 1024
406 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
408 ; CHECK-NEXT: ret void
414 %iv = phi i32 [ 0, %entry], [ %iv.next, %latch]
415 %vol = load volatile i32, i32* @A
416 %earlycnd = icmp ne i32 %vol, 0
417 br i1 %earlycnd, label %latch, label %exit
420 %iv.next = add i32 %iv, 1
421 %fx = udiv i32 %iv, 4
422 store volatile i32 %iv, i32* @A
423 %c = icmp ult i32 %fx, 1024
424 br i1 %c, label %loop, label %exit
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(
440 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1
441 ; CHECK-NEXT: br label [[OUTER:%.*]]
443 ; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV1_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
444 ; CHECK-NEXT: store volatile i32 [[IV1]], i32* @A, align 4
445 ; CHECK-NEXT: [[IV1_NEXT]] = add nuw nsw i32 [[IV1]], 1
446 ; CHECK-NEXT: br label [[INNER:%.*]]
448 ; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 0, [[OUTER]] ], [ [[IV2_NEXT:%.*]], [[INNER_LATCH:%.*]] ]
449 ; CHECK-NEXT: store volatile i32 [[IV2]], i32* @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]]
464 ; CHECK-NEXT: ret void
470 %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer_latch ]
471 store volatile i32 %iv1, i32* @A
472 %iv1.next = add i32 %iv1, 1
476 %iv2 = phi i32 [ 0, %outer ], [ %iv2.next, %inner_latch ]
477 store volatile i32 %iv2, i32* @A
478 %iv2.next = add i32 %iv2, 1
479 %innertest = icmp ult i32 %iv2, 20
480 br i1 %innertest, label %inner_latch, label %exit
483 %innertestb = icmp ult i32 %iv2, %n
484 br i1 %innertestb, label %inner, label %outer_latch
487 %outertest = icmp ult i32 %iv1, 20
488 br i1 %outertest, label %outer, label %exit