Compiler projects using llvm
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s

declare void @clobber()

define i32 @partial_unswitch_true_successor(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @partial_unswitch_false_successor(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_false_successor(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %clobber, label %noclobber

clobber:
  call void @clobber()
  br label %loop.latch

noclobber:
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @partial_unswtich_gep_load_icmp(i32** %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswtich_gep_load_icmp(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i32*, i32** [[PTR:%.*]], i32 1
; CHECK-NEXT:    [[TMP1:%.*]] = load i32*, i32** [[TMP0]], align 8
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 100
; CHECK-NEXT:    br i1 [[TMP3]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32*, i32** [[PTR]], i32 1
; CHECK-NEXT:    [[LV_1:%.*]] = load i32*, i32** [[GEP]], align 8
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[LV_1]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP3:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = getelementptr i32*, i32** %ptr, i32 1
  %lv.1 = load i32*, i32** %gep
  %lv = load i32, i32* %lv.1
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @partial_unswitch_reduction_phi(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_reduction_phi(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    [[RED_US:%.*]] = phi i32 [ 20, [[ENTRY_SPLIT_US]] ], [ [[RED_NEXT_US:%.*]], [[LOOP_LATCH_US]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    [[ADD_10_US:%.*]] = add i32 [[RED_US]], 10
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[RED_NEXT_US]] = phi i32 [ [[ADD_10_US]], [[NOCLOBBER_US]] ]
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    [[RED_NEXT_LCSSA_US:%.*]] = phi i32 [ [[RED_NEXT_US]], [[LOOP_LATCH_US]] ]
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[RED:%.*]] = phi i32 [ 20, [[ENTRY_SPLIT]] ], [ [[RED_NEXT:%.*]], [[LOOP_LATCH]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    [[ADD_5:%.*]] = add i32 [[RED]], 5
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       noclobber:
; CHECK-NEXT:    [[ADD_10:%.*]] = add i32 [[RED]], 10
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[RED_NEXT]] = phi i32 [ [[ADD_5]], [[CLOBBER]] ], [ [[ADD_10]], [[NOCLOBBER]] ]
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP4:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    [[RED_NEXT_LCSSA:%.*]] = phi i32 [ [[RED_NEXT]], [[LOOP_LATCH]] ]
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    [[DOTUS_PHI:%.*]] = phi i32 [ [[RED_NEXT_LCSSA]], [[EXIT_SPLIT]] ], [ [[RED_NEXT_LCSSA_US]], [[EXIT_SPLIT_US]] ]
; CHECK-NEXT:    ret i32 [[DOTUS_PHI]]
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %red = phi i32 [ 20, %entry ], [ %red.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %clobber, label %noclobber

clobber:
  call void @clobber()
  %add.5 = add i32 %red, 5
  br label %loop.latch

noclobber:
  %add.10 = add i32 %red, 10
  br label %loop.latch

loop.latch:
  %red.next = phi i32 [ %add.5, %clobber ], [ %add.10, %noclobber ]
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  %red.next.lcssa = phi i32 [ %red.next, %loop.latch ]
  ret i32 %red.next.lcssa
}

; Partial unswitching is possible, because the store in %noclobber does not
; alias the load of the condition.
define i32 @partial_unswitch_true_successor_noclobber(i32* noalias %ptr.1, i32* noalias %ptr.2, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor_noclobber(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    [[LV_US:%.*]] = load i32, i32* [[PTR_1]], align 4
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    [[GEP_1_US:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV_US]]
; CHECK-NEXT:    store i32 [[LV_US]], i32* [[GEP_1_US]], align 4
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR_1]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2]], i32 [[IV]]
; CHECK-NEXT:    store i32 [[LV]], i32* [[GEP_1]], align 4
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP5:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr.1
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv
  store i32 %lv, i32* %gep.1
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define void @no_partial_unswitch_phi_cond(i1 %lc, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_phi_cond(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[SC:%.*]] = phi i1 [ [[LC:%.*]], [[ENTRY]] ], [ true, [[LOOP_LATCH]] ]
; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %sc = phi i1 [ %lc, %entry ], [ true, %loop.latch ]
  br i1 %sc, label %clobber, label %noclobber

clobber:
  call void @clobber()
  br label %loop.latch

noclobber:
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret void
}

define void @no_partial_unswitch_clobber_latch(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_clobber_latch(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  call void @clobber()
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret void
}

define void @no_partial_unswitch_clobber_header(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_clobber_header(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  call void @clobber()
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret void
}

define void @no_partial_unswitch_clobber_both(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_clobber_both(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  call void @clobber()
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret void
}

define i32 @no_partial_unswitch_true_successor_storeclobber(i32* %ptr.1, i32* %ptr.2, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_true_successor_storeclobber(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV]]
; CHECK-NEXT:    store i32 [[LV]], i32* [[GEP_1]], align 4
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr.1
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv
  store i32 %lv, i32* %gep.1
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; Make sure the duplicated instructions are moved to a preheader that always
; executes when the loop body also executes. Do not check the unswitched code,
; because it is already checked in the @partial_unswitch_true_successor test
; case.
define i32 @partial_unswitch_true_successor_preheader_insertion(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor_preheader_insertion(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[EC:%.*]] = icmp ne i32* [[PTR:%.*]], null
; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]]
; CHECK:       loop.ph:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PH_SPLIT_US:%.*]], label [[LOOP_PH_SPLIT:%.*]]
; CHECK:       loop.ph.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[LOOP_PH_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_LOOPEXIT_SPLIT_US:%.*]]
; CHECK:       exit.loopexit.split.us:
; CHECK-NEXT:    br label [[EXIT_LOOPEXIT:%.*]]
; CHECK:       loop.ph.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[LOOP_PH_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT_SPLIT:%.*]], !llvm.loop [[LOOP6:![0-9]+]]
; CHECK:       exit.loopexit.split:
; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
; CHECK:       exit.loopexit:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;

entry:
  %ec = icmp ne i32* %ptr, null
  br i1 %ec, label %loop.ph, label %exit

loop.ph:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %loop.ph ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; Make sure the duplicated instructions are hoisted just before the branch of
; the preheader. Do not check the unswitched code, because it is already checked
; in the @partial_unswitch_true_successor test case
define i32 @partial_unswitch_true_successor_insert_point(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor_insert_point(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP7:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  call void @clobber()
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; Make sure invariant instructions in the loop are also hoisted to the preheader.
; Do not check the unswitched code, because it is already checked in the
; @partial_unswitch_true_successor test case
define i32 @partial_unswitch_true_successor_hoist_invariant(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor_hoist_invariant(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 1
; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 100
; CHECK-NEXT:    br i1 [[TMP2]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, i32* [[PTR]], i64 1
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[GEP]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = getelementptr i32, i32* %ptr, i64 1
  %lv = load i32, i32* %gep
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; Do not unswitch if the condition depends on an atomic load. Duplicating such
; loads is not safe.
define i32 @no_partial_unswitch_atomic_load_unordered(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_atomic_load_unordered(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] unordered, align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load atomic i32, i32* %ptr unordered, align 4
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; Do not unswitch if the condition depends on an atomic load. Duplicating such
; loads is not safe.
define i32 @no_partial_unswitch_atomic_load_monotonic(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_atomic_load_monotonic(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] monotonic, align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load atomic i32, i32* %ptr monotonic, align 4
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}


declare i32 @get_value()

; Do not unswitch if the condition depends on a call, that may clobber memory.
; Duplicating such a call is not safe.
define i32 @no_partial_unswitch_cond_call(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_cond_call(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = call i32 @get_value()
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = call i32 @get_value()
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @no_partial_unswitch_true_successor_exit(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_true_successor_exit(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[EXIT:%.*]], label [[CLOBBER:%.*]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %exit, label %clobber

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @no_partial_unswitch_true_same_successor(i32* %ptr, i32 %N) {
; CHECK-LABEL: @no_partial_unswitch_true_same_successor(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[NOCLOBBER]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %noclobber

noclobber:
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

define i32 @partial_unswitch_true_to_latch(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_to_latch(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[LOOP_LATCH]], label [[CLOBBER:%.*]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %loop.latch, label %clobber

clobber:
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; There could be multiple unswitch candidates which include partially invariant
; condition. When the exiting block is selected as best unswitch one, clone loop
; blocks.
define i32 @partial_unswitch_exiting_block_with_multiple_unswitch_candidates(i32 %0, i32 %1, i32* %ptr) {
; CHECK-LABEL: @partial_unswitch_exiting_block_with_multiple_unswitch_candidates(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[EXIT_COND:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[PTR:%.*]], align 16
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 41
; CHECK-NEXT:    br i1 [[TMP3]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br i1 [[EXIT_COND]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]], label [[ENTRY_SPLIT_US_SPLIT:%.*]]
; CHECK:       entry.split.us.split.us:
; CHECK-NEXT:    br label [[LOOP_US_US:%.*]]
; CHECK:       loop.us.us:
; CHECK-NEXT:    br label [[EXITING_US_US:%.*]]
; CHECK:       exiting.us.us:
; CHECK-NEXT:    br label [[LOOP_US_US]]
; CHECK:       entry.split.us.split:
; CHECK-NEXT:    br label [[LOOP_US:%.*]]
; CHECK:       loop.us:
; CHECK-NEXT:    br label [[EXITING_US:%.*]]
; CHECK:       exiting.us:
; CHECK-NEXT:    br label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    [[RET_VAL_US:%.*]] = phi i32 [ 1, [[EXITING_US]] ]
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR]], align 16
; CHECK-NEXT:    [[IF_COND:%.*]] = icmp ult i32 [[VAL]], 41
; CHECK-NEXT:    br i1 [[IF_COND]], label [[IF_THEN:%.*]], label [[EXITING:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    store i32 [[TMP1:%.*]], i32* [[PTR]], align 16
; CHECK-NEXT:    br label [[EXITING]]
; CHECK:       exiting:
; CHECK-NEXT:    br i1 [[EXIT_COND]], label [[LOOP]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP10:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    [[RET_VAL:%.*]] = phi i32 [ 1, [[EXITING]] ]
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    [[DOTUS_PHI:%.*]] = phi i32 [ [[RET_VAL]], [[EXIT_SPLIT]] ], [ [[RET_VAL_US]], [[EXIT_SPLIT_US]] ]
; CHECK-NEXT:    ret i32 [[DOTUS_PHI]]
;
entry:
  %exit.cond = icmp ne i32 %0, 0
  br label %loop

loop:
  %val = load i32, i32* %ptr, align 16
  %if.cond = icmp ult i32 %val, 41
  br i1 %if.cond, label %if.then, label %exiting

if.then:
  store i32 %1, i32* %ptr, align 16
  br label %exiting

exiting:
  br i1 %exit.cond, label %loop, label %exit

exit:
  %ret.val = phi i32 [ 1, %exiting ]
  ret i32 %ret.val
}

; The path with noclobber block is only duplicated so we need to calculate only
; the cost of the path with noclobber.
define i32 @partial_unswitch_true_successor_for_cost_calculation(i32* %ptr, i32 %N) {
; CHECK-LABEL: @partial_unswitch_true_successor_for_cost_calculation(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK:       entry.split.us:
; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
; CHECK:       loop.header.us:
; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
; CHECK:       noclobber.us:
; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
; CHECK:       loop.latch.us:
; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
; CHECK:       exit.split.us:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       entry.split:
; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
; CHECK:       loop.header:
; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
; CHECK:       noclobber:
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       clobber:
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    call void @clobber()
; CHECK-NEXT:    br label [[LOOP_LATCH]]
; CHECK:       loop.latch:
; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]]
; CHECK:       exit.split:
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 10
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %lv = load i32, i32* %ptr
  %sc = icmp eq i32 %lv, 100
  br i1 %sc, label %noclobber, label %clobber

noclobber:
  br label %loop.latch

clobber:
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  call void @clobber()
  br label %loop.latch

loop.latch:
  %c = icmp ult i32 %iv, %N
  %iv.next = add i32 %iv, 1
  br i1 %c, label %loop.header, label %exit

exit:
  ret i32 10
}

; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[UNSWITCH_PARTIAL_DISABLE:![0-9]+]]}
; CHECK: [[UNSWITCH_PARTIAL_DISABLE]] = !{!"llvm.loop.unswitch.partial.disable"}
; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[UNSWITCH_PARTIAL_DISABLE]]}
; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[UNSWITCH_PARTIAL_DISABLE]]}