1 ; Specifically exercise the cost modeling for non-trivial loop unswitching.
3 ; RUN: opt -passes='loop(unswitch<nontrivial>),verify<loops>' -unswitch-threshold=5 -S < %s | FileCheck %s
4 ; RUN: opt -passes='loop-mssa(unswitch<nontrivial>),verify<loops>' -unswitch-threshold=5 -S < %s | FileCheck %s
5 ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s
6 ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s
12 ; First establish enough code size in the duplicated 'loop_begin' block to
13 ; suppress unswitching.
14 define void @test_no_unswitch(i1* %ptr, i1 %cond) {
15 ; CHECK-LABEL: @test_no_unswitch(
19 ; CHECK-NEXT: br label %loop_begin
21 ; We shouldn't have unswitched into any other block either.
22 ; CHECK-NOT: br i1 %cond
29 br i1 %cond, label %loop_a, label %loop_b
31 ; CHECK-NEXT: call void @x()
32 ; CHECK-NEXT: call void @x()
33 ; CHECK-NEXT: call void @x()
34 ; CHECK-NEXT: call void @x()
35 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
46 %v = load i1, i1* %ptr
47 br i1 %v, label %loop_begin, label %loop_exit
53 ; Now check that the smaller formulation of 'loop_begin' does in fact unswitch
54 ; with our low threshold.
55 define void @test_unswitch(i1* %ptr, i1 %cond) {
56 ; CHECK-LABEL: @test_unswitch(
60 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
64 br i1 %cond, label %loop_a, label %loop_b
69 ; The 'loop_a' unswitched loop.
71 ; CHECK: entry.split.us:
72 ; CHECK-NEXT: br label %loop_begin.us
74 ; CHECK: loop_begin.us:
75 ; CHECK-NEXT: call void @x()
76 ; CHECK-NEXT: br label %loop_a.us
79 ; CHECK-NEXT: call void @a()
80 ; CHECK-NEXT: br label %loop_latch.us
82 ; CHECK: loop_latch.us:
83 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
84 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
86 ; CHECK: loop_exit.split.us:
87 ; CHECK-NEXT: br label %loop_exit
92 ; The 'loop_b' unswitched loop.
95 ; CHECK-NEXT: br label %loop_begin
98 ; CHECK-NEXT: call void @x()
99 ; CHECK-NEXT: br label %loop_b
102 ; CHECK-NEXT: call void @b()
103 ; CHECK-NEXT: br label %loop_latch
106 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
107 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
109 ; CHECK: loop_exit.split:
110 ; CHECK-NEXT: br label %loop_exit
113 %v = load i1, i1* %ptr
114 br i1 %v, label %loop_begin, label %loop_exit
119 ; CHECK-NEXT: ret void
122 ; Check that even with large amounts of code on either side of the unswitched
123 ; branch, if that code would be kept in only one of the unswitched clones it
124 ; doesn't contribute to the cost.
125 define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
126 ; CHECK-LABEL: @test_unswitch_non_dup_code(
130 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
134 br i1 %cond, label %loop_a, label %loop_b
142 ; The 'loop_a' unswitched loop.
144 ; CHECK: entry.split.us:
145 ; CHECK-NEXT: br label %loop_begin.us
147 ; CHECK: loop_begin.us:
148 ; CHECK-NEXT: call void @x()
149 ; CHECK-NEXT: br label %loop_a.us
152 ; CHECK-NEXT: call void @a()
153 ; CHECK-NEXT: call void @a()
154 ; CHECK-NEXT: call void @a()
155 ; CHECK-NEXT: call void @a()
156 ; CHECK-NEXT: br label %loop_latch.us
158 ; CHECK: loop_latch.us:
159 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
160 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
162 ; CHECK: loop_exit.split.us:
163 ; CHECK-NEXT: br label %loop_exit
171 ; The 'loop_b' unswitched loop.
173 ; CHECK: entry.split:
174 ; CHECK-NEXT: br label %loop_begin
177 ; CHECK-NEXT: call void @x()
178 ; CHECK-NEXT: br label %loop_b
181 ; CHECK-NEXT: call void @b()
182 ; CHECK-NEXT: call void @b()
183 ; CHECK-NEXT: call void @b()
184 ; CHECK-NEXT: call void @b()
185 ; CHECK-NEXT: br label %loop_latch
188 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
189 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
191 ; CHECK: loop_exit.split:
192 ; CHECK-NEXT: br label %loop_exit
195 %v = load i1, i1* %ptr
196 br i1 %v, label %loop_begin, label %loop_exit
201 ; CHECK-NEXT: ret void
204 ; Much like with non-duplicated code directly in the successor, we also won't
205 ; duplicate even interesting CFGs.
206 define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
207 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
211 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
215 br i1 %cond, label %loop_a, label %loop_b
218 %v1 = load i1, i1* %ptr
219 br i1 %v1, label %loop_a_a, label %loop_a_b
228 ; The 'loop_a' unswitched loop.
230 ; CHECK: entry.split.us:
231 ; CHECK-NEXT: br label %loop_begin.us
233 ; CHECK: loop_begin.us:
234 ; CHECK-NEXT: call void @x()
235 ; CHECK-NEXT: br label %loop_a.us
238 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
239 ; CHECK-NEXT: br i1 %[[V]], label %loop_a_a.us, label %loop_a_b.us
241 ; CHECK: loop_a_b.us:
242 ; CHECK-NEXT: call void @a()
243 ; CHECK-NEXT: br label %loop_latch.us
245 ; CHECK: loop_a_a.us:
246 ; CHECK-NEXT: call void @a()
247 ; CHECK-NEXT: br label %loop_latch.us
249 ; CHECK: loop_latch.us:
250 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
251 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
253 ; CHECK: loop_exit.split.us:
254 ; CHECK-NEXT: br label %loop_exit
257 %v2 = load i1, i1* %ptr
258 br i1 %v2, label %loop_b_a, label %loop_b_b
267 ; The 'loop_b' unswitched loop.
269 ; CHECK: entry.split:
270 ; CHECK-NEXT: br label %loop_begin
273 ; CHECK-NEXT: call void @x()
274 ; CHECK-NEXT: br label %loop_b
277 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
278 ; CHECK-NEXT: br i1 %[[V]], label %loop_b_a, label %loop_b_b
281 ; CHECK-NEXT: call void @b()
282 ; CHECK-NEXT: br label %loop_latch
285 ; CHECK-NEXT: call void @b()
286 ; CHECK-NEXT: br label %loop_latch
289 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
290 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
292 ; CHECK: loop_exit.split:
293 ; CHECK-NEXT: br label %loop_exit
296 %v3 = load i1, i1* %ptr
297 br i1 %v3, label %loop_begin, label %loop_exit
302 ; CHECK-NEXT: ret void
305 ; Check that even if there is *some* non-duplicated code on one side of an
306 ; unswitch, we don't count any other code in the loop that will in fact have to
308 define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
309 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
313 ; CHECK-NEXT: br label %loop_begin
315 ; We shouldn't have unswitched into any other block either.
316 ; CHECK-NOT: br i1 %cond
320 br i1 %cond, label %loop_a, label %loop_b
322 ; CHECK-NEXT: call void @x()
323 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
326 %v1 = load i1, i1* %ptr
327 br i1 %v1, label %loop_a_a, label %loop_a_b
338 %v2 = load i1, i1* %ptr
339 br i1 %v2, label %loop_b_a, label %loop_b_b
352 %v = load i1, i1* %ptr
353 br i1 %v, label %loop_begin, label %loop_exit
359 ; Check that we still unswitch when the exit block contains lots of code, even
360 ; though we do clone the exit block as part of unswitching. This should work
361 ; because we should split the exit block before anything inside it.
362 define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
363 ; CHECK-LABEL: @test_unswitch_large_exit(
367 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
371 br i1 %cond, label %loop_a, label %loop_b
376 ; The 'loop_a' unswitched loop.
378 ; CHECK: entry.split.us:
379 ; CHECK-NEXT: br label %loop_begin.us
381 ; CHECK: loop_begin.us:
382 ; CHECK-NEXT: call void @x()
383 ; CHECK-NEXT: br label %loop_a.us
386 ; CHECK-NEXT: call void @a()
387 ; CHECK-NEXT: br label %loop_latch.us
389 ; CHECK: loop_latch.us:
390 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
391 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
393 ; CHECK: loop_exit.split.us:
394 ; CHECK-NEXT: br label %loop_exit
399 ; The 'loop_b' unswitched loop.
401 ; CHECK: entry.split:
402 ; CHECK-NEXT: br label %loop_begin
405 ; CHECK-NEXT: call void @x()
406 ; CHECK-NEXT: br label %loop_b
409 ; CHECK-NEXT: call void @b()
410 ; CHECK-NEXT: br label %loop_latch
413 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
414 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
416 ; CHECK: loop_exit.split:
417 ; CHECK-NEXT: br label %loop_exit
420 %v = load i1, i1* %ptr
421 br i1 %v, label %loop_begin, label %loop_exit
430 ; CHECK-NEXT: call void @x()
431 ; CHECK-NEXT: call void @x()
432 ; CHECK-NEXT: call void @x()
433 ; CHECK-NEXT: call void @x()
434 ; CHECK-NEXT: ret void
437 ; Check that we handle a dedicated exit edge unswitch which is still
438 ; non-trivial and has lots of code in the exit.
439 define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
440 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
444 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
448 br i1 %cond, label %loop_a, label %loop_b_exit
453 ; The 'loop_a' unswitched loop.
455 ; CHECK: entry.split.us:
456 ; CHECK-NEXT: br label %loop_begin.us
458 ; CHECK: loop_begin.us:
459 ; CHECK-NEXT: call void @x()
460 ; CHECK-NEXT: br label %loop_a.us
463 ; CHECK-NEXT: call void @a()
464 ; CHECK-NEXT: br label %loop_latch.us
466 ; CHECK: loop_latch.us:
467 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
468 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
470 ; CHECK: loop_exit.split.us:
471 ; CHECK-NEXT: br label %loop_exit
479 ; The 'loop_b_exit' unswitched exit path.
481 ; CHECK: entry.split:
482 ; CHECK-NEXT: br label %loop_begin
485 ; CHECK-NEXT: call void @x()
486 ; CHECK-NEXT: br label %loop_b_exit
488 ; CHECK: loop_b_exit:
489 ; CHECK-NEXT: call void @b()
490 ; CHECK-NEXT: call void @b()
491 ; CHECK-NEXT: call void @b()
492 ; CHECK-NEXT: call void @b()
493 ; CHECK-NEXT: ret void
496 %v = load i1, i1* %ptr
497 br i1 %v, label %loop_begin, label %loop_exit
502 ; CHECK-NEXT: ret void