From: Florian Hahn Date: Mon, 19 Dec 2016 17:13:37 +0000 (+0000) Subject: [LoopVersioning] Require loop-simplify form for loop versioning. X-Git-Tag: llvmorg-4.0.0-rc1~1692 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2e03213f90b0c443a4f3415757e8893d70420a85;p=platform%2Fupstream%2Fllvm.git [LoopVersioning] Require loop-simplify form for loop versioning. Summary: Requiring loop-simplify form for loop versioning ensures that the runtime check block always dominates the exit block. This patch closes #30958 (https://llvm.org/bugs/show_bug.cgi?id=30958). Reviewers: silviu.baranga, hfinkel, anemet, ashutosh.nema Subscribers: ashutosh.nema, mzolotukhin, efriedma, hfinkel, llvm-commits Differential Revision: https://reviews.llvm.org/D27469 llvm-svn: 290116 --- diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp index 1db8caa..1da0fd8 100644 --- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp @@ -606,11 +606,13 @@ public: 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); diff --git a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp index 8e83c47..08e7acd 100644 --- a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp +++ b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -517,6 +517,11 @@ public: 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. diff --git a/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp b/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp index aa09f89..c23d891b 100644 --- a/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp +++ b/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp @@ -218,9 +218,10 @@ private: /// \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 @@ bool LoopVersioningLICM::legalLoopStructure() { 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); diff --git a/llvm/lib/Transforms/Utils/LoopVersioning.cpp b/llvm/lib/Transforms/Utils/LoopVersioning.cpp index b3c6169..29756d9 100644 --- a/llvm/lib/Transforms/Utils/LoopVersioning.cpp +++ b/llvm/lib/Transforms/Utils/LoopVersioning.cpp @@ -36,7 +36,7 @@ LoopVersioning::LoopVersioning(const LoopAccessInfo &LAI, Loop *L, LoopInfo *LI, : 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 @@ public: 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(); diff --git a/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll b/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll index be44fe2b4..63f63997 100644 --- a/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll +++ b/llvm/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 diff --git a/llvm/test/Transforms/LoopDistribute/diagnostics.ll b/llvm/test/Transforms/LoopDistribute/diagnostics.ll index 9c0d915..ada2436 100644 --- a/llvm/test/Transforms/LoopDistribute/diagnostics.ll +++ b/llvm/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: diff --git a/llvm/test/Transforms/LoopVectorize/diag-with-hotness-info.ll b/llvm/test/Transforms/LoopVectorize/diag-with-hotness-info.ll index 04bd5df..43bf9ce 100644 --- a/llvm/test/Transforms/LoopVectorize/diag-with-hotness-info.ll +++ b/llvm/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 diff --git a/llvm/test/Transforms/LoopVersioning/exit-block-dominates-rt-check-block.ll b/llvm/test/Transforms/LoopVersioning/exit-block-dominates-rt-check-block.ll new file mode 100644 index 0000000..51bfb28 --- /dev/null +++ b/llvm/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: diff --git a/llvm/test/Transforms/LoopVersioning/noalias-version-twice.ll b/llvm/test/Transforms/LoopVersioning/noalias-version-twice.ll index 81ec0c0..50f3616 100644 --- a/llvm/test/Transforms/LoopVersioning/noalias-version-twice.ll +++ b/llvm/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