1 ; Specifically exercise the cost modeling for non-trivial loop unswitching.
3 ; RUN: opt -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -unswitch-threshold=5 -S < %s | FileCheck %s
4 ; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -unswitch-threshold=5 -S -verify-memoryssa < %s | FileCheck %s
10 ; First establish enough code size in the duplicated 'loop_begin' block to
11 ; suppress unswitching.
12 define void @test_no_unswitch(ptr %ptr, i1 %cond) {
13 ; CHECK-LABEL: @test_no_unswitch(
17 ; CHECK-NEXT: br label %loop_begin
19 ; We shouldn't have unswitched into any other block either.
20 ; CHECK-NOT: br i1 %cond
27 br i1 %cond, label %loop_a, label %loop_b
29 ; CHECK-NEXT: call void @x()
30 ; CHECK-NEXT: call void @x()
31 ; CHECK-NEXT: call void @x()
32 ; CHECK-NEXT: call void @x()
33 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
44 %v = load i1, ptr %ptr
45 br i1 %v, label %loop_begin, label %loop_exit
51 ; Now check that the smaller formulation of 'loop_begin' does in fact unswitch
52 ; with our low threshold.
53 define void @test_unswitch(ptr %ptr, i1 %cond) {
54 ; CHECK-LABEL: @test_unswitch(
58 ; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %cond
59 ; CHECK-NEXT: br i1 [[FROZEN]], 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, ptr %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, ptr %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, ptr %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(ptr %ptr, i1 %cond) {
125 ; CHECK-LABEL: @test_unswitch_non_dup_code(
129 ; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %cond
130 ; CHECK-NEXT: br i1 [[FROZEN]], 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, ptr %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, ptr %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, ptr %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(ptr %ptr, i1 %cond) {
207 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
211 ; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %cond
212 ; CHECK-NEXT: br i1 [[FROZEN]], label %entry.split.us, label %entry.split
216 br i1 %cond, label %loop_a, label %loop_b
219 %v1 = load i1, ptr %ptr
220 br i1 %v1, label %loop_a_a, label %loop_a_b
229 ; The 'loop_a' unswitched loop.
231 ; CHECK: entry.split.us:
232 ; CHECK-NEXT: br label %loop_begin.us
234 ; CHECK: loop_begin.us:
235 ; CHECK-NEXT: call void @x()
236 ; CHECK-NEXT: br label %loop_a.us
239 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
240 ; CHECK-NEXT: br i1 %[[V]], label %loop_a_a.us, label %loop_a_b.us
242 ; CHECK: loop_a_b.us:
243 ; CHECK-NEXT: call void @a()
244 ; CHECK-NEXT: br label %loop_latch.us
246 ; CHECK: loop_a_a.us:
247 ; CHECK-NEXT: call void @a()
248 ; CHECK-NEXT: br label %loop_latch.us
250 ; CHECK: loop_latch.us:
251 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
252 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
254 ; CHECK: loop_exit.split.us:
255 ; CHECK-NEXT: br label %loop_exit
258 %v2 = load i1, ptr %ptr
259 br i1 %v2, label %loop_b_a, label %loop_b_b
268 ; The 'loop_b' unswitched loop.
270 ; CHECK: entry.split:
271 ; CHECK-NEXT: br label %loop_begin
274 ; CHECK-NEXT: call void @x()
275 ; CHECK-NEXT: br label %loop_b
278 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
279 ; CHECK-NEXT: br i1 %[[V]], label %loop_b_a, label %loop_b_b
282 ; CHECK-NEXT: call void @b()
283 ; CHECK-NEXT: br label %loop_latch
286 ; CHECK-NEXT: call void @b()
287 ; CHECK-NEXT: br label %loop_latch
290 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
291 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
293 ; CHECK: loop_exit.split:
294 ; CHECK-NEXT: br label %loop_exit
297 %v3 = load i1, ptr %ptr
298 br i1 %v3, label %loop_begin, label %loop_exit
303 ; CHECK-NEXT: ret void
306 ; Check that even if there is *some* non-duplicated code on one side of an
307 ; unswitch, we don't count any other code in the loop that will in fact have to
309 define void @test_no_unswitch_non_dup_code(ptr %ptr, i1 %cond) {
310 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
314 ; CHECK-NEXT: br label %loop_begin
316 ; We shouldn't have unswitched into any other block either.
317 ; CHECK-NOT: br i1 %cond
321 br i1 %cond, label %loop_a, label %loop_b
323 ; CHECK-NEXT: call void @x()
324 ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b
327 %v1 = load i1, ptr %ptr
328 br i1 %v1, label %loop_a_a, label %loop_a_b
339 %v2 = load i1, ptr %ptr
340 br i1 %v2, label %loop_b_a, label %loop_b_b
353 %v = load i1, ptr %ptr
354 br i1 %v, label %loop_begin, label %loop_exit
360 ; Check that we still unswitch when the exit block contains lots of code, even
361 ; though we do clone the exit block as part of unswitching. This should work
362 ; because we should split the exit block before anything inside it.
363 define void @test_unswitch_large_exit(ptr %ptr, i1 %cond) {
364 ; CHECK-LABEL: @test_unswitch_large_exit(
368 ; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %cond
369 ; CHECK-NEXT: br i1 [[FROZEN]], label %entry.split.us, label %entry.split
373 br i1 %cond, label %loop_a, label %loop_b
378 ; The 'loop_a' unswitched loop.
380 ; CHECK: entry.split.us:
381 ; CHECK-NEXT: br label %loop_begin.us
383 ; CHECK: loop_begin.us:
384 ; CHECK-NEXT: call void @x()
385 ; CHECK-NEXT: br label %loop_a.us
388 ; CHECK-NEXT: call void @a()
389 ; CHECK-NEXT: br label %loop_latch.us
391 ; CHECK: loop_latch.us:
392 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
393 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
395 ; CHECK: loop_exit.split.us:
396 ; CHECK-NEXT: br label %loop_exit
401 ; The 'loop_b' unswitched loop.
403 ; CHECK: entry.split:
404 ; CHECK-NEXT: br label %loop_begin
407 ; CHECK-NEXT: call void @x()
408 ; CHECK-NEXT: br label %loop_b
411 ; CHECK-NEXT: call void @b()
412 ; CHECK-NEXT: br label %loop_latch
415 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
416 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
418 ; CHECK: loop_exit.split:
419 ; CHECK-NEXT: br label %loop_exit
422 %v = load i1, ptr %ptr
423 br i1 %v, label %loop_begin, label %loop_exit
432 ; CHECK-NEXT: call void @x()
433 ; CHECK-NEXT: call void @x()
434 ; CHECK-NEXT: call void @x()
435 ; CHECK-NEXT: call void @x()
436 ; CHECK-NEXT: ret void
439 ; Check that we handle a dedicated exit edge unswitch which is still
440 ; non-trivial and has lots of code in the exit.
441 define void @test_unswitch_dedicated_exiting(ptr %ptr, i1 %cond) {
442 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
446 ; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %cond
447 ; CHECK-NEXT: br i1 [[FROZEN]], label %entry.split.us, label %entry.split
451 br i1 %cond, label %loop_a, label %loop_b_exit
456 ; The 'loop_a' unswitched loop.
458 ; CHECK: entry.split.us:
459 ; CHECK-NEXT: br label %loop_begin.us
461 ; CHECK: loop_begin.us:
462 ; CHECK-NEXT: call void @x()
463 ; CHECK-NEXT: br label %loop_a.us
466 ; CHECK-NEXT: call void @a()
467 ; CHECK-NEXT: br label %loop_latch.us
469 ; CHECK: loop_latch.us:
470 ; CHECK-NEXT: %[[V:.*]] = load i1, ptr %ptr
471 ; CHECK-NEXT: br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
473 ; CHECK: loop_exit.split.us:
474 ; CHECK-NEXT: br label %loop_exit
482 ; The 'loop_b_exit' unswitched exit path.
484 ; CHECK: entry.split:
485 ; CHECK-NEXT: br label %loop_begin
488 ; CHECK-NEXT: call void @x()
489 ; CHECK-NEXT: br label %loop_b_exit
491 ; CHECK: loop_b_exit:
492 ; CHECK-NEXT: call void @b()
493 ; CHECK-NEXT: call void @b()
494 ; CHECK-NEXT: call void @b()
495 ; CHECK-NEXT: call void @b()
496 ; CHECK-NEXT: ret void
499 %v = load i1, ptr %ptr
500 br i1 %v, label %loop_begin, label %loop_exit
505 ; CHECK-NEXT: ret void