| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | |
| ; RUN: opt < %s -passes=loop-unroll -unroll-runtime=true -unroll-runtime-epilog=false -unroll-runtime-multi-exit=true -unroll-count=4 -verify-dom-info -S | FileCheck %s | |
| ; REQUIRES: asserts | |
| ; The tests below are for verifying dom tree after runtime unrolling | |
| ; with multiple exit/exiting blocks. | |
| ; We explicitly set the unroll count so that expensiveTripCount computation is allowed. | |
| declare i1 @unknown(i32) readonly nounwind willreturn | |
| ; mergedexit block has edges from loop exit blocks. | |
| define i64 @test1() { | |
| ; CHECK-LABEL: @test1( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: br label [[PREHEADER:%.*]] | |
| ; CHECK: preheader: | |
| ; CHECK-NEXT: [[TRIP:%.*]] = zext i32 undef to i64 | |
| ; CHECK-NEXT: br label [[HEADER:%.*]] | |
| ; CHECK: header: | |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2, [[PREHEADER]] ], [ [[ADD_IV_3:%.*]], [[LATCH_3:%.*]] ] | |
| ; CHECK-NEXT: [[ADD_IV:%.*]] = add nuw nsw i64 [[IV]], 2 | |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[ADD_IV]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH:%.*]], label [[HEADEREXIT:%.*]] | |
| ; CHECK: latch: | |
| ; CHECK-NEXT: [[SHFT:%.*]] = ashr i64 [[ADD_IV]], 1 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[SHFT]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER_1:%.*]], label [[LATCHEXIT:%.*]] | |
| ; CHECK: header.1: | |
| ; CHECK-NEXT: [[ADD_IV_1:%.*]] = add nuw nsw i64 [[IV]], 4 | |
| ; CHECK-NEXT: [[CMP1_1:%.*]] = icmp samesign ult i64 [[ADD_IV_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_1]], label [[LATCH_1:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.1: | |
| ; CHECK-NEXT: [[SHFT_1:%.*]] = ashr i64 [[ADD_IV_1]], 1 | |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ult i64 [[SHFT_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_1]], label [[HEADER_2:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.2: | |
| ; CHECK-NEXT: [[ADD_IV_2:%.*]] = add nuw nsw i64 [[IV]], 6 | |
| ; CHECK-NEXT: [[CMP1_2:%.*]] = icmp samesign ult i64 [[ADD_IV_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_2]], label [[LATCH_2:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.2: | |
| ; CHECK-NEXT: [[SHFT_2:%.*]] = ashr i64 [[ADD_IV_2]], 1 | |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ult i64 [[SHFT_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_2]], label [[HEADER_3:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.3: | |
| ; CHECK-NEXT: [[ADD_IV_3]] = add nuw nsw i64 [[IV]], 8 | |
| ; CHECK-NEXT: [[CMP1_3:%.*]] = icmp samesign ult i64 [[ADD_IV_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_3]], label [[LATCH_3]], label [[HEADEREXIT]] | |
| ; CHECK: latch.3: | |
| ; CHECK-NEXT: [[SHFT_3:%.*]] = ashr i64 [[ADD_IV_3]], 1 | |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp ult i64 [[SHFT_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_3]], label [[HEADER]], label [[LATCHEXIT]], !llvm.loop [[LOOP0:![0-9]+]] | |
| ; CHECK: headerexit: | |
| ; CHECK-NEXT: [[ADDPHI:%.*]] = phi i64 [ [[ADD_IV]], [[HEADER]] ], [ [[ADD_IV_1]], [[HEADER_1]] ], [ [[ADD_IV_2]], [[HEADER_2]] ], [ [[ADD_IV_3]], [[HEADER_3]] ] | |
| ; CHECK-NEXT: br label [[MERGEDEXIT:%.*]] | |
| ; CHECK: latchexit: | |
| ; CHECK-NEXT: [[SHFTPHI:%.*]] = phi i64 [ [[SHFT]], [[LATCH]] ], [ [[SHFT_1]], [[LATCH_1]] ], [ [[SHFT_2]], [[LATCH_2]] ], [ [[SHFT_3]], [[LATCH_3]] ] | |
| ; CHECK-NEXT: br label [[MERGEDEXIT]] | |
| ; CHECK: mergedexit: | |
| ; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[ADDPHI]], [[HEADEREXIT]] ], [ [[SHFTPHI]], [[LATCHEXIT]] ] | |
| ; CHECK-NEXT: ret i64 [[RETVAL]] | |
| ; | |
| entry: | |
| br label %preheader | |
| preheader: ; preds = %bb | |
| %trip = zext i32 undef to i64 | |
| br label %header | |
| header: ; preds = %latch, %preheader | |
| %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ] | |
| %add.iv = add nuw nsw i64 %iv, 2 | |
| %cmp1 = icmp ult i64 %add.iv, %trip | |
| br i1 %cmp1, label %latch, label %headerexit | |
| latch: ; preds = %header | |
| %shft = ashr i64 %add.iv, 1 | |
| %cmp2 = icmp ult i64 %shft, %trip | |
| br i1 %cmp2, label %header, label %latchexit | |
| headerexit: ; preds = %header | |
| %addphi = phi i64 [ %add.iv, %header ] | |
| br label %mergedexit | |
| latchexit: ; preds = %latch | |
| %shftphi = phi i64 [ %shft, %latch ] | |
| br label %mergedexit | |
| mergedexit: ; preds = %latchexit, %headerexit | |
| %retval = phi i64 [ %addphi, %headerexit ], [ %shftphi, %latchexit ] | |
| ret i64 %retval | |
| } | |
| ; mergedexit has edges from loop exit blocks and a block outside the loop. | |
| define void @test2(i1 %cond, i32 %n) { | |
| ; CHECK-LABEL: @test2( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: br i1 [[COND:%.*]], label [[PREHEADER:%.*]], label [[MERGEDEXIT:%.*]] | |
| ; CHECK: preheader: | |
| ; CHECK-NEXT: [[TRIP:%.*]] = zext i32 [[N:%.*]] to i64 | |
| ; CHECK-NEXT: br label [[HEADER:%.*]] | |
| ; CHECK: header: | |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2, [[PREHEADER]] ], [ [[ADD_IV_3:%.*]], [[LATCH_3:%.*]] ] | |
| ; CHECK-NEXT: [[ADD_IV:%.*]] = add nuw nsw i64 [[IV]], 2 | |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[ADD_IV]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH:%.*]], label [[HEADEREXIT:%.*]] | |
| ; CHECK: latch: | |
| ; CHECK-NEXT: [[SHFT:%.*]] = ashr i64 [[ADD_IV]], 1 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[SHFT]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER_1:%.*]], label [[LATCHEXIT:%.*]] | |
| ; CHECK: header.1: | |
| ; CHECK-NEXT: [[ADD_IV_1:%.*]] = add nuw nsw i64 [[IV]], 4 | |
| ; CHECK-NEXT: [[CMP1_1:%.*]] = icmp samesign ult i64 [[ADD_IV_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_1]], label [[LATCH_1:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.1: | |
| ; CHECK-NEXT: [[SHFT_1:%.*]] = ashr i64 [[ADD_IV_1]], 1 | |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ult i64 [[SHFT_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_1]], label [[HEADER_2:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.2: | |
| ; CHECK-NEXT: [[ADD_IV_2:%.*]] = add nuw nsw i64 [[IV]], 6 | |
| ; CHECK-NEXT: [[CMP1_2:%.*]] = icmp samesign ult i64 [[ADD_IV_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_2]], label [[LATCH_2:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.2: | |
| ; CHECK-NEXT: [[SHFT_2:%.*]] = ashr i64 [[ADD_IV_2]], 1 | |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ult i64 [[SHFT_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_2]], label [[HEADER_3:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.3: | |
| ; CHECK-NEXT: [[ADD_IV_3]] = add nuw nsw i64 [[IV]], 8 | |
| ; CHECK-NEXT: [[CMP1_3:%.*]] = icmp samesign ult i64 [[ADD_IV_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_3]], label [[LATCH_3]], label [[HEADEREXIT]] | |
| ; CHECK: latch.3: | |
| ; CHECK-NEXT: [[SHFT_3:%.*]] = ashr i64 [[ADD_IV_3]], 1 | |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp ult i64 [[SHFT_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_3]], label [[HEADER]], label [[LATCHEXIT]], !llvm.loop [[LOOP2:![0-9]+]] | |
| ; CHECK: headerexit: | |
| ; CHECK-NEXT: br label [[MERGEDEXIT]] | |
| ; CHECK: latchexit: | |
| ; CHECK-NEXT: br label [[MERGEDEXIT]] | |
| ; CHECK: mergedexit: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| entry: | |
| br i1 %cond, label %preheader, label %mergedexit | |
| preheader: ; preds = %entry | |
| %trip = zext i32 %n to i64 | |
| br label %header | |
| header: ; preds = %latch, %preheader | |
| %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ] | |
| %add.iv = add nuw nsw i64 %iv, 2 | |
| %cmp1 = icmp ult i64 %add.iv, %trip | |
| br i1 %cmp1, label %latch, label %headerexit | |
| latch: ; preds = %header | |
| %shft = ashr i64 %add.iv, 1 | |
| %cmp2 = icmp ult i64 %shft, %trip | |
| br i1 %cmp2, label %header, label %latchexit | |
| headerexit: ; preds = %header | |
| br label %mergedexit | |
| latchexit: ; preds = %latch | |
| br label %mergedexit | |
| mergedexit: ; preds = %latchexit, %headerexit, %entry | |
| ret void | |
| } | |
| ; exitsucc is from loop exit block only. | |
| define i64 @test3(i32 %n) { | |
| ; CHECK-LABEL: @test3( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: br label [[PREHEADER:%.*]] | |
| ; CHECK: preheader: | |
| ; CHECK-NEXT: [[TRIP:%.*]] = zext i32 [[N:%.*]] to i64 | |
| ; CHECK-NEXT: br label [[HEADER:%.*]] | |
| ; CHECK: header: | |
| ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2, [[PREHEADER]] ], [ [[ADD_IV_3:%.*]], [[LATCH_3:%.*]] ] | |
| ; CHECK-NEXT: [[ADD_IV:%.*]] = add nuw nsw i64 [[IV]], 2 | |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[ADD_IV]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH:%.*]], label [[HEADEREXIT:%.*]] | |
| ; CHECK: latch: | |
| ; CHECK-NEXT: [[SHFT:%.*]] = ashr i64 [[ADD_IV]], 1 | |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[SHFT]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER_1:%.*]], label [[LATCHEXIT:%.*]] | |
| ; CHECK: header.1: | |
| ; CHECK-NEXT: [[ADD_IV_1:%.*]] = add nuw nsw i64 [[IV]], 4 | |
| ; CHECK-NEXT: [[CMP1_1:%.*]] = icmp samesign ult i64 [[ADD_IV_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_1]], label [[LATCH_1:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.1: | |
| ; CHECK-NEXT: [[SHFT_1:%.*]] = ashr i64 [[ADD_IV_1]], 1 | |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ult i64 [[SHFT_1]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_1]], label [[HEADER_2:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.2: | |
| ; CHECK-NEXT: [[ADD_IV_2:%.*]] = add nuw nsw i64 [[IV]], 6 | |
| ; CHECK-NEXT: [[CMP1_2:%.*]] = icmp samesign ult i64 [[ADD_IV_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_2]], label [[LATCH_2:%.*]], label [[HEADEREXIT]] | |
| ; CHECK: latch.2: | |
| ; CHECK-NEXT: [[SHFT_2:%.*]] = ashr i64 [[ADD_IV_2]], 1 | |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ult i64 [[SHFT_2]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_2]], label [[HEADER_3:%.*]], label [[LATCHEXIT]] | |
| ; CHECK: header.3: | |
| ; CHECK-NEXT: [[ADD_IV_3]] = add nuw nsw i64 [[IV]], 8 | |
| ; CHECK-NEXT: [[CMP1_3:%.*]] = icmp samesign ult i64 [[ADD_IV_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP1_3]], label [[LATCH_3]], label [[HEADEREXIT]] | |
| ; CHECK: latch.3: | |
| ; CHECK-NEXT: [[SHFT_3:%.*]] = ashr i64 [[ADD_IV_3]], 1 | |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp ult i64 [[SHFT_3]], [[TRIP]] | |
| ; CHECK-NEXT: br i1 [[CMP2_3]], label [[HEADER]], label [[LATCHEXIT]], !llvm.loop [[LOOP3:![0-9]+]] | |
| ; CHECK: headerexit: | |
| ; CHECK-NEXT: br label [[EXITSUCC:%.*]] | |
| ; CHECK: latchexit: | |
| ; CHECK-NEXT: [[SHFTPHI:%.*]] = phi i64 [ [[SHFT]], [[LATCH]] ], [ [[SHFT_1]], [[LATCH_1]] ], [ [[SHFT_2]], [[LATCH_2]] ], [ [[SHFT_3]], [[LATCH_3]] ] | |
| ; CHECK-NEXT: ret i64 [[SHFTPHI]] | |
| ; CHECK: exitsucc: | |
| ; CHECK-NEXT: ret i64 96 | |
| ; | |
| entry: | |
| br label %preheader | |
| preheader: ; preds = %bb | |
| %trip = zext i32 %n to i64 | |
| br label %header | |
| header: ; preds = %latch, %preheader | |
| %iv = phi i64 [ 2, %preheader ], [ %add.iv, %latch ] | |
| %add.iv = add nuw nsw i64 %iv, 2 | |
| %cmp1 = icmp ult i64 %add.iv, %trip | |
| br i1 %cmp1, label %latch, label %headerexit | |
| latch: ; preds = %header | |
| %shft = ashr i64 %add.iv, 1 | |
| %cmp2 = icmp ult i64 %shft, %trip | |
| br i1 %cmp2, label %header, label %latchexit | |
| headerexit: ; preds = %header | |
| br label %exitsucc | |
| latchexit: ; preds = %latch | |
| %shftphi = phi i64 [ %shft, %latch ] | |
| ret i64 %shftphi | |
| exitsucc: ; preds = %headerexit | |
| ret i64 96 | |
| } | |
| ; exit block (%default) has an exiting block and another exit block as predecessors. | |
| define void @test4(i16 %c3) { | |
| ; CHECK-LABEL: @test4( | |
| ; CHECK-NEXT: preheader: | |
| ; CHECK-NEXT: [[C1:%.*]] = zext i32 undef to i64 | |
| ; CHECK-NEXT: [[TMP0:%.*]] = freeze i64 [[C1]] | |
| ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], -1 | |
| ; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[TMP0]], 3 | |
| ; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i64 [[XTRAITER]], 0 | |
| ; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[HEADER_PROL_PREHEADER:%.*]], label [[HEADER_PROL_LOOPEXIT:%.*]] | |
| ; CHECK: header.prol.preheader: | |
| ; CHECK-NEXT: br label [[HEADER_PROL:%.*]] | |
| ; CHECK: header.prol: | |
| ; CHECK-NEXT: [[INDVARS_IV_PROL:%.*]] = phi i64 [ 0, [[HEADER_PROL_PREHEADER]] ], [ [[INDVARS_IV_NEXT_PROL:%.*]], [[LATCH_PROL:%.*]] ] | |
| ; CHECK-NEXT: [[PROL_ITER:%.*]] = phi i64 [ 0, [[HEADER_PROL_PREHEADER]] ], [ [[PROL_ITER_NEXT:%.*]], [[LATCH_PROL]] ] | |
| ; CHECK-NEXT: br label [[EXITING_PROL:%.*]] | |
| ; CHECK: exiting.prol: | |
| ; CHECK-NEXT: switch i16 [[C3:%.*]], label [[DEFAULT_LOOPEXIT_LOOPEXIT1:%.*]] [ | |
| ; CHECK-NEXT: i16 45, label [[OTHEREXIT_LOOPEXIT2:%.*]] | |
| ; CHECK-NEXT: i16 95, label [[LATCH_PROL]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: latch.prol: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_PROL]] = add nuw nsw i64 [[INDVARS_IV_PROL]], 1 | |
| ; CHECK-NEXT: [[C2_PROL:%.*]] = icmp ult i64 [[INDVARS_IV_NEXT_PROL]], [[C1]] | |
| ; CHECK-NEXT: [[PROL_ITER_NEXT]] = add i64 [[PROL_ITER]], 1 | |
| ; CHECK-NEXT: [[PROL_ITER_CMP:%.*]] = icmp ne i64 [[PROL_ITER_NEXT]], [[XTRAITER]] | |
| ; CHECK-NEXT: br i1 [[PROL_ITER_CMP]], label [[HEADER_PROL]], label [[HEADER_PROL_LOOPEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP4:![0-9]+]] | |
| ; CHECK: header.prol.loopexit.unr-lcssa: | |
| ; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_PROL]], [[LATCH_PROL]] ] | |
| ; CHECK-NEXT: br label [[HEADER_PROL_LOOPEXIT]] | |
| ; CHECK: header.prol.loopexit: | |
| ; CHECK-NEXT: [[INDVARS_IV_UNR:%.*]] = phi i64 [ 0, [[PREHEADER:%.*]] ], [ [[INDVARS_IV_UNR_PH]], [[HEADER_PROL_LOOPEXIT_UNR_LCSSA]] ] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 [[TMP1]], 3 | |
| ; CHECK-NEXT: br i1 [[TMP2]], label [[LATCHEXIT:%.*]], label [[PREHEADER_NEW:%.*]] | |
| ; CHECK: preheader.new: | |
| ; CHECK-NEXT: br label [[HEADER:%.*]] | |
| ; CHECK: header: | |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_UNR]], [[PREHEADER_NEW]] ], [ [[INDVARS_IV_NEXT_3:%.*]], [[LATCH_3:%.*]] ] | |
| ; CHECK-NEXT: br label [[EXITING:%.*]] | |
| ; CHECK: exiting: | |
| ; CHECK-NEXT: switch i16 [[C3]], label [[DEFAULT_LOOPEXIT_LOOPEXIT:%.*]] [ | |
| ; CHECK-NEXT: i16 45, label [[OTHEREXIT_LOOPEXIT:%.*]] | |
| ; CHECK-NEXT: i16 95, label [[LATCH:%.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: latch: | |
| ; CHECK-NEXT: br label [[EXITING_1:%.*]] | |
| ; CHECK: exiting.1: | |
| ; CHECK-NEXT: switch i16 [[C3]], label [[DEFAULT_LOOPEXIT_LOOPEXIT]] [ | |
| ; CHECK-NEXT: i16 45, label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK-NEXT: i16 95, label [[LATCH_1:%.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: latch.1: | |
| ; CHECK-NEXT: br label [[EXITING_2:%.*]] | |
| ; CHECK: exiting.2: | |
| ; CHECK-NEXT: switch i16 [[C3]], label [[DEFAULT_LOOPEXIT_LOOPEXIT]] [ | |
| ; CHECK-NEXT: i16 45, label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK-NEXT: i16 95, label [[LATCH_2:%.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: latch.2: | |
| ; CHECK-NEXT: br label [[EXITING_3:%.*]] | |
| ; CHECK: exiting.3: | |
| ; CHECK-NEXT: switch i16 [[C3]], label [[DEFAULT_LOOPEXIT_LOOPEXIT]] [ | |
| ; CHECK-NEXT: i16 45, label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK-NEXT: i16 95, label [[LATCH_3]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: latch.3: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_3]] = add nuw nsw i64 [[INDVARS_IV]], 4 | |
| ; CHECK-NEXT: [[C2_3:%.*]] = icmp samesign ult i64 [[INDVARS_IV_NEXT_3]], [[C1]] | |
| ; CHECK-NEXT: br i1 [[C2_3]], label [[HEADER]], label [[LATCHEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP5:![0-9]+]] | |
| ; CHECK: latchexit.unr-lcssa: | |
| ; CHECK-NEXT: br label [[LATCHEXIT]] | |
| ; CHECK: latchexit: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: default.loopexit.loopexit: | |
| ; CHECK-NEXT: br label [[DEFAULT_LOOPEXIT:%.*]] | |
| ; CHECK: default.loopexit.loopexit1: | |
| ; CHECK-NEXT: br label [[DEFAULT_LOOPEXIT]] | |
| ; CHECK: default.loopexit: | |
| ; CHECK-NEXT: br label [[DEFAULT:%.*]] | |
| ; CHECK: default: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: otherexit.loopexit: | |
| ; CHECK-NEXT: br label [[OTHEREXIT:%.*]] | |
| ; CHECK: otherexit.loopexit2: | |
| ; CHECK-NEXT: br label [[OTHEREXIT]] | |
| ; CHECK: otherexit: | |
| ; CHECK-NEXT: br label [[DEFAULT]] | |
| ; | |
| preheader: | |
| %c1 = zext i32 undef to i64 | |
| br label %header | |
| header: ; preds = %latch, %preheader | |
| %indvars.iv = phi i64 [ 0, %preheader ], [ %indvars.iv.next, %latch ] | |
| br label %exiting | |
| exiting: ; preds = %header | |
| switch i16 %c3, label %default [ | |
| i16 45, label %otherexit | |
| i16 95, label %latch | |
| ] | |
| latch: ; preds = %exiting | |
| %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 | |
| %c2 = icmp ult i64 %indvars.iv.next, %c1 | |
| br i1 %c2, label %header, label %latchexit | |
| latchexit: ; preds = %latch | |
| ret void | |
| default: ; preds = %otherexit, %exiting | |
| ret void | |
| otherexit: ; preds = %exiting | |
| br label %default | |
| } | |
| ; exit block (%exitB) has an exiting block and another exit block as predecessors. | |
| ; exiting block comes from inner loop. | |
| define void @test5() { | |
| ; CHECK-LABEL: @test5( | |
| ; CHECK-NEXT: bb: | |
| ; CHECK-NEXT: [[TMP:%.*]] = icmp sgt i32 undef, 79 | |
| ; CHECK-NEXT: br i1 [[TMP]], label [[OUTERLATCHEXIT:%.*]], label [[BB1:%.*]] | |
| ; CHECK: bb1: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 undef | |
| ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -1 | |
| ; CHECK-NEXT: [[XTRAITER:%.*]] = and i32 [[TMP0]], 3 | |
| ; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i32 [[XTRAITER]], 0 | |
| ; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[OUTERH_PROL_PREHEADER:%.*]], label [[OUTERH_PROL_LOOPEXIT:%.*]] | |
| ; CHECK: outerH.prol.preheader: | |
| ; CHECK-NEXT: br label [[OUTERH_PROL:%.*]] | |
| ; CHECK: outerH.prol: | |
| ; CHECK-NEXT: [[TMP4_PROL:%.*]] = phi i32 [ [[TMP6_PROL:%.*]], [[OUTERLATCH_PROL:%.*]] ], [ undef, [[OUTERH_PROL_PREHEADER]] ] | |
| ; CHECK-NEXT: [[PROL_ITER:%.*]] = phi i32 [ 0, [[OUTERH_PROL_PREHEADER]] ], [ [[PROL_ITER_NEXT:%.*]], [[OUTERLATCH_PROL]] ] | |
| ; CHECK-NEXT: br label [[INNERH_PROL:%.*]] | |
| ; CHECK: innerH.prol: | |
| ; CHECK-NEXT: [[C1_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_PROL]], label [[INNEREXITING_PROL:%.*]], label [[OTHEREXITB_LOOPEXIT1:%.*]] | |
| ; CHECK: innerexiting.prol: | |
| ; CHECK-NEXT: [[C2_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_PROL]], label [[INNERLATCH_PROL:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT2:%.*]] | |
| ; CHECK: innerLatch.prol: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_1_PROL:%.*]], label [[OUTERLATCH_PROL]] | |
| ; CHECK: innerH.1.prol: | |
| ; CHECK-NEXT: [[C1_1_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_1_PROL]], label [[INNEREXITING_1_PROL:%.*]], label [[OTHEREXITB_LOOPEXIT1]] | |
| ; CHECK: innerexiting.1.prol: | |
| ; CHECK-NEXT: [[C2_1_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_1_PROL]], label [[INNERLATCH_1_PROL:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT2]] | |
| ; CHECK: innerLatch.1.prol: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_2_PROL:%.*]], label [[OUTERLATCH_PROL]] | |
| ; CHECK: innerH.2.prol: | |
| ; CHECK-NEXT: [[C1_2_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_2_PROL]], label [[INNEREXITING_2_PROL:%.*]], label [[OTHEREXITB_LOOPEXIT1]] | |
| ; CHECK: innerexiting.2.prol: | |
| ; CHECK-NEXT: [[C2_2_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_2_PROL]], label [[INNERLATCH_2_PROL:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT2]] | |
| ; CHECK: innerLatch.2.prol: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_3_PROL:%.*]], label [[OUTERLATCH_PROL]] | |
| ; CHECK: innerH.3.prol: | |
| ; CHECK-NEXT: [[C1_3_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_3_PROL]], label [[INNEREXITING_3_PROL:%.*]], label [[OTHEREXITB_LOOPEXIT1]] | |
| ; CHECK: innerexiting.3.prol: | |
| ; CHECK-NEXT: [[C2_3_PROL:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_3_PROL]], label [[INNERLATCH_3_PROL:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT2]] | |
| ; CHECK: innerLatch.3.prol: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_PROL]], label [[OUTERLATCH_PROL]], !llvm.loop [[LOOP6:![0-9]+]] | |
| ; CHECK: outerLatch.prol: | |
| ; CHECK-NEXT: [[TMP6_PROL]] = add i32 [[TMP4_PROL]], 1 | |
| ; CHECK-NEXT: [[TMP7_PROL:%.*]] = icmp sgt i32 [[TMP6_PROL]], 79 | |
| ; CHECK-NEXT: [[PROL_ITER_NEXT]] = add i32 [[PROL_ITER]], 1 | |
| ; CHECK-NEXT: [[PROL_ITER_CMP:%.*]] = icmp ne i32 [[PROL_ITER_NEXT]], [[XTRAITER]] | |
| ; CHECK-NEXT: br i1 [[PROL_ITER_CMP]], label [[OUTERH_PROL]], label [[OUTERH_PROL_LOOPEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP7:![0-9]+]] | |
| ; CHECK: outerH.prol.loopexit.unr-lcssa: | |
| ; CHECK-NEXT: [[TMP4_UNR_PH:%.*]] = phi i32 [ [[TMP6_PROL]], [[OUTERLATCH_PROL]] ] | |
| ; CHECK-NEXT: br label [[OUTERH_PROL_LOOPEXIT]] | |
| ; CHECK: outerH.prol.loopexit: | |
| ; CHECK-NEXT: [[TMP4_UNR:%.*]] = phi i32 [ undef, [[BB1]] ], [ [[TMP4_UNR_PH]], [[OUTERH_PROL_LOOPEXIT_UNR_LCSSA]] ] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 3 | |
| ; CHECK-NEXT: br i1 [[TMP2]], label [[OUTERLATCHEXIT_LOOPEXIT:%.*]], label [[BB1_NEW:%.*]] | |
| ; CHECK: bb1.new: | |
| ; CHECK-NEXT: br label [[OUTERH:%.*]] | |
| ; CHECK: outerH: | |
| ; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP4_UNR]], [[BB1_NEW]] ], [ [[TMP6_3:%.*]], [[OUTERLATCH_3:%.*]] ] | |
| ; CHECK-NEXT: br label [[INNERH:%.*]] | |
| ; CHECK: innerH: | |
| ; CHECK-NEXT: [[C1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1]], label [[INNEREXITING:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT:%.*]] | |
| ; CHECK: innerexiting: | |
| ; CHECK-NEXT: [[C2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2]], label [[INNERLATCH:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT:%.*]] | |
| ; CHECK: innerLatch: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_1:%.*]], label [[OUTERLATCH:%.*]] | |
| ; CHECK: innerH.1: | |
| ; CHECK-NEXT: [[C1_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_1]], label [[INNEREXITING_1:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerexiting.1: | |
| ; CHECK-NEXT: [[C2_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_1]], label [[INNERLATCH_1:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerLatch.1: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_2:%.*]], label [[OUTERLATCH]] | |
| ; CHECK: innerH.2: | |
| ; CHECK-NEXT: [[C1_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_2]], label [[INNEREXITING_2:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerexiting.2: | |
| ; CHECK-NEXT: [[C2_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_2]], label [[INNERLATCH_2:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerLatch.2: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_3:%.*]], label [[OUTERLATCH]] | |
| ; CHECK: innerH.3: | |
| ; CHECK-NEXT: [[C1_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_3]], label [[INNEREXITING_3:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerexiting.3: | |
| ; CHECK-NEXT: [[C2_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_3]], label [[INNERLATCH_3:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: innerLatch.3: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH]], label [[OUTERLATCH]], !llvm.loop [[LOOP6]] | |
| ; CHECK: outerLatch: | |
| ; CHECK-NEXT: br label [[INNERH_14:%.*]] | |
| ; CHECK: innerH.14: | |
| ; CHECK-NEXT: [[C1_13:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_13]], label [[INNEREXITING_16:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT18:%.*]] | |
| ; CHECK: innerexiting.16: | |
| ; CHECK-NEXT: [[C2_15:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_15]], label [[INNERLATCH_17:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT19:%.*]] | |
| ; CHECK: innerLatch.17: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_1_1:%.*]], label [[OUTERLATCH_1:%.*]] | |
| ; CHECK: innerH.1.1: | |
| ; CHECK-NEXT: [[C1_1_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_1_1]], label [[INNEREXITING_1_1:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT18]] | |
| ; CHECK: innerexiting.1.1: | |
| ; CHECK-NEXT: [[C2_1_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_1_1]], label [[INNERLATCH_1_1:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT19]] | |
| ; CHECK: innerLatch.1.1: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_2_1:%.*]], label [[OUTERLATCH_1]] | |
| ; CHECK: innerH.2.1: | |
| ; CHECK-NEXT: [[C1_2_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_2_1]], label [[INNEREXITING_2_1:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT18]] | |
| ; CHECK: innerexiting.2.1: | |
| ; CHECK-NEXT: [[C2_2_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_2_1]], label [[INNERLATCH_2_1:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT19]] | |
| ; CHECK: innerLatch.2.1: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_3_1:%.*]], label [[OUTERLATCH_1]] | |
| ; CHECK: innerH.3.1: | |
| ; CHECK-NEXT: [[C1_3_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_3_1]], label [[INNEREXITING_3_1:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT18]] | |
| ; CHECK: innerexiting.3.1: | |
| ; CHECK-NEXT: [[C2_3_1:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_3_1]], label [[INNERLATCH_3_1:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT19]] | |
| ; CHECK: innerLatch.3.1: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_14]], label [[OUTERLATCH_1]], !llvm.loop [[LOOP6]] | |
| ; CHECK: outerLatch.1: | |
| ; CHECK-NEXT: br label [[INNERH_29:%.*]] | |
| ; CHECK: innerH.29: | |
| ; CHECK-NEXT: [[C1_28:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_28]], label [[INNEREXITING_211:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT20:%.*]] | |
| ; CHECK: innerexiting.211: | |
| ; CHECK-NEXT: [[C2_210:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_210]], label [[INNERLATCH_212:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT21:%.*]] | |
| ; CHECK: innerLatch.212: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_1_2:%.*]], label [[OUTERLATCH_2:%.*]] | |
| ; CHECK: innerH.1.2: | |
| ; CHECK-NEXT: [[C1_1_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_1_2]], label [[INNEREXITING_1_2:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT20]] | |
| ; CHECK: innerexiting.1.2: | |
| ; CHECK-NEXT: [[C2_1_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_1_2]], label [[INNERLATCH_1_2:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT21]] | |
| ; CHECK: innerLatch.1.2: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_2_2:%.*]], label [[OUTERLATCH_2]] | |
| ; CHECK: innerH.2.2: | |
| ; CHECK-NEXT: [[C1_2_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_2_2]], label [[INNEREXITING_2_2:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT20]] | |
| ; CHECK: innerexiting.2.2: | |
| ; CHECK-NEXT: [[C2_2_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_2_2]], label [[INNERLATCH_2_2:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT21]] | |
| ; CHECK: innerLatch.2.2: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_3_2:%.*]], label [[OUTERLATCH_2]] | |
| ; CHECK: innerH.3.2: | |
| ; CHECK-NEXT: [[C1_3_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_3_2]], label [[INNEREXITING_3_2:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT20]] | |
| ; CHECK: innerexiting.3.2: | |
| ; CHECK-NEXT: [[C2_3_2:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_3_2]], label [[INNERLATCH_3_2:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT21]] | |
| ; CHECK: innerLatch.3.2: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_29]], label [[OUTERLATCH_2]], !llvm.loop [[LOOP6]] | |
| ; CHECK: outerLatch.2: | |
| ; CHECK-NEXT: br label [[INNERH_314:%.*]] | |
| ; CHECK: innerH.314: | |
| ; CHECK-NEXT: [[C1_313:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_313]], label [[INNEREXITING_316:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT22:%.*]] | |
| ; CHECK: innerexiting.316: | |
| ; CHECK-NEXT: [[C2_315:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_315]], label [[INNERLATCH_317:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT23:%.*]] | |
| ; CHECK: innerLatch.317: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_1_3:%.*]], label [[OUTERLATCH_3]] | |
| ; CHECK: innerH.1.3: | |
| ; CHECK-NEXT: [[C1_1_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_1_3]], label [[INNEREXITING_1_3:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT22]] | |
| ; CHECK: innerexiting.1.3: | |
| ; CHECK-NEXT: [[C2_1_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_1_3]], label [[INNERLATCH_1_3:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT23]] | |
| ; CHECK: innerLatch.1.3: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_2_3:%.*]], label [[OUTERLATCH_3]] | |
| ; CHECK: innerH.2.3: | |
| ; CHECK-NEXT: [[C1_2_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_2_3]], label [[INNEREXITING_2_3:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT22]] | |
| ; CHECK: innerexiting.2.3: | |
| ; CHECK-NEXT: [[C2_2_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_2_3]], label [[INNERLATCH_2_3:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT23]] | |
| ; CHECK: innerLatch.2.3: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_3_3:%.*]], label [[OUTERLATCH_3]] | |
| ; CHECK: innerH.3.3: | |
| ; CHECK-NEXT: [[C1_3_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C1_3_3]], label [[INNEREXITING_3_3:%.*]], label [[OTHEREXITB_LOOPEXIT_LOOPEXIT22]] | |
| ; CHECK: innerexiting.3.3: | |
| ; CHECK-NEXT: [[C2_3_3:%.*]] = call i1 @unknown(i32 0) | |
| ; CHECK-NEXT: br i1 [[C2_3_3]], label [[INNERLATCH_3_3:%.*]], label [[EXITB_LOOPEXIT_LOOPEXIT_LOOPEXIT23]] | |
| ; CHECK: innerLatch.3.3: | |
| ; CHECK-NEXT: br i1 false, label [[INNERH_314]], label [[OUTERLATCH_3]], !llvm.loop [[LOOP6]] | |
| ; CHECK: outerLatch.3: | |
| ; CHECK-NEXT: [[TMP6_3]] = add i32 [[TMP4]], 4 | |
| ; CHECK-NEXT: [[TMP7_3:%.*]] = icmp sgt i32 [[TMP6_3]], 79 | |
| ; CHECK-NEXT: br i1 [[TMP7_3]], label [[OUTERLATCHEXIT_LOOPEXIT_UNR_LCSSA:%.*]], label [[OUTERH]], !llvm.loop [[LOOP8:![0-9]+]] | |
| ; CHECK: outerLatchExit.loopexit.unr-lcssa: | |
| ; CHECK-NEXT: br label [[OUTERLATCHEXIT_LOOPEXIT]] | |
| ; CHECK: outerLatchExit.loopexit: | |
| ; CHECK-NEXT: br label [[OUTERLATCHEXIT]] | |
| ; CHECK: outerLatchExit: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: exitB.loopexit.loopexit.loopexit: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT_LOOPEXIT:%.*]] | |
| ; CHECK: exitB.loopexit.loopexit.loopexit19: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: exitB.loopexit.loopexit.loopexit21: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: exitB.loopexit.loopexit.loopexit23: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT_LOOPEXIT]] | |
| ; CHECK: exitB.loopexit.loopexit: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT:%.*]] | |
| ; CHECK: exitB.loopexit.loopexit2: | |
| ; CHECK-NEXT: br label [[EXITB_LOOPEXIT]] | |
| ; CHECK: exitB.loopexit: | |
| ; CHECK-NEXT: br label [[EXITB:%.*]] | |
| ; CHECK: exitB: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: otherexitB.loopexit.loopexit: | |
| ; CHECK-NEXT: br label [[OTHEREXITB_LOOPEXIT:%.*]] | |
| ; CHECK: otherexitB.loopexit.loopexit18: | |
| ; CHECK-NEXT: br label [[OTHEREXITB_LOOPEXIT]] | |
| ; CHECK: otherexitB.loopexit.loopexit20: | |
| ; CHECK-NEXT: br label [[OTHEREXITB_LOOPEXIT]] | |
| ; CHECK: otherexitB.loopexit.loopexit22: | |
| ; CHECK-NEXT: br label [[OTHEREXITB_LOOPEXIT]] | |
| ; CHECK: otherexitB.loopexit: | |
| ; CHECK-NEXT: br label [[OTHEREXITB:%.*]] | |
| ; CHECK: otherexitB.loopexit1: | |
| ; CHECK-NEXT: br label [[OTHEREXITB]] | |
| ; CHECK: otherexitB: | |
| ; CHECK-NEXT: br label [[EXITB]] | |
| ; | |
| bb: | |
| %tmp = icmp sgt i32 undef, 79 | |
| br i1 %tmp, label %outerLatchExit, label %bb1 | |
| bb1: ; preds = %bb | |
| br label %outerH | |
| outerH: ; preds = %outerLatch, %bb1 | |
| %tmp4 = phi i32 [ %tmp6, %outerLatch ], [ undef, %bb1 ] | |
| br label %innerH | |
| innerH: ; preds = %innerLatch, %outerH | |
| %c1 = call i1 @unknown(i32 0) | |
| br i1 %c1, label %innerexiting, label %otherexitB | |
| innerexiting: ; preds = %innerH | |
| %c2 = call i1 @unknown(i32 0) | |
| br i1 %c2, label %innerLatch, label %exitB | |
| innerLatch: ; preds = %innerexiting | |
| %tmp13 = fcmp olt double undef, 2.000000e+00 | |
| br i1 %tmp13, label %innerH, label %outerLatch | |
| outerLatch: ; preds = %innerLatch | |
| %tmp6 = add i32 %tmp4, 1 | |
| %tmp7 = icmp sgt i32 %tmp6, 79 | |
| br i1 %tmp7, label %outerLatchExit, label %outerH | |
| outerLatchExit: ; preds = %outerLatch, %bb | |
| ret void | |
| exitB: ; preds = %innerexiting, %otherexitB | |
| ret void | |
| otherexitB: ; preds = %innerH | |
| br label %exitB | |
| } | |
| ; Blocks reachable from exits (not_zero44) have the IDom as the block within the loop (Header). | |
| ; Update the IDom to the preheader. | |
| define void @test6(i64 %start) { | |
| ; CHECK-LABEL: @test6( | |
| ; CHECK-NEXT: entry: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[START:%.*]], 2 | |
| ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP0]], i64 616) | |
| ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[SMAX]], -1 | |
| ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], [[START]] | |
| ; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP2]], 1 | |
| ; CHECK-NEXT: [[TMP4:%.*]] = add nuw i64 [[TMP3]], 1 | |
| ; CHECK-NEXT: [[TMP5:%.*]] = freeze i64 [[TMP4]] | |
| ; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP5]], -1 | |
| ; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[TMP5]], 3 | |
| ; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i64 [[XTRAITER]], 0 | |
| ; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[HEADER_PROL_PREHEADER:%.*]], label [[HEADER_PROL_LOOPEXIT:%.*]] | |
| ; CHECK: header.prol.preheader: | |
| ; CHECK-NEXT: br label [[HEADER_PROL:%.*]] | |
| ; CHECK: header.prol: | |
| ; CHECK-NEXT: [[INDVARS_IV_PROL:%.*]] = phi i64 [ [[START]], [[HEADER_PROL_PREHEADER]] ], [ [[INDVARS_IV_NEXT_PROL:%.*]], [[LATCH_PROL:%.*]] ] | |
| ; CHECK-NEXT: [[PROL_ITER:%.*]] = phi i64 [ 0, [[HEADER_PROL_PREHEADER]] ], [ [[PROL_ITER_NEXT:%.*]], [[LATCH_PROL]] ] | |
| ; CHECK-NEXT: [[IV_I32_PROL:%.*]] = trunc i64 [[INDVARS_IV_PROL]] to i32 | |
| ; CHECK-NEXT: [[C1_PROL:%.*]] = call i1 @unknown(i32 [[IV_I32_PROL]]) | |
| ; CHECK-NEXT: br i1 [[C1_PROL]], label [[LATCH_PROL]], label [[OTHEREXIT_LOOPEXIT1:%.*]] | |
| ; CHECK: latch.prol: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_PROL]] = add nsw i64 [[INDVARS_IV_PROL]], 2 | |
| ; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT_PROL]], 616 | |
| ; CHECK-NEXT: [[PROL_ITER_NEXT]] = add i64 [[PROL_ITER]], 1 | |
| ; CHECK-NEXT: [[PROL_ITER_CMP:%.*]] = icmp ne i64 [[PROL_ITER_NEXT]], [[XTRAITER]] | |
| ; CHECK-NEXT: br i1 [[PROL_ITER_CMP]], label [[HEADER_PROL]], label [[HEADER_PROL_LOOPEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP9:![0-9]+]] | |
| ; CHECK: header.prol.loopexit.unr-lcssa: | |
| ; CHECK-NEXT: [[INDVARS_IV_UNR_PH:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_PROL]], [[LATCH_PROL]] ] | |
| ; CHECK-NEXT: br label [[HEADER_PROL_LOOPEXIT]] | |
| ; CHECK: header.prol.loopexit: | |
| ; CHECK-NEXT: [[INDVARS_IV_UNR:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_UNR_PH]], [[HEADER_PROL_LOOPEXIT_UNR_LCSSA]] ] | |
| ; CHECK-NEXT: [[TMP8:%.*]] = icmp ult i64 [[TMP6]], 3 | |
| ; CHECK-NEXT: br i1 [[TMP8]], label [[LATCHEXIT:%.*]], label [[ENTRY_NEW:%.*]] | |
| ; CHECK: entry.new: | |
| ; CHECK-NEXT: br label [[HEADER:%.*]] | |
| ; CHECK: header: | |
| ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_UNR]], [[ENTRY_NEW]] ], [ [[INDVARS_IV_NEXT_3:%.*]], [[LATCH_3:%.*]] ] | |
| ; CHECK-NEXT: [[IV_I32:%.*]] = trunc i64 [[INDVARS_IV]] to i32 | |
| ; CHECK-NEXT: [[C1:%.*]] = call i1 @unknown(i32 [[IV_I32]]) | |
| ; CHECK-NEXT: br i1 [[C1]], label [[LATCH:%.*]], label [[OTHEREXIT_LOOPEXIT:%.*]] | |
| ; CHECK: latch: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nsw i64 [[INDVARS_IV]], 2 | |
| ; CHECK-NEXT: [[IV_I32_1:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 | |
| ; CHECK-NEXT: [[C1_1:%.*]] = call i1 @unknown(i32 [[IV_I32_1]]) | |
| ; CHECK-NEXT: br i1 [[C1_1]], label [[LATCH_1:%.*]], label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK: latch.1: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_1:%.*]] = add nsw i64 [[INDVARS_IV]], 4 | |
| ; CHECK-NEXT: [[IV_I32_2:%.*]] = trunc i64 [[INDVARS_IV_NEXT_1]] to i32 | |
| ; CHECK-NEXT: [[C1_2:%.*]] = call i1 @unknown(i32 [[IV_I32_2]]) | |
| ; CHECK-NEXT: br i1 [[C1_2]], label [[LATCH_2:%.*]], label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK: latch.2: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_2:%.*]] = add nsw i64 [[INDVARS_IV]], 6 | |
| ; CHECK-NEXT: [[IV_I32_3:%.*]] = trunc i64 [[INDVARS_IV_NEXT_2]] to i32 | |
| ; CHECK-NEXT: [[C1_3:%.*]] = call i1 @unknown(i32 [[IV_I32_3]]) | |
| ; CHECK-NEXT: br i1 [[C1_3]], label [[LATCH_3]], label [[OTHEREXIT_LOOPEXIT]] | |
| ; CHECK: latch.3: | |
| ; CHECK-NEXT: [[INDVARS_IV_NEXT_3]] = add nsw i64 [[INDVARS_IV]], 8 | |
| ; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT_3]], 616 | |
| ; CHECK-NEXT: br i1 [[TMP9]], label [[HEADER]], label [[LATCHEXIT_UNR_LCSSA:%.*]], !llvm.loop [[LOOP10:![0-9]+]] | |
| ; CHECK: latchexit.unr-lcssa: | |
| ; CHECK-NEXT: br label [[LATCHEXIT]] | |
| ; CHECK: latchexit: | |
| ; CHECK-NEXT: br label [[LATCHEXITSUCC:%.*]] | |
| ; CHECK: otherexit.loopexit: | |
| ; CHECK-NEXT: br label [[OTHEREXIT:%.*]] | |
| ; CHECK: otherexit.loopexit1: | |
| ; CHECK-NEXT: br label [[OTHEREXIT]] | |
| ; CHECK: otherexit: | |
| ; CHECK-NEXT: br label [[OTHEREXITSUCC:%.*]] | |
| ; CHECK: otherexitsucc: | |
| ; CHECK-NEXT: br label [[NOT_ZERO44:%.*]] | |
| ; CHECK: not_zero44: | |
| ; CHECK-NEXT: unreachable | |
| ; CHECK: latchexitsucc: | |
| ; CHECK-NEXT: br label [[NOT_ZERO44]] | |
| ; | |
| entry: | |
| br label %header | |
| header: ; preds = %latch, %entry | |
| %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %latch ] | |
| %iv.i32 = trunc i64 %indvars.iv to i32 | |
| %c1 = call i1 @unknown(i32 %iv.i32) | |
| br i1 %c1, label %latch, label %otherexit | |
| latch: ; preds = %header | |
| %indvars.iv.next = add nsw i64 %indvars.iv, 2 | |
| %0 = icmp slt i64 %indvars.iv.next, 616 | |
| br i1 %0, label %header, label %latchexit | |
| latchexit: ; preds = %latch | |
| br label %latchexitsucc | |
| otherexit: ; preds = %header | |
| br label %otherexitsucc | |
| otherexitsucc: ; preds = %otherexit | |
| br label %not_zero44 | |
| not_zero44: ; preds = %latchexitsucc, %otherexitsucc | |
| unreachable | |
| latchexitsucc: ; preds = %latchexit | |
| br label %not_zero44 | |
| } | |