1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -mtriple=thumbv8m.main -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S -o - %s | FileCheck %s
8 define void @test_no_unswitch(i1* %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, i1* [[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, i1* %ptr
49 br i1 %v, label %loop_begin, label %loop_exit
55 define void @test_unswitch(i1* %ptr, i1 %cond) {
56 ; CHECK-LABEL: @test_unswitch(
58 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
59 ; CHECK: entry.split.us:
60 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
61 ; CHECK: loop_begin.us:
62 ; CHECK-NEXT: call void @x()
63 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
65 ; CHECK-NEXT: call void @a()
66 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
67 ; CHECK: loop_latch.us:
68 ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
69 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
70 ; CHECK: loop_exit.split.us:
71 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
73 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
75 ; CHECK-NEXT: call void @x()
76 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
78 ; CHECK-NEXT: call void @b()
79 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
81 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
82 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
83 ; CHECK: loop_exit.split:
84 ; CHECK-NEXT: br label [[LOOP_EXIT]]
86 ; CHECK-NEXT: ret void
93 br i1 %cond, label %loop_a, label %loop_b
104 %v = load i1, i1* %ptr
105 br i1 %v, label %loop_begin, label %loop_exit
111 define void @test_unswitch_minsize(i1* %ptr, i1 %cond) #0 {
112 ; CHECK-LABEL: @test_unswitch_minsize(
114 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
116 ; CHECK-NEXT: call void @x()
117 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
119 ; CHECK-NEXT: call void @a()
120 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
122 ; CHECK-NEXT: call void @b()
123 ; CHECK-NEXT: br label [[LOOP_LATCH]]
125 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1
126 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
128 ; CHECK-NEXT: ret void
135 br i1 %cond, label %loop_a, label %loop_b
146 %v = load i1, i1* %ptr
147 br i1 %v, label %loop_begin, label %loop_exit
153 define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
154 ; CHECK-LABEL: @test_unswitch_non_dup_code(
156 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
157 ; CHECK: entry.split.us:
158 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
159 ; CHECK: loop_begin.us:
160 ; CHECK-NEXT: call void @x()
161 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
163 ; CHECK-NEXT: call void @a()
164 ; CHECK-NEXT: call void @a()
165 ; CHECK-NEXT: call void @a()
166 ; CHECK-NEXT: call void @a()
167 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
168 ; CHECK: loop_latch.us:
169 ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
170 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
171 ; CHECK: loop_exit.split.us:
172 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
173 ; CHECK: entry.split:
174 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
176 ; CHECK-NEXT: call void @x()
177 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
179 ; CHECK-NEXT: call void @b()
180 ; CHECK-NEXT: call void @b()
181 ; CHECK-NEXT: call void @b()
182 ; CHECK-NEXT: call void @b()
183 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
185 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
186 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
187 ; CHECK: loop_exit.split:
188 ; CHECK-NEXT: br label [[LOOP_EXIT]]
190 ; CHECK-NEXT: ret void
197 br i1 %cond, label %loop_a, label %loop_b
214 %v = load i1, i1* %ptr
215 br i1 %v, label %loop_begin, label %loop_exit
221 define void @test_unswitch_non_dup_code_minsize(i1* %ptr, i1 %cond) #0 {
222 ; CHECK-LABEL: @test_unswitch_non_dup_code_minsize(
224 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
226 ; CHECK-NEXT: call void @x()
227 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
229 ; CHECK-NEXT: call void @a()
230 ; CHECK-NEXT: call void @a()
231 ; CHECK-NEXT: call void @a()
232 ; CHECK-NEXT: call void @a()
233 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
235 ; CHECK-NEXT: call void @b()
236 ; CHECK-NEXT: call void @b()
237 ; CHECK-NEXT: call void @b()
238 ; CHECK-NEXT: call void @b()
239 ; CHECK-NEXT: br label [[LOOP_LATCH]]
241 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1
242 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
244 ; CHECK-NEXT: ret void
251 br i1 %cond, label %loop_a, label %loop_b
268 %v = load i1, i1* %ptr
269 br i1 %v, label %loop_begin, label %loop_exit
275 define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
276 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
278 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
279 ; CHECK: entry.split.us:
280 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
281 ; CHECK: loop_begin.us:
282 ; CHECK-NEXT: call void @x()
283 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
285 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
286 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
287 ; CHECK: loop_a_b.us:
288 ; CHECK-NEXT: call void @a()
289 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
290 ; CHECK: loop_a_a.us:
291 ; CHECK-NEXT: call void @a()
292 ; CHECK-NEXT: br label [[LOOP_LATCH_US]]
293 ; CHECK: loop_latch.us:
294 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1
295 ; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
296 ; CHECK: loop_exit.split.us:
297 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
298 ; CHECK: entry.split:
299 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
301 ; CHECK-NEXT: call void @x()
302 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
304 ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
305 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
307 ; CHECK-NEXT: call void @b()
308 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
310 ; CHECK-NEXT: call void @b()
311 ; CHECK-NEXT: br label [[LOOP_LATCH]]
313 ; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1
314 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
315 ; CHECK: loop_exit.split:
316 ; CHECK-NEXT: br label [[LOOP_EXIT]]
318 ; CHECK-NEXT: ret void
325 br i1 %cond, label %loop_a, label %loop_b
328 %v1 = load i1, i1* %ptr
329 br i1 %v1, label %loop_a_a, label %loop_a_b
340 %v2 = load i1, i1* %ptr
341 br i1 %v2, label %loop_b_a, label %loop_b_b
352 %v3 = load i1, i1* %ptr
353 br i1 %v3, label %loop_begin, label %loop_exit
359 define void @test_unswitch_non_dup_code_in_cfg_minsize(i1* %ptr, i1 %cond) #0 {
360 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg_minsize(
362 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
364 ; CHECK-NEXT: call void @x()
365 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
367 ; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1
368 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
370 ; CHECK-NEXT: call void @a()
371 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
373 ; CHECK-NEXT: call void @a()
374 ; CHECK-NEXT: br label [[LOOP_LATCH]]
376 ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
377 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
379 ; CHECK-NEXT: call void @b()
380 ; CHECK-NEXT: br label [[LOOP_LATCH]]
382 ; CHECK-NEXT: call void @b()
383 ; CHECK-NEXT: br label [[LOOP_LATCH]]
385 ; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1
386 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
388 ; CHECK-NEXT: ret void
395 br i1 %cond, label %loop_a, label %loop_b
398 %v1 = load i1, i1* %ptr
399 br i1 %v1, label %loop_a_a, label %loop_a_b
410 %v2 = load i1, i1* %ptr
411 br i1 %v2, label %loop_b_a, label %loop_b_b
422 %v3 = load i1, i1* %ptr
423 br i1 %v3, label %loop_begin, label %loop_exit
429 define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
430 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
432 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
434 ; CHECK-NEXT: call void @x()
435 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
437 ; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1
438 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
440 ; CHECK-NEXT: call void @a()
441 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
443 ; CHECK-NEXT: call void @a()
444 ; CHECK-NEXT: br label [[LOOP_LATCH]]
446 ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1
447 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
449 ; CHECK-NEXT: call void @b()
450 ; CHECK-NEXT: br label [[LOOP_LATCH]]
452 ; CHECK-NEXT: call void @b()
453 ; CHECK-NEXT: br label [[LOOP_LATCH]]
455 ; CHECK-NEXT: call void @x()
456 ; CHECK-NEXT: call void @x()
457 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
458 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
460 ; CHECK-NEXT: ret void
467 br i1 %cond, label %loop_a, label %loop_b
470 %v1 = load i1, i1* %ptr
471 br i1 %v1, label %loop_a_a, label %loop_a_b
482 %v2 = load i1, i1* %ptr
483 br i1 %v2, label %loop_b_a, label %loop_b_b
496 %v = load i1, i1* %ptr
497 br i1 %v, label %loop_begin, label %loop_exit
503 define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
504 ; CHECK-LABEL: @test_unswitch_large_exit(
506 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
507 ; CHECK: entry.split.us:
508 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
509 ; CHECK: loop_begin.us:
510 ; CHECK-NEXT: call void @x()
511 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
513 ; CHECK-NEXT: call void @a()
514 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
515 ; CHECK: loop_latch.us:
516 ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
517 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
518 ; CHECK: loop_exit.split.us:
519 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
520 ; CHECK: entry.split:
521 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
523 ; CHECK-NEXT: call void @x()
524 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
526 ; CHECK-NEXT: call void @b()
527 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
529 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1
530 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
531 ; CHECK: loop_exit.split:
532 ; CHECK-NEXT: br label [[LOOP_EXIT]]
534 ; CHECK-NEXT: call void @x()
535 ; CHECK-NEXT: call void @x()
536 ; CHECK-NEXT: call void @x()
537 ; CHECK-NEXT: call void @x()
538 ; CHECK-NEXT: ret void
545 br i1 %cond, label %loop_a, label %loop_b
556 %v = load i1, i1* %ptr
557 br i1 %v, label %loop_begin, label %loop_exit
567 define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
568 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
570 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
571 ; CHECK: entry.split.us:
572 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
573 ; CHECK: loop_begin.us:
574 ; CHECK-NEXT: call void @x()
575 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
577 ; CHECK-NEXT: call void @a()
578 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
579 ; CHECK: loop_latch.us:
580 ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
581 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
582 ; CHECK: loop_exit.split.us:
583 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
584 ; CHECK: entry.split:
585 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
587 ; CHECK-NEXT: call void @x()
588 ; CHECK-NEXT: br label [[LOOP_B_EXIT:%.*]]
589 ; CHECK: loop_b_exit:
590 ; CHECK-NEXT: call void @b()
591 ; CHECK-NEXT: call void @b()
592 ; CHECK-NEXT: call void @b()
593 ; CHECK-NEXT: call void @b()
594 ; CHECK-NEXT: ret void
596 ; CHECK-NEXT: ret void
603 br i1 %cond, label %loop_a, label %loop_b_exit
617 %v = load i1, i1* %ptr
618 br i1 %v, label %loop_begin, label %loop_exit
624 define void @test_unswitch_dedicated_exiting_minsize(i1* %ptr, i1 %cond) #0 {
625 ; CHECK-LABEL: @test_unswitch_dedicated_exiting_minsize(
627 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
629 ; CHECK-NEXT: call void @x()
630 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B_EXIT:%.*]]
632 ; CHECK-NEXT: call void @a()
633 ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]]
634 ; CHECK: loop_b_exit:
635 ; CHECK-NEXT: call void @b()
636 ; CHECK-NEXT: call void @b()
637 ; CHECK-NEXT: call void @b()
638 ; CHECK-NEXT: call void @b()
639 ; CHECK-NEXT: ret void
641 ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1
642 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
644 ; CHECK-NEXT: ret void
651 br i1 %cond, label %loop_a, label %loop_b_exit
665 %v = load i1, i1* %ptr
666 br i1 %v, label %loop_begin, label %loop_exit
672 attributes #0 = { minsize optsize }