Index: lib/Transforms/Scalar/LoopDistribute.cpp =================================================================== --- lib/Transforms/Scalar/LoopDistribute.cpp +++ lib/Transforms/Scalar/LoopDistribute.cpp @@ -606,11 +606,13 @@ DEBUG(dbgs() << "\nLDist: In \"" << L->getHeader()->getParent()->getName() << "\" checking " << *L << "\n"); - BasicBlock *PH = L->getLoopPreheader(); - if (!PH) - return fail("NoHeader", "no preheader"); if (!L->getExitBlock()) return fail("MultipleExitBlocks", "multiple exit blocks"); + if (!L->isLoopSimplifyForm()) + return fail("NotLoopSimplifyForm", + "loop is not in loop-simplify form"); + + BasicBlock *PH = L->getLoopPreheader(); // LAA will check that we only have a single exiting block. LAI = &GetLAA(*L); Index: lib/Transforms/Scalar/LoopLoadElimination.cpp =================================================================== --- lib/Transforms/Scalar/LoopLoadElimination.cpp +++ lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -517,6 +517,11 @@ return false; } + if (!L->isLoopSimplifyForm()) { + DEBUG(dbgs() << "Loop is not is loop-simplify form"); + return false; + } + // Point of no-return, start the transformation. First, version the loop // if necessary. Index: lib/Transforms/Scalar/LoopVersioningLICM.cpp =================================================================== --- lib/Transforms/Scalar/LoopVersioningLICM.cpp +++ lib/Transforms/Scalar/LoopVersioningLICM.cpp @@ -218,9 +218,10 @@ /// \brief Check loop structure and confirms it's good for LoopVersioningLICM. bool LoopVersioningLICM::legalLoopStructure() { - // Loop must have a preheader, if not return false. - if (!CurLoop->getLoopPreheader()) { - DEBUG(dbgs() << " loop preheader is missing\n"); + // Loop must be in loop simplify form. + if (!CurLoop->isLoopSimplifyForm()) { + DEBUG( + dbgs() << " loop is not in loop-simplify form.\n"); return false; } // Loop should be innermost loop, if not return false. @@ -256,11 +257,6 @@ DEBUG(dbgs() << " loop depth is more then threshold\n"); return false; } - // Loop should have a dedicated exit block, if not return false. - if (!CurLoop->hasDedicatedExits()) { - DEBUG(dbgs() << " loop does not has dedicated exit blocks\n"); - return false; - } // We need to be able to compute the loop trip count in order // to generate the bound checks. const SCEV *ExitCount = SE->getBackedgeTakenCount(CurLoop); Index: lib/Transforms/Utils/LoopVersioning.cpp =================================================================== --- lib/Transforms/Utils/LoopVersioning.cpp +++ lib/Transforms/Utils/LoopVersioning.cpp @@ -36,7 +36,7 @@ : VersionedLoop(L), NonVersionedLoop(nullptr), LAI(LAI), LI(LI), DT(DT), SE(SE) { assert(L->getExitBlock() && "No single exit block"); - assert(L->getLoopPreheader() && "No preheader"); + assert(L->isLoopSimplifyForm() && "Loop is not in loop-simplify form"); if (UseLAIChecks) { setAliasChecks(LAI.getRuntimePointerChecking()->getChecks()); setSCEVChecks(LAI.getPSE().getUnionPredicate()); @@ -278,8 +278,8 @@ bool Changed = false; for (Loop *L : Worklist) { const LoopAccessInfo &LAI = LAA->getInfo(L); - if (LAI.getNumRuntimePointerChecks() || - !LAI.getPSE().getUnionPredicate().isAlwaysTrue()) { + if (L->isLoopSimplifyForm() && (LAI.getNumRuntimePointerChecks() || + !LAI.getPSE().getUnionPredicate().isAlwaysTrue())) { LoopVersioning LVer(LAI, L, LI, DT, SE); LVer.versionLoop(); LVer.annotateLoopWithNoAlias(); Index: test/Transforms/LoopDistribute/diagnostics-with-hotness.ll =================================================================== --- test/Transforms/LoopDistribute/diagnostics-with-hotness.ll +++ test/Transforms/LoopDistribute/diagnostics-with-hotness.ll @@ -1,14 +1,14 @@ -; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: opt -loop-simplify -loop-distribute -S -pass-remarks-missed=loop-distribute \ ; RUN: -pass-remarks-analysis=loop-distribute \ ; RUN: -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS -; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: opt -loop-simplify -loop-distribute -S -pass-remarks-missed=loop-distribute \ ; RUN: -pass-remarks-analysis=loop-distribute \ ; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS -; RUN: opt -passes='require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ +; RUN: opt -passes='loop-simplify,require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ ; RUN: -pass-remarks-analysis=loop-distribute \ ; RUN: -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS -; RUN: opt -passes='require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ +; RUN: opt -passes='loop-simplify,require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ ; RUN: -pass-remarks-analysis=loop-distribute \ ; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS Index: test/Transforms/LoopDistribute/diagnostics.ll =================================================================== --- test/Transforms/LoopDistribute/diagnostics.ll +++ test/Transforms/LoopDistribute/diagnostics.ll @@ -1,10 +1,13 @@ -; RUN: opt -loop-distribute -S < %s 2>&1 \ +; RUN: opt -loop-simplify -loop-distribute -S < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=NO_REMARKS -; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute < %s 2>&1 \ +; RUN: opt -loop-simplify -loop-distribute -S \ +; RUN: -pass-remarks-missed=loop-distribute < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=MISSED_REMARKS -; RUN: opt -loop-distribute -S -pass-remarks-analysis=loop-distribute < %s 2>&1 \ +; RUN: opt -loop-simplify -loop-distribute -S \ +; RUN: -pass-remarks-analysis=loop-distribute < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=ANALYSIS_REMARKS -; RUN: opt -loop-distribute -S -pass-remarks=loop-distribute < %s 2>&1 \ +; RUN: opt -loop-simplify -loop-distribute -S \ +; RUN: -pass-remarks=loop-distribute < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=REMARKS ; This is the input program: Index: test/Transforms/LoopVectorize/diag-with-hotness-info.ll =================================================================== --- test/Transforms/LoopVectorize/diag-with-hotness-info.ll +++ test/Transforms/LoopVectorize/diag-with-hotness-info.ll @@ -10,7 +10,8 @@ ; RUN: -pass-remarks-with-hotness < %s 2>&1 | \ ; RUN: FileCheck -check-prefix=HOTNESS -check-prefix=BOTH %s -; RUN: opt -S -passes=loop-vectorize -pass-remarks-missed=loop-vectorize < %s 2>&1 | \ +; RUN: opt -S -passes=loop-vectorize \ +; RUN: -pass-remarks-missed=loop-vectorize < %s 2>&1 | \ ; RUN: FileCheck -check-prefix=NO_HOTNESS -check-prefix=BOTH %s Index: test/Transforms/LoopVersioning/exit-block-dominates-rt-check-block.ll =================================================================== --- /dev/null +++ test/Transforms/LoopVersioning/exit-block-dominates-rt-check-block.ll @@ -0,0 +1,38 @@ +; This test ensures loop versioning does not produce an invalid dominator tree +; if the exit block of the loop (bb0) dominates the runtime check block +; (bb1 will become the runtime check block). + +; RUN: opt -loop-distribute -verify-dom-info -S -o - %s > %t +; RUN: opt -loop-simplify -loop-distribute -verify-dom-info -S -o - %s > %t +; RUN: FileCheck --check-prefix CHECK-VERSIONING -input-file %t %s + +; RUN: opt -loop-versioning -verify-dom-info -S -o - %s > %t +; RUN: opt -loop-simplify -loop-versioning -verify-dom-info -S -o - %s > %t +; RUN: FileCheck --check-prefix CHECK-VERSIONING -input-file %t %s + +@c1 = external global i16 + +define void @f(i16 %a) { + br label %bb0 + +bb0: + br label %bb1 + +bb1: + %tmp1 = load i16, i16* @c1 + br label %bb2 + +bb2: + %tmp2 = phi i16 [ %tmp1, %bb1 ], [ %tmp3, %bb2 ] + %tmp4 = getelementptr inbounds [1 x i32], [1 x i32]* undef, i32 0, i32 4 + store i32 1, i32* %tmp4 + %tmp5 = getelementptr inbounds [1 x i32], [1 x i32]* undef, i32 0, i32 9 + store i32 0, i32* %tmp5 + %tmp3 = add i16 %tmp2, 1 + store i16 %tmp2, i16* @c1 + %tmp6 = icmp sle i16 %tmp3, 0 + br i1 %tmp6, label %bb2, label %bb0 +} + +; Simple check to make sure loop versioning happened. +; CHECK-VERSIONING: bb2.lver.check: Index: test/Transforms/LoopVersioning/noalias-version-twice.ll =================================================================== --- test/Transforms/LoopVersioning/noalias-version-twice.ll +++ test/Transforms/LoopVersioning/noalias-version-twice.ll @@ -1,4 +1,5 @@ -; RUN: opt -basicaa -loop-distribute -scoped-noalias -loop-versioning -S < %s | FileCheck %s +; RUN: opt -basicaa -loop-distribute -loop-simplify -scoped-noalias \ +; RUN: -loop-versioning -S < %s | FileCheck %s ; Test the metadata generated when versioning an already versioned loop. Here ; we invoke loop distribution to perform the first round of versioning. It