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 -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s
5 ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s
11 ; First establish enough code size in the duplicated 'loop_begin' block to
12 ; suppress unswitching.
13 define void @test_no_unswitch(i1* %ptr, i1 %cond) {
14 ; CHECK-LABEL: @test_no_unswitch(
18 ; CHECK-NEXT: br label %loop_begin
20 ; We shouldn't have unswitched into any other block either.
21 ; CHECK-NOT: br i1 %cond
28 br i1 %cond, label %loop_a, label %loop_b
30 ; CHECK-NEXT: call void @x()
31 ; CHECK-NEXT: call void @x()
32 ; CHECK-NEXT: call void @x()
33 ; CHECK-NEXT: call void @x()
34 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
45 %v = load i1, i1* %ptr
46 br i1 %v, label %loop_begin, label %loop_exit
52 ; Now check that the smaller formulation of 'loop_begin' does in fact unswitch
53 ; with our low threshold.
54 define void @test_unswitch(i1* %ptr, i1 %cond) {
55 ; CHECK-LABEL: @test_unswitch(
59 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
63 br i1 %cond, label %loop_a, label %loop_b
68 ; The 'loop_a' unswitched loop.
70 ; CHECK: entry.split.us:
71 ; CHECK-NEXT: br label %loop_begin.us
73 ; CHECK: loop_begin.us:
74 ; CHECK-NEXT: call void @x()
75 ; CHECK-NEXT: br label %loop_a.us
78 ; CHECK-NEXT: call void @a()
79 ; CHECK-NEXT: br label %loop_latch.us
81 ; CHECK: loop_latch.us:
82 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
83 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
85 ; CHECK: loop_exit.split.us:
86 ; CHECK-NEXT: br label %loop_exit
91 ; The 'loop_b' unswitched loop.
94 ; CHECK-NEXT: br label %loop_begin
97 ; CHECK-NEXT: call void @x()
98 ; CHECK-NEXT: br label %loop_b
101 ; CHECK-NEXT: call void @b()
102 ; CHECK-NEXT: br label %loop_latch
105 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
106 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
108 ; CHECK: loop_exit.split:
109 ; CHECK-NEXT: br label %loop_exit
112 %v = load i1, i1* %ptr
113 br i1 %v, label %loop_begin, label %loop_exit
118 ; CHECK-NEXT: ret void
121 ; Check that even with large amounts of code on either side of the unswitched
122 ; branch, if that code would be kept in only one of the unswitched clones it
123 ; doesn't contribute to the cost.
124 define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
125 ; CHECK-LABEL: @test_unswitch_non_dup_code(
129 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
133 br i1 %cond, label %loop_a, label %loop_b
141 ; The 'loop_a' unswitched loop.
143 ; CHECK: entry.split.us:
144 ; CHECK-NEXT: br label %loop_begin.us
146 ; CHECK: loop_begin.us:
147 ; CHECK-NEXT: call void @x()
148 ; CHECK-NEXT: br label %loop_a.us
151 ; CHECK-NEXT: call void @a()
152 ; CHECK-NEXT: call void @a()
153 ; CHECK-NEXT: call void @a()
154 ; CHECK-NEXT: call void @a()
155 ; CHECK-NEXT: br label %loop_latch.us
157 ; CHECK: loop_latch.us:
158 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
159 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
161 ; CHECK: loop_exit.split.us:
162 ; CHECK-NEXT: br label %loop_exit
170 ; The 'loop_b' unswitched loop.
172 ; CHECK: entry.split:
173 ; CHECK-NEXT: br label %loop_begin
176 ; CHECK-NEXT: call void @x()
177 ; CHECK-NEXT: br label %loop_b
180 ; CHECK-NEXT: call void @b()
181 ; CHECK-NEXT: call void @b()
182 ; CHECK-NEXT: call void @b()
183 ; CHECK-NEXT: call void @b()
184 ; CHECK-NEXT: br label %loop_latch
187 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
188 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
190 ; CHECK: loop_exit.split:
191 ; CHECK-NEXT: br label %loop_exit
194 %v = load i1, i1* %ptr
195 br i1 %v, label %loop_begin, label %loop_exit
200 ; CHECK-NEXT: ret void
203 ; Much like with non-duplicated code directly in the successor, we also won't
204 ; duplicate even interesting CFGs.
205 define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
206 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
210 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
214 br i1 %cond, label %loop_a, label %loop_b
217 %v1 = load i1, i1* %ptr
218 br i1 %v1, label %loop_a_a, label %loop_a_b
227 ; The 'loop_a' unswitched loop.
229 ; CHECK: entry.split.us:
230 ; CHECK-NEXT: br label %loop_begin.us
232 ; CHECK: loop_begin.us:
233 ; CHECK-NEXT: call void @x()
234 ; CHECK-NEXT: br label %loop_a.us
237 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
238 ; CHECK-NEXT: br i1 %[[V]], label %loop_a_a.us, label %loop_a_b.us
240 ; CHECK: loop_a_b.us:
241 ; CHECK-NEXT: call void @a()
242 ; CHECK-NEXT: br label %loop_latch.us
244 ; CHECK: loop_a_a.us:
245 ; CHECK-NEXT: call void @a()
246 ; CHECK-NEXT: br label %loop_latch.us
248 ; CHECK: loop_latch.us:
249 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
250 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
252 ; CHECK: loop_exit.split.us:
253 ; CHECK-NEXT: br label %loop_exit
256 %v2 = load i1, i1* %ptr
257 br i1 %v2, label %loop_b_a, label %loop_b_b
266 ; The 'loop_b' unswitched loop.
268 ; CHECK: entry.split:
269 ; CHECK-NEXT: br label %loop_begin
272 ; CHECK-NEXT: call void @x()
273 ; CHECK-NEXT: br label %loop_b
276 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
277 ; CHECK-NEXT: br i1 %[[V]], label %loop_b_a, label %loop_b_b
280 ; CHECK-NEXT: call void @b()
281 ; CHECK-NEXT: br label %loop_latch
284 ; CHECK-NEXT: call void @b()
285 ; CHECK-NEXT: br label %loop_latch
288 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
289 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
291 ; CHECK: loop_exit.split:
292 ; CHECK-NEXT: br label %loop_exit
295 %v3 = load i1, i1* %ptr
296 br i1 %v3, label %loop_begin, label %loop_exit
301 ; CHECK-NEXT: ret void
304 ; Check that even if there is *some* non-duplicated code on one side of an
305 ; unswitch, we don't count any other code in the loop that will in fact have to
307 define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
308 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
312 ; CHECK-NEXT: br label %loop_begin
314 ; We shouldn't have unswitched into any other block either.
315 ; CHECK-NOT: br i1 %cond
319 br i1 %cond, label %loop_a, label %loop_b
321 ; CHECK-NEXT: call void @x()
322 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
325 %v1 = load i1, i1* %ptr
326 br i1 %v1, label %loop_a_a, label %loop_a_b
337 %v2 = load i1, i1* %ptr
338 br i1 %v2, label %loop_b_a, label %loop_b_b
351 %v = load i1, i1* %ptr
352 br i1 %v, label %loop_begin, label %loop_exit
358 ; Check that we still unswitch when the exit block contains lots of code, even
359 ; though we do clone the exit block as part of unswitching. This should work
360 ; because we should split the exit block before anything inside it.
361 define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
362 ; CHECK-LABEL: @test_unswitch_large_exit(
366 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
370 br i1 %cond, label %loop_a, label %loop_b
375 ; The 'loop_a' unswitched loop.
377 ; CHECK: entry.split.us:
378 ; CHECK-NEXT: br label %loop_begin.us
380 ; CHECK: loop_begin.us:
381 ; CHECK-NEXT: call void @x()
382 ; CHECK-NEXT: br label %loop_a.us
385 ; CHECK-NEXT: call void @a()
386 ; CHECK-NEXT: br label %loop_latch.us
388 ; CHECK: loop_latch.us:
389 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
390 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
392 ; CHECK: loop_exit.split.us:
393 ; CHECK-NEXT: br label %loop_exit
398 ; The 'loop_b' unswitched loop.
400 ; CHECK: entry.split:
401 ; CHECK-NEXT: br label %loop_begin
404 ; CHECK-NEXT: call void @x()
405 ; CHECK-NEXT: br label %loop_b
408 ; CHECK-NEXT: call void @b()
409 ; CHECK-NEXT: br label %loop_latch
412 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
413 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
415 ; CHECK: loop_exit.split:
416 ; CHECK-NEXT: br label %loop_exit
419 %v = load i1, i1* %ptr
420 br i1 %v, label %loop_begin, label %loop_exit
429 ; CHECK-NEXT: call void @x()
430 ; CHECK-NEXT: call void @x()
431 ; CHECK-NEXT: call void @x()
432 ; CHECK-NEXT: call void @x()
433 ; CHECK-NEXT: ret void
436 ; Check that we handle a dedicated exit edge unswitch which is still
437 ; non-trivial and has lots of code in the exit.
438 define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
439 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
443 ; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
447 br i1 %cond, label %loop_a, label %loop_b_exit
452 ; The 'loop_a' unswitched loop.
454 ; CHECK: entry.split.us:
455 ; CHECK-NEXT: br label %loop_begin.us
457 ; CHECK: loop_begin.us:
458 ; CHECK-NEXT: call void @x()
459 ; CHECK-NEXT: br label %loop_a.us
462 ; CHECK-NEXT: call void @a()
463 ; CHECK-NEXT: br label %loop_latch.us
465 ; CHECK: loop_latch.us:
466 ; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
467 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
469 ; CHECK: loop_exit.split.us:
470 ; CHECK-NEXT: br label %loop_exit
478 ; The 'loop_b_exit' unswitched exit path.
480 ; CHECK: entry.split:
481 ; CHECK-NEXT: br label %loop_begin
484 ; CHECK-NEXT: call void @x()
485 ; CHECK-NEXT: br label %loop_b_exit
487 ; CHECK: loop_b_exit:
488 ; CHECK-NEXT: call void @b()
489 ; CHECK-NEXT: call void @b()
490 ; CHECK-NEXT: call void @b()
491 ; CHECK-NEXT: call void @b()
492 ; CHECK-NEXT: ret void
495 %v = load i1, i1* %ptr
496 br i1 %v, label %loop_begin, label %loop_exit
501 ; CHECK-NEXT: ret void