1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -mtriple=thumbv8m.main -passes='simple-loop-unswitch<nontrivial>' -unswitch-threshold=5 -S -o - %s | FileCheck %s
8 define void @test_no_unswitch(ptr %ptr, i1 %cond) {
9 ; CHECK-LABEL: @test_no_unswitch(
11 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
13 ; CHECK-NEXT: call void @x()
14 ; CHECK-NEXT: call void @x()
15 ; CHECK-NEXT: call void @x()
16 ; CHECK-NEXT: call void @x()
17 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
19 ; CHECK-NEXT: call void @a()
20 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
22 ; CHECK-NEXT: call void @b()
23 ; CHECK-NEXT: br label [[LOOP_LATCH]]
25 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR:%.*]], align 1
26 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
28 ; CHECK-NEXT: ret void
37 br i1 %cond, label %loop_a, label %loop_b
48 %v = load i1, ptr %ptr
49 br i1 %v, label %loop_begin, label %loop_exit
55 define void @test_unswitch(ptr %ptr, i1 %cond) {
56 ; CHECK-LABEL: @test_unswitch(
58 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
59 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
60 ; CHECK: entry.split.us:
61 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
62 ; CHECK: loop_begin.us:
63 ; CHECK-NEXT: call void @x()
64 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
66 ; CHECK-NEXT: call void @a()
67 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
68 ; CHECK: loop_latch.us:
69 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
70 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
71 ; CHECK: loop_exit.split.us:
72 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
74 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
76 ; CHECK-NEXT: call void @x()
77 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
79 ; CHECK-NEXT: call void @b()
80 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
82 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR]], align 1
83 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
84 ; CHECK: loop_exit.split:
85 ; CHECK-NEXT: br label [[LOOP_EXIT]]
87 ; CHECK-NEXT: ret void
94 br i1 %cond, label %loop_a, label %loop_b
105 %v = load i1, ptr %ptr
106 br i1 %v, label %loop_begin, label %loop_exit
112 define void @test_unswitch_minsize(ptr %ptr, i1 %cond) #0 {
113 ; CHECK-LABEL: @test_unswitch_minsize(
115 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
117 ; CHECK-NEXT: call void @x()
118 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
120 ; CHECK-NEXT: call void @a()
121 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
123 ; CHECK-NEXT: call void @b()
124 ; CHECK-NEXT: br label [[LOOP_LATCH]]
126 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR:%.*]], align 1
127 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
129 ; CHECK-NEXT: ret void
136 br i1 %cond, label %loop_a, label %loop_b
147 %v = load i1, ptr %ptr
148 br i1 %v, label %loop_begin, label %loop_exit
154 define void @test_unswitch_non_dup_code(ptr %ptr, i1 %cond) {
155 ; CHECK-LABEL: @test_unswitch_non_dup_code(
157 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
158 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
159 ; CHECK: entry.split.us:
160 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
161 ; CHECK: loop_begin.us:
162 ; CHECK-NEXT: call void @x()
163 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
165 ; CHECK-NEXT: call void @a()
166 ; CHECK-NEXT: call void @a()
167 ; CHECK-NEXT: call void @a()
168 ; CHECK-NEXT: call void @a()
169 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
170 ; CHECK: loop_latch.us:
171 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
172 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
173 ; CHECK: loop_exit.split.us:
174 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
175 ; CHECK: entry.split:
176 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
178 ; CHECK-NEXT: call void @x()
179 ; 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:%.*]]
187 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR]], align 1
188 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
189 ; CHECK: loop_exit.split:
190 ; CHECK-NEXT: br label [[LOOP_EXIT]]
192 ; CHECK-NEXT: ret void
199 br i1 %cond, label %loop_a, label %loop_b
216 %v = load i1, ptr %ptr
217 br i1 %v, label %loop_begin, label %loop_exit
223 define void @test_unswitch_non_dup_code_minsize(ptr %ptr, i1 %cond) #0 {
224 ; CHECK-LABEL: @test_unswitch_non_dup_code_minsize(
226 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
228 ; CHECK-NEXT: call void @x()
229 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
231 ; CHECK-NEXT: call void @a()
232 ; CHECK-NEXT: call void @a()
233 ; CHECK-NEXT: call void @a()
234 ; CHECK-NEXT: call void @a()
235 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
237 ; CHECK-NEXT: call void @b()
238 ; CHECK-NEXT: call void @b()
239 ; CHECK-NEXT: call void @b()
240 ; CHECK-NEXT: call void @b()
241 ; CHECK-NEXT: br label [[LOOP_LATCH]]
243 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR:%.*]], align 1
244 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
246 ; CHECK-NEXT: ret void
253 br i1 %cond, label %loop_a, label %loop_b
270 %v = load i1, ptr %ptr
271 br i1 %v, label %loop_begin, label %loop_exit
277 define void @test_unswitch_non_dup_code_in_cfg(ptr %ptr, i1 %cond) {
278 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
280 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
281 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
282 ; CHECK: entry.split.us:
283 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
284 ; CHECK: loop_begin.us:
285 ; CHECK-NEXT: call void @x()
286 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
288 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
289 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
290 ; CHECK: loop_a_b.us:
291 ; CHECK-NEXT: call void @a()
292 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
293 ; CHECK: loop_a_a.us:
294 ; CHECK-NEXT: call void @a()
295 ; CHECK-NEXT: br label [[LOOP_LATCH_US]]
296 ; CHECK: loop_latch.us:
297 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
298 ; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
299 ; CHECK: loop_exit.split.us:
300 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
301 ; CHECK: entry.split:
302 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
304 ; CHECK-NEXT: call void @x()
305 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
307 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
308 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
310 ; CHECK-NEXT: call void @b()
311 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
313 ; CHECK-NEXT: call void @b()
314 ; CHECK-NEXT: br label [[LOOP_LATCH]]
316 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
317 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
318 ; CHECK: loop_exit.split:
319 ; CHECK-NEXT: br label [[LOOP_EXIT]]
321 ; CHECK-NEXT: ret void
328 br i1 %cond, label %loop_a, label %loop_b
331 %v1 = load i1, ptr %ptr
332 br i1 %v1, label %loop_a_a, label %loop_a_b
343 %v2 = load i1, ptr %ptr
344 br i1 %v2, label %loop_b_a, label %loop_b_b
355 %v3 = load i1, ptr %ptr
356 br i1 %v3, label %loop_begin, label %loop_exit
362 define void @test_unswitch_non_dup_code_in_cfg_minsize(ptr %ptr, i1 %cond) #0 {
363 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg_minsize(
365 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
367 ; CHECK-NEXT: call void @x()
368 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
370 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
371 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
373 ; CHECK-NEXT: call void @a()
374 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
376 ; CHECK-NEXT: call void @a()
377 ; CHECK-NEXT: br label [[LOOP_LATCH]]
379 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
380 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
382 ; CHECK-NEXT: call void @b()
383 ; CHECK-NEXT: br label [[LOOP_LATCH]]
385 ; CHECK-NEXT: call void @b()
386 ; CHECK-NEXT: br label [[LOOP_LATCH]]
388 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
389 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
391 ; CHECK-NEXT: ret void
398 br i1 %cond, label %loop_a, label %loop_b
401 %v1 = load i1, ptr %ptr
402 br i1 %v1, label %loop_a_a, label %loop_a_b
413 %v2 = load i1, ptr %ptr
414 br i1 %v2, label %loop_b_a, label %loop_b_b
425 %v3 = load i1, ptr %ptr
426 br i1 %v3, label %loop_begin, label %loop_exit
432 define void @test_no_unswitch_non_dup_code(ptr %ptr, i1 %cond) {
433 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
435 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
437 ; CHECK-NEXT: call void @x()
438 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
440 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
441 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
443 ; CHECK-NEXT: call void @a()
444 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
446 ; CHECK-NEXT: call void @a()
447 ; CHECK-NEXT: br label [[LOOP_LATCH]]
449 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
450 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
452 ; CHECK-NEXT: call void @b()
453 ; CHECK-NEXT: br label [[LOOP_LATCH]]
455 ; CHECK-NEXT: call void @b()
456 ; CHECK-NEXT: br label [[LOOP_LATCH]]
458 ; CHECK-NEXT: call void @x()
459 ; CHECK-NEXT: call void @x()
460 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR]], align 1
461 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
463 ; CHECK-NEXT: ret void
470 br i1 %cond, label %loop_a, label %loop_b
473 %v1 = load i1, ptr %ptr
474 br i1 %v1, label %loop_a_a, label %loop_a_b
485 %v2 = load i1, ptr %ptr
486 br i1 %v2, label %loop_b_a, label %loop_b_b
499 %v = load i1, ptr %ptr
500 br i1 %v, label %loop_begin, label %loop_exit
506 define void @test_unswitch_large_exit(ptr %ptr, i1 %cond) {
507 ; CHECK-LABEL: @test_unswitch_large_exit(
509 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
510 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
511 ; CHECK: entry.split.us:
512 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
513 ; CHECK: loop_begin.us:
514 ; CHECK-NEXT: call void @x()
515 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
517 ; CHECK-NEXT: call void @a()
518 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
519 ; CHECK: loop_latch.us:
520 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
521 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
522 ; CHECK: loop_exit.split.us:
523 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
524 ; CHECK: entry.split:
525 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
527 ; CHECK-NEXT: call void @x()
528 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
530 ; CHECK-NEXT: call void @b()
531 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
533 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR]], align 1
534 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
535 ; CHECK: loop_exit.split:
536 ; CHECK-NEXT: br label [[LOOP_EXIT]]
538 ; CHECK-NEXT: call void @x()
539 ; CHECK-NEXT: call void @x()
540 ; CHECK-NEXT: call void @x()
541 ; CHECK-NEXT: call void @x()
542 ; CHECK-NEXT: ret void
549 br i1 %cond, label %loop_a, label %loop_b
560 %v = load i1, ptr %ptr
561 br i1 %v, label %loop_begin, label %loop_exit
571 define void @test_unswitch_dedicated_exiting(ptr %ptr, i1 %cond) {
572 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
574 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
575 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
576 ; CHECK: entry.split.us:
577 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
578 ; CHECK: loop_begin.us:
579 ; CHECK-NEXT: call void @x()
580 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
582 ; CHECK-NEXT: call void @a()
583 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
584 ; CHECK: loop_latch.us:
585 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
586 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
587 ; CHECK: loop_exit.split.us:
588 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
589 ; CHECK: entry.split:
590 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
592 ; CHECK-NEXT: call void @x()
593 ; CHECK-NEXT: br label [[LOOP_B_EXIT:%.*]]
594 ; CHECK: loop_b_exit:
595 ; CHECK-NEXT: call void @b()
596 ; CHECK-NEXT: call void @b()
597 ; CHECK-NEXT: call void @b()
598 ; CHECK-NEXT: call void @b()
599 ; CHECK-NEXT: ret void
601 ; CHECK-NEXT: ret void
608 br i1 %cond, label %loop_a, label %loop_b_exit
622 %v = load i1, ptr %ptr
623 br i1 %v, label %loop_begin, label %loop_exit
629 define void @test_unswitch_dedicated_exiting_minsize(ptr %ptr, i1 %cond) #0 {
630 ; CHECK-LABEL: @test_unswitch_dedicated_exiting_minsize(
632 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
634 ; CHECK-NEXT: call void @x()
635 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B_EXIT:%.*]]
637 ; CHECK-NEXT: call void @a()
638 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
639 ; CHECK: loop_b_exit:
640 ; CHECK-NEXT: call void @b()
641 ; CHECK-NEXT: call void @b()
642 ; CHECK-NEXT: call void @b()
643 ; CHECK-NEXT: call void @b()
644 ; CHECK-NEXT: ret void
646 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR:%.*]], align 1
647 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
649 ; CHECK-NEXT: ret void
656 br i1 %cond, label %loop_a, label %loop_b_exit
670 %v = load i1, ptr %ptr
671 br i1 %v, label %loop_begin, label %loop_exit
677 attributes #0 = { minsize optsize }