Index: llvm/include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -356,6 +356,14 @@ Worklist.insert(CurrentL); } + bool isLoopNestChanged() const { + return LoopNestChanged; + } + + void markLoopNestChanged(bool Changed) { + LoopNestChanged = Changed; + } + private: friend class llvm::FunctionToLoopPassAdaptor; @@ -368,6 +376,7 @@ Loop *CurrentL; bool SkipCurrentLoop; const bool LoopNestMode; + bool LoopNestChanged; #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS // In debug builds we also track the parent loop to implement asserts even in @@ -376,8 +385,10 @@ #endif LPMUpdater(SmallPriorityWorklist &Worklist, - LoopAnalysisManager &LAM, bool LoopNestMode = false) - : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode) {} + LoopAnalysisManager &LAM, bool LoopNestMode = false, + bool LoopNestChanged=false) + : Worklist(Worklist), LAM(LAM), LoopNestMode(LoopNestMode), + LoopNestChanged(LoopNestChanged) {} }; template Index: llvm/lib/Analysis/LoopNestAnalysis.cpp =================================================================== --- llvm/lib/Analysis/LoopNestAnalysis.cpp +++ llvm/lib/Analysis/LoopNestAnalysis.cpp @@ -450,6 +450,12 @@ return OS; } +LoopNestAnalysis::Result +LoopNestAnalysis::run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR) { + return LoopNest(L, AR.SE); +} + //===----------------------------------------------------------------------===// // LoopNestPrinterPass implementation // Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -492,6 +492,7 @@ LOOP_ANALYSIS("ddg", DDGAnalysis()) LOOP_ANALYSIS("iv-users", IVUsersAnalysis()) LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) +LOOP_ANALYSIS("loop-nest", LoopNestAnalysis()) #undef LOOP_ANALYSIS #ifndef LOOP_PASS Index: llvm/lib/Transforms/Scalar/LoopInterchange.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -44,6 +44,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include @@ -1773,5 +1774,6 @@ OptimizationRemarkEmitter ORE(&F); if (!LoopInterchange(&AR.SE, &AR.LI, &DI, &AR.DT, CC, &ORE).run(LN)) return PreservedAnalyses::all(); + U.markLoopNestChanged(true); return getLoopPassPreservedAnalyses(); } Index: llvm/lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -78,12 +78,7 @@ unsigned LoopPassIndex = 0, LoopNestPassIndex = 0; - // `LoopNestPtr` points to the `LoopNest` object for the current top-level - // loop and `IsLoopNestPtrValid` indicates whether the pointer is still valid. - // The `LoopNest` object will have to be re-constructed if the pointer is - // invalid when encountering a loop-nest pass. - std::unique_ptr LoopNestPtr; - bool IsLoopNestPtrValid = false; + Loop *OuterMostLoop = &L; for (size_t I = 0, E = IsLoopNestPass.size(); I != E; ++I) { Optional PassPA; @@ -94,14 +89,17 @@ } else { // The `I`-th pass is a loop-nest pass. auto &Pass = LoopNestPasses[LoopNestPassIndex++]; - - // If the loop-nest object calculated before is no longer valid, - // re-calculate it here before running the loop-nest pass. - if (!IsLoopNestPtrValid) { - LoopNestPtr = LoopNest::getLoopNest(L, AR.SE); - IsLoopNestPtrValid = true; + assert(OuterMostLoop->isOutermost() && + "LoopNest should be constructed only with the outermost loop!"); + LoopNest &LN = AM.getResult(*OuterMostLoop, AR); + PassPA = runSinglePass(LN, Pass, AM, AR, U, PI); + + // Restore the correct loopnest status. + if (U.isLoopNestChanged()) { + while (auto *PL = OuterMostLoop->getParentLoop()) + OuterMostLoop = PL; + U.markLoopNestChanged(false); } - PassPA = runSinglePass(*LoopNestPtr, Pass, AM, AR, U, PI); } // `PassPA` is `None` means that the before-pass callbacks in @@ -124,9 +122,6 @@ // aggregate preserved set for this pass manager. PA.intersect(std::move(*PassPA)); - // Check if the current pass preserved the loop-nest object or not. - IsLoopNestPtrValid &= PassPA->getChecker().preserved(); - // After running the loop pass, the parent loop might change and we need to // notify the updater, otherwise U.ParentL might gets outdated and triggers // assertion failures in addSiblingLoops and addChildLoops. Index: llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp =================================================================== --- llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp +++ llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp @@ -301,6 +301,8 @@ // Register our mock analysis. LAM.registerPass([&] { return MLAHandle.getAnalysis(); }); + LAM.registerPass([&] { return LoopNestAnalysis(); }); + // We need DominatorTreeAnalysis for LoopAnalysis. FAM.registerPass([&] { return DominatorTreeAnalysis(); }); FAM.registerPass([&] { return LoopAnalysis(); });