| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -mtriple=thumbv8m.main -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S -o - %s | FileCheck %s |
| |
| declare void @a() |
| declare void @b() |
| declare void @x() |
| |
| define void @test_no_unswitch(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_no_unswitch( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| loop_begin: |
| call void @x() |
| call void @x() |
| call void @x() |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_unswitch( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] |
| ; CHECK: loop_begin.us: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_A_US:%.*]] |
| ; CHECK: loop_a.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] |
| ; CHECK: loop_latch.us: |
| ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] |
| ; CHECK: loop_exit.split.us: |
| ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_B:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]] |
| ; CHECK: loop_exit.split: |
| ; CHECK-NEXT: br label [[LOOP_EXIT]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_minsize(i1* %ptr, i1 %cond) #0 { |
| ; CHECK-LABEL: @test_unswitch_minsize( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_unswitch_non_dup_code( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] |
| ; CHECK: loop_begin.us: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_A_US:%.*]] |
| ; CHECK: loop_a.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] |
| ; CHECK: loop_latch.us: |
| ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] |
| ; CHECK: loop_exit.split.us: |
| ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_B:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]] |
| ; CHECK: loop_exit.split: |
| ; CHECK-NEXT: br label [[LOOP_EXIT]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| call void @a() |
| call void @a() |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| call void @b() |
| call void @b() |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_non_dup_code_minsize(i1* %ptr, i1 %cond) #0 { |
| ; CHECK-LABEL: @test_unswitch_non_dup_code_minsize( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| call void @a() |
| call void @a() |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| call void @b() |
| call void @b() |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] |
| ; CHECK: loop_begin.us: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_A_US:%.*]] |
| ; CHECK: loop_a.us: |
| ; CHECK-NEXT: [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]] |
| ; CHECK: loop_a_b.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] |
| ; CHECK: loop_a_a.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US]] |
| ; CHECK: loop_latch.us: |
| ; CHECK-NEXT: [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] |
| ; CHECK: loop_exit.split.us: |
| ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_B:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]] |
| ; CHECK: loop_b_a: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_b_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]] |
| ; CHECK: loop_exit.split: |
| ; CHECK-NEXT: br label [[LOOP_EXIT]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| %v1 = load i1, i1* %ptr |
| br i1 %v1, label %loop_a_a, label %loop_a_b |
| |
| loop_a_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_a_b: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| %v2 = load i1, i1* %ptr |
| br i1 %v2, label %loop_b_a, label %loop_b_b |
| |
| loop_b_a: |
| call void @b() |
| br label %loop_latch |
| |
| loop_b_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v3 = load i1, i1* %ptr |
| br i1 %v3, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_non_dup_code_in_cfg_minsize(i1* %ptr, i1 %cond) #0 { |
| ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg_minsize( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]] |
| ; CHECK: loop_a_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_a_b: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]] |
| ; CHECK: loop_b_a: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_b_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V3:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| %v1 = load i1, i1* %ptr |
| br i1 %v1, label %loop_a_a, label %loop_a_b |
| |
| loop_a_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_a_b: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| %v2 = load i1, i1* %ptr |
| br i1 %v2, label %loop_b_a, label %loop_b_b |
| |
| loop_b_a: |
| call void @b() |
| br label %loop_latch |
| |
| loop_b_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v3 = load i1, i1* %ptr |
| br i1 %v3, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_no_unswitch_non_dup_code( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]] |
| ; CHECK: loop_a_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_a_b: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: [[V2:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]] |
| ; CHECK: loop_b_a: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_b_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| %v1 = load i1, i1* %ptr |
| br i1 %v1, label %loop_a_a, label %loop_a_b |
| |
| loop_a_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_a_b: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| %v2 = load i1, i1* %ptr |
| br i1 %v2, label %loop_b_a, label %loop_b_b |
| |
| loop_b_a: |
| call void @b() |
| br label %loop_latch |
| |
| loop_b_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| call void @x() |
| call void @x() |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_unswitch_large_exit( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] |
| ; CHECK: loop_begin.us: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_A_US:%.*]] |
| ; CHECK: loop_a.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] |
| ; CHECK: loop_latch.us: |
| ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] |
| ; CHECK: loop_exit.split.us: |
| ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_B:%.*]] |
| ; CHECK: loop_b: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]] |
| ; CHECK: loop_exit.split: |
| ; CHECK-NEXT: br label [[LOOP_EXIT]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b: |
| call void @b() |
| br label %loop_latch |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| call void @x() |
| call void @x() |
| call void @x() |
| call void @x() |
| ret void |
| } |
| |
| define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) { |
| ; CHECK-LABEL: @test_unswitch_dedicated_exiting( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] |
| ; CHECK: entry.split.us: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]] |
| ; CHECK: loop_begin.us: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_A_US:%.*]] |
| ; CHECK: loop_a.us: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]] |
| ; CHECK: loop_latch.us: |
| ; CHECK-NEXT: [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]] |
| ; CHECK: loop_exit.split.us: |
| ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]] |
| ; CHECK: entry.split: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br label [[LOOP_B_EXIT:%.*]] |
| ; CHECK: loop_b_exit: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: ret void |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b_exit |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b_exit: |
| call void @b() |
| call void @b() |
| call void @b() |
| call void @b() |
| ret void |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| define void @test_unswitch_dedicated_exiting_minsize(i1* %ptr, i1 %cond) #0 { |
| ; CHECK-LABEL: @test_unswitch_dedicated_exiting_minsize( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] |
| ; CHECK: loop_begin: |
| ; CHECK-NEXT: call void @x() |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B_EXIT:%.*]] |
| ; CHECK: loop_a: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label [[LOOP_LATCH:%.*]] |
| ; CHECK: loop_b_exit: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: ret void |
| ; CHECK: loop_latch: |
| ; CHECK-NEXT: [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1 |
| ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]] |
| ; CHECK: loop_exit: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop_begin |
| |
| loop_begin: |
| call void @x() |
| br i1 %cond, label %loop_a, label %loop_b_exit |
| |
| loop_a: |
| call void @a() |
| br label %loop_latch |
| |
| loop_b_exit: |
| call void @b() |
| call void @b() |
| call void @b() |
| call void @b() |
| ret void |
| |
| loop_latch: |
| %v = load i1, i1* %ptr |
| br i1 %v, label %loop_begin, label %loop_exit |
| |
| loop_exit: |
| ret void |
| } |
| |
| attributes #0 = { minsize optsize } |