Compiler projects using llvm
; 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:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
; CHECK-NEXT:    br i1 [[COND_FR]], 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:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
; CHECK-NEXT:    br i1 [[COND_FR]], 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:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
; CHECK-NEXT:    br i1 [[COND_FR]], 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:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
; CHECK-NEXT:    br i1 [[COND_FR]], 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:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
; CHECK-NEXT:    br i1 [[COND_FR]], 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 }