Index: llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -51,6 +51,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Utils/LCSSA.h" namespace llvm { @@ -248,10 +249,18 @@ class FunctionToLoopPassAdaptor : public PassInfoMixin> { public: - explicit FunctionToLoopPassAdaptor(LoopPassT Pass) : Pass(std::move(Pass)) {} + explicit FunctionToLoopPassAdaptor(LoopPassT Pass) : Pass(std::move(Pass)) { + LoopCanonicalizationFPM.addPass(LCSSAPass()); + } /// \brief Runs the loop passes across every loop in the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + // Before we even compute any loop analyses, first run a miniature function + // pass pipeline to put loops into their canonical form. Note that we can + // directly build up function analyses after this as the function pass + // manager handles all the invalidation at that layer. + PreservedAnalyses PA = LoopCanonicalizationFPM.run(F, AM); + // Setup the loop analysis manager from its proxy. LoopAnalysisManager &LAM = AM.getResult(F).getManager(); @@ -260,7 +269,7 @@ // If there are no loops, there is nothing to do here. if (LI.empty()) - return PreservedAnalyses::all(); + return PA; // Get the analysis results needed by loop passes. LoopStandardAnalysisResults LAR = {AM.getResult(F), @@ -271,8 +280,6 @@ AM.getResult(F), AM.getResult(F)}; - PreservedAnalyses PA = PreservedAnalyses::all(); - // A postorder worklist of loops to process. SmallPriorityWorklist Worklist; @@ -294,8 +301,15 @@ // Reset the update structure for this loop. Updater.CurrentL = L; Updater.SkipCurrentLoop = false; + #ifndef NDEBUG + // Save a parent loop pointer for asserts. Updater.ParentL = L->getParentLoop(); + + // Verify the loop structure and LCSSA form before visiting the loop. + L->verifyLoop(); + assert(L->isRecursivelyLCSSAForm(LAR.DT, LI) && + "Loops must remain in LCSSA form!"); #endif PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater); @@ -335,6 +349,8 @@ private: LoopPassT Pass; + + FunctionPassManager LoopCanonicalizationFPM; }; /// \brief A function to deduce a loop pass type and wrap it in the templated Index: llvm/trunk/test/Analysis/IVUsers/quadradic-exit-value.ll =================================================================== --- llvm/trunk/test/Analysis/IVUsers/quadradic-exit-value.ll +++ llvm/trunk/test/Analysis/IVUsers/quadradic-exit-value.ll @@ -5,7 +5,7 @@ ; passes *always* work on LCSSA. This should stop using a different set of ; checks at that point. -; RUN: opt < %s -analyze -iv-users | FileCheck %s +; RUN: opt < %s -analyze -iv-users | FileCheck %s --check-prefixes=CHECK,CHECK-NO-LCSSA ; RUN: opt < %s -disable-output -passes='print' 2>&1 | FileCheck %s ; Provide legal integer types. @@ -14,7 +14,7 @@ ; The value of %r is dependent on a polynomial iteration expression. ; ; CHECK-LABEL: IV Users for loop %foo.loop -; CHECK: {1,+,3,+,2}<%foo.loop> +; CHECK-NO-LCSSA: {1,+,3,+,2}<%foo.loop> define i64 @foo(i64 %n) { entry: br label %foo.loop @@ -36,7 +36,7 @@ ; sure they aren't marked as post-inc users. ; ; CHECK-LABEL: IV Users for loop %test2.loop -; CHECK: %sext.us = {0,+,(16777216 + (-16777216 * %sub.us)),+,33554432}<%test2.loop> in %f = ashr i32 %sext.us, 24 +; CHECK-NO-LCSSA: %sext.us = {0,+,(16777216 + (-16777216 * %sub.us)),+,33554432}<%test2.loop> in %f = ashr i32 %sext.us, 24 define i32 @test2() { entry: br label %test2.loop Index: llvm/trunk/test/Other/new-pass-manager.ll =================================================================== --- llvm/trunk/test/Other/new-pass-manager.ll +++ llvm/trunk/test/Other/new-pass-manager.ll @@ -539,9 +539,9 @@ ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: FunctionToLoopPassAdaptor -; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: LoopAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: DominatorTreeAnalysis +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: AAManager ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: AssumptionAnalysis Index: llvm/trunk/test/Transforms/LICM/atomics.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/atomics.ll +++ llvm/trunk/test/Transforms/LICM/atomics.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -S -basicaa -licm | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require,require,require,require,loop(licm)' < %s -S | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='require,loop(licm)' < %s -S | FileCheck %s ; Check that we can hoist unordered loads define i32 @test1(i32* nocapture %y) nounwind uwtable ssp { Index: llvm/trunk/test/Transforms/LICM/constexpr.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/constexpr.ll +++ llvm/trunk/test/Transforms/LICM/constexpr.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -S -basicaa -licm | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require,require,require,require,loop(licm)' < %s -S | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='require,loop(licm)' < %s -S | FileCheck %s ; This fixes PR22460 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: llvm/trunk/test/Transforms/LICM/hoist-nounwind.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/hoist-nounwind.ll +++ llvm/trunk/test/Transforms/LICM/hoist-nounwind.ll @@ -1,5 +1,5 @@ ; RUN: opt -S -basicaa -licm < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes='lcssa,require,require,require,require,loop(licm)' -S %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='require,loop(licm)' -S %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: llvm/trunk/test/Transforms/LICM/hoisting.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/hoisting.ll +++ llvm/trunk/test/Transforms/LICM/hoisting.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -licm -S | FileCheck %s -; RUN: opt -lcssa %s | opt -aa-pipeline=basic-aa -passes='require,require,require,require,loop(licm)' -S | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa -passes='require,loop(licm)' -S | FileCheck %s @X = global i32 0 ; [#uses=1]