Index: lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp =================================================================== --- lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -1371,28 +1371,35 @@ DT.recalculate(F); + // We need to first add all the pre and post loop blocks into the loop + // structures (as part of createClonedLoopStructure), and then update the + // LCSSA form and LoopSimplifyForm. This is necessary for correctly updating + // LI when LoopSimplifyForm is generated. + Loop *PreL = nullptr, *PostL = nullptr; if (!PreLoop.Blocks.empty()) { - auto *L = createClonedLoopStructure( + PreL = createClonedLoopStructure( &OriginalLoop, OriginalLoop.getParentLoop(), PreLoop.Map); - formLCSSARecursively(*L, DT, &LI, &SE); - simplifyLoop(L, &DT, &LI, &SE, nullptr, true); - // Pre loops are slow paths, we do not need to perform any loop - // optimizations on them. - DisableAllLoopOptsOnLoop(*L); } if (!PostLoop.Blocks.empty()) { - auto *L = createClonedLoopStructure( + PostL = createClonedLoopStructure( &OriginalLoop, OriginalLoop.getParentLoop(), PostLoop.Map); + } + + // This function canonicalizes the loop into Loop-Simplify and LCSSA forms. + auto CanonicalizeLoop = [&] (Loop *L, bool IsOriginalLoop) { + if (!L) + return; formLCSSARecursively(*L, DT, &LI, &SE); simplifyLoop(L, &DT, &LI, &SE, nullptr, true); - // Post loops are slow paths, we do not need to perform any loop + // Pre/post loops are slow paths, we do not need to perform any loop // optimizations on them. - DisableAllLoopOptsOnLoop(*L); - } - - formLCSSARecursively(OriginalLoop, DT, &LI, &SE); - simplifyLoop(&OriginalLoop, &DT, &LI, &SE, nullptr, true); + if (!IsOriginalLoop) + DisableAllLoopOptsOnLoop(*L); + }; + CanonicalizeLoop(PreL, false); + CanonicalizeLoop(PostL, false); + CanonicalizeLoop(&OriginalLoop, true); return true; } Index: test/Transforms/IRCE/correct-loop-info.ll =================================================================== --- /dev/null +++ test/Transforms/IRCE/correct-loop-info.ll @@ -0,0 +1,65 @@ +; RUN: opt -irce < %s + +; REQUIRES: asserts + +; IRCE creates the pre and post loop, and invokes the +; canonicalizing these loops to LCSSA and loop-simplfy structure. Make sure that the update to the loopinfo does not +; incorrectly change the header while canonicalizing these pre/post loops. We +; were incorrectly updating LI when the split loop is a subloop as in the case below. +source_filename = "correct-loop-info.ll" + +define void @baz() personality i32* ()* @ham { +bb: + br label %outerheader + +outerheader: ; preds = %bb14, %bb + %tmp = icmp slt i32 undef, 84 + br i1 %tmp, label %bb2, label %bb16 + +bb2: ; preds = %outerheader + br label %innerheader + +innerheader: ; preds = %bb8, %bb2 + %tmp4 = phi i32 [ %tmp6, %bb8 ], [ undef, %bb2 ] + invoke void @pluto() + to label %bb5 unwind label %outer_exiting + +bb5: ; preds = %innerheader + %tmp6 = add i32 %tmp4, 1 + %tmp7 = icmp ult i32 %tmp6, 0 + br i1 %tmp7, label %bb8, label %exit3 + +bb8: ; preds = %bb5 + %tmp9 = icmp slt i32 %tmp6, 84 + br i1 %tmp9, label %innerheader, label %bb13 + +outer_exiting: ; preds = %innerheader + %tmp11 = landingpad { i8*, i32 } + cleanup + switch i32 undef, label %exit2 [ + i32 142, label %bb14 + i32 448, label %exit + ] + +exit3: ; preds = %bb5 + ret void + +bb13: ; preds = %bb8 + unreachable + +bb14: ; preds = %outer_exiting + br label %outerheader + +exit: ; preds = %outer_exiting + ret void + +bb16: ; preds = %outerheader + ret void + +exit2: ; preds = %outer_exiting + ret void +} + +declare i32* @ham() + +declare void @pluto()