1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -irce < %s -S | FileCheck %s 3; RUN: opt -passes='require<branch-prob>,irce' < %s -S | FileCheck %s 4 5; REQUIRES: asserts 6 7; IRCE creates the pre and post loop, and invokes the 8; canonicalizing these loops to LCSSA and loop-simplfy structure. Make sure that the update to the loopinfo does not 9; incorrectly change the header while canonicalizing these pre/post loops. We 10; were incorrectly updating LI when the split loop is a subloop as in the case below. 11source_filename = "correct-loop-info.ll" 12 13define void @baz() personality i32* ()* @ham { 14; CHECK-LABEL: @baz( 15; CHECK-NEXT: bb: 16; CHECK-NEXT: br label [[OUTERHEADER:%.*]] 17; CHECK: outerheader: 18; CHECK-NEXT: [[TMP:%.*]] = icmp slt i32 undef, 84 19; CHECK-NEXT: br i1 [[TMP]], label [[BB2:%.*]], label [[BB16:%.*]] 20; CHECK: bb2: 21; CHECK-NEXT: br i1 false, label [[INNERHEADER_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] 22; CHECK: innerheader.preloop.preheader: 23; CHECK-NEXT: br label [[INNERHEADER_PRELOOP:%.*]] 24; CHECK: mainloop: 25; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[INDVAR_END:%.*]], 0 26; CHECK-NEXT: br i1 [[TMP0]], label [[INNERHEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 27; CHECK: innerheader.preheader: 28; CHECK-NEXT: br label [[INNERHEADER:%.*]] 29; CHECK: innerheader: 30; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP6:%.*]], [[BB8:%.*]] ], [ [[TMP4_PRELOOP_COPY:%.*]], [[INNERHEADER_PREHEADER]] ] 31; CHECK-NEXT: invoke void @pluto() 32; CHECK-NEXT: to label [[BB5:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit.split-lp 33; CHECK: bb5: 34; CHECK-NEXT: [[TMP6]] = add i32 [[TMP4]], 1 35; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 1 36; CHECK-NEXT: br i1 true, label [[BB8]], label [[EXIT3_LOOPEXIT5:%.*]] 37; CHECK: bb8: 38; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i32 [[TMP6]], 84 39; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP6]], 0 40; CHECK-NEXT: br i1 [[TMP1]], label [[INNERHEADER]], label [[MAIN_EXIT_SELECTOR:%.*]] 41; CHECK: main.exit.selector: 42; CHECK-NEXT: [[TMP6_LCSSA:%.*]] = phi i32 [ [[TMP6]], [[BB8]] ] 43; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP6_LCSSA]], 84 44; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[BB13:%.*]] 45; CHECK: main.pseudo.exit: 46; CHECK-NEXT: [[TMP4_COPY:%.*]] = phi i32 [ [[TMP4_PRELOOP_COPY]], [[MAINLOOP:%.*]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 47; CHECK-NEXT: [[INDVAR_END1:%.*]] = phi i32 [ [[INDVAR_END]], [[MAINLOOP]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 48; CHECK-NEXT: br label [[POSTLOOP:%.*]] 49; CHECK: outer_exiting.loopexit: 50; CHECK-NEXT: [[LPAD_LOOPEXIT:%.*]] = landingpad { i8*, i32 } 51; CHECK-NEXT: cleanup 52; CHECK-NEXT: br label [[OUTER_EXITING:%.*]] 53; CHECK: outer_exiting.loopexit.split-lp.loopexit: 54; CHECK-NEXT: [[LPAD_LOOPEXIT2:%.*]] = landingpad { i8*, i32 } 55; CHECK-NEXT: cleanup 56; CHECK-NEXT: br label %outer_exiting.loopexit.split-lp 57; CHECK: outer_exiting.loopexit.split-lp.loopexit.split-lp: 58; CHECK-NEXT: %lpad.loopexit.split-lp3 = landingpad { i8*, i32 } 59; CHECK-NEXT: cleanup 60; CHECK-NEXT: br label %outer_exiting.loopexit.split-lp 61; CHECK: outer_exiting.loopexit.split-lp: 62; CHECK-NEXT: br label [[OUTER_EXITING]] 63; CHECK: outer_exiting: 64; CHECK-NEXT: switch i32 undef, label [[EXIT2:%.*]] [ 65; CHECK-NEXT: i32 142, label [[BB14:%.*]] 66; CHECK-NEXT: i32 448, label [[EXIT:%.*]] 67; CHECK-NEXT: ] 68; CHECK: exit3.loopexit: 69; CHECK-NEXT: br label [[EXIT3:%.*]] 70; CHECK: exit3.loopexit4: 71; CHECK-NEXT: br label [[EXIT3]] 72; CHECK: exit3.loopexit5: 73; CHECK-NEXT: br label [[EXIT3]] 74; CHECK: exit3: 75; CHECK-NEXT: ret void 76; CHECK: bb13.loopexit: 77; CHECK-NEXT: br label [[BB13]] 78; CHECK: bb13: 79; CHECK-NEXT: unreachable 80; CHECK: bb14: 81; CHECK-NEXT: br label [[OUTERHEADER]] 82; CHECK: exit: 83; CHECK-NEXT: ret void 84; CHECK: bb16: 85; CHECK-NEXT: ret void 86; CHECK: exit2: 87; CHECK-NEXT: ret void 88; CHECK: innerheader.preloop: 89; CHECK-NEXT: [[TMP4_PRELOOP:%.*]] = phi i32 [ [[TMP6_PRELOOP:%.*]], [[BB8_PRELOOP:%.*]] ], [ undef, [[INNERHEADER_PRELOOP_PREHEADER]] ] 90; CHECK-NEXT: invoke void @pluto() 91; CHECK-NEXT: to label [[BB5_PRELOOP:%.*]] unwind label [[OUTER_EXITING_LOOPEXIT:%.*]] 92; CHECK: bb5.preloop: 93; CHECK-NEXT: [[TMP6_PRELOOP]] = add i32 [[TMP4_PRELOOP]], 1 94; CHECK-NEXT: [[TMP7_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 1 95; CHECK-NEXT: br i1 [[TMP7_PRELOOP]], label [[BB8_PRELOOP]], label [[EXIT3_LOOPEXIT:%.*]] 96; CHECK: bb8.preloop: 97; CHECK-NEXT: [[TMP9_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 84 98; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], -1 99; CHECK-NEXT: br i1 [[TMP3]], label [[INNERHEADER_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop !0, !irce.loop.clone !5 100; CHECK: preloop.exit.selector: 101; CHECK-NEXT: [[TMP6_PRELOOP_LCSSA:%.*]] = phi i32 [ [[TMP6_PRELOOP]], [[BB8_PRELOOP]] ] 102; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i32 [[TMP6_PRELOOP_LCSSA]], 84 103; CHECK-NEXT: br i1 [[TMP4]], label [[PRELOOP_PSEUDO_EXIT]], label [[BB13]] 104; CHECK: preloop.pseudo.exit: 105; CHECK-NEXT: [[TMP4_PRELOOP_COPY]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 106; CHECK-NEXT: [[INDVAR_END]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 107; CHECK-NEXT: br label [[MAINLOOP]] 108; CHECK: postloop: 109; CHECK-NEXT: br label [[INNERHEADER_POSTLOOP:%.*]] 110; CHECK: innerheader.postloop: 111; CHECK-NEXT: [[TMP4_POSTLOOP:%.*]] = phi i32 [ [[TMP6_POSTLOOP:%.*]], [[BB8_POSTLOOP:%.*]] ], [ [[TMP4_COPY]], [[POSTLOOP]] ] 112; CHECK-NEXT: invoke void @pluto() 113; CHECK-NEXT: to label [[BB5_POSTLOOP:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit 114; CHECK: bb5.postloop: 115; CHECK-NEXT: [[TMP6_POSTLOOP]] = add i32 [[TMP4_POSTLOOP]], 1 116; CHECK-NEXT: [[TMP7_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 1 117; CHECK-NEXT: br i1 [[TMP7_POSTLOOP]], label [[BB8_POSTLOOP]], label [[EXIT3_LOOPEXIT4:%.*]] 118; CHECK: bb8.postloop: 119; CHECK-NEXT: [[TMP9_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 84 120; CHECK-NEXT: br i1 [[TMP9_POSTLOOP]], label [[INNERHEADER_POSTLOOP]], label [[BB13_LOOPEXIT:%.*]], !llvm.loop !6, !irce.loop.clone !5 121; 122bb: 123 br label %outerheader 124 125outerheader: ; preds = %bb14, %bb 126 %tmp = icmp slt i32 undef, 84 127 br i1 %tmp, label %bb2, label %bb16 128 129bb2: ; preds = %outerheader 130 br label %innerheader 131 132innerheader: ; preds = %bb8, %bb2 133 %tmp4 = phi i32 [ %tmp6, %bb8 ], [ undef, %bb2 ] 134 invoke void @pluto() 135 to label %bb5 unwind label %outer_exiting 136 137bb5: ; preds = %innerheader 138 %tmp6 = add i32 %tmp4, 1 139 %tmp7 = icmp slt i32 %tmp6, 1 140 br i1 %tmp7, label %bb8, label %exit3 141 142bb8: ; preds = %bb5 143 %tmp9 = icmp slt i32 %tmp6, 84 144 br i1 %tmp9, label %innerheader, label %bb13 145 146outer_exiting: ; preds = %innerheader 147 %tmp11 = landingpad { i8*, i32 } 148 cleanup 149 switch i32 undef, label %exit2 [ 150 i32 142, label %bb14 151 i32 448, label %exit 152 ] 153 154exit3: ; preds = %bb5 155 ret void 156 157bb13: ; preds = %bb8 158 unreachable 159 160bb14: ; preds = %outer_exiting 161 br label %outerheader 162 163exit: ; preds = %outer_exiting 164 ret void 165 166bb16: ; preds = %outerheader 167 ret void 168 169exit2: ; preds = %outer_exiting 170 ret void 171} 172 173declare i32* @ham() 174 175declare void @pluto() 176 177!0 = distinct !{!0, !1, !2, !3, !4} 178!1 = !{!"llvm.loop.unroll.disable"} 179!2 = !{!"llvm.loop.vectorize.enable", i1 false} 180!3 = !{!"llvm.loop.licm_versioning.disable"} 181!4 = !{!"llvm.loop.distribute.enable", i1 false} 182!5 = !{} 183!6 = distinct !{!6, !1, !2, !3, !4} 184