[llvm] r291651 - [PM] Rewrite the loop pass manager to use a worklist and augmented run

Ivan Krasin via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 11 15:54:40 PST 2017


Grrr. A typo. Please, read: there's nothing wrong with the code (Chandler's
CL) *AND* the remedy would be ...

On Wed, Jan 11, 2017 at 3:51 PM, Ivan Krasin <krasin at google.com> wrote:

> Mike,
>
> this is a known and fixed issue in libstdc++: https://gcc.gnu.
> org/bugzilla/show_bug.cgi?id=60734
> There's nothing wrong with the code in the remedy would be to upgrade
> buildbots to newer Ubuntu (16.04) which have this undefined behavior fixed.
> This work is in the progress. ETA: end of day.
>
> On Wed, Jan 11, 2017 at 3:49 PM, Mike Aizatsky <aizatsky at google.com>
> wrote:
>
>> Chandler,
>>
>> Looks like ubsan complains about this change:
>>
>> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/2034
>>
>> [ RUN      ] LoopPassManagerTest.FunctionPassInvalidationOfLoopAnalyses
>> /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_tree.h:1540:28:
>> runtime error: upcast of address 0x00000366a0d0 with insufficient space for
>> an object of type 'std::_Rb_tree_node<std::pair<const void *const,
>> testing::(anonymous namespace)::MockObjectState> >'
>> 0x00000366a0d0: note: pointer points here
>>  00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  d0 a0 66
>> 03 00 00 00 00  d0 a0 66 03
>>               ^
>>     #0 0xc4d1b7 in std::_Rb_tree<void const*, std::pair<void const*
>> const, testing::(anonymous namespace)::MockObjectState>,
>> std::_Select1st<std::pair<void const* const, testing::(anonymous
>> namespace)::MockObjectState> >, std::less<void const*>,
>> std::allocator<std::pair<void const* const, testing::(anonymous
>> namespace)::MockObjectState> > >::_M_get_insert_hint_unique_p
>> os(std::_Rb_tree_const_iterator<std::pair<void const* const,
>> testing::(anonymous namespace)::MockObjectState> >, void const* const&)
>> /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.
>> 9/bits/stl_tree.h:1540:28
>>     #1 0xc4ce76 in std::_Rb_tree_iterator<std::pair<void const* const,
>> testing::(anonymous namespace)::MockObjectState> > std::_Rb_tree<void
>> const*, std::pair<void const* const, testing::(anonymous
>> namespace)::MockObjectState>, std::_Select1st<std::pair<void const* const,
>> testing::(anonymous namespace)::MockObjectState> >, std::less<void const*>,
>> std::allocator<std::pair<void const* const, testing::(anonymous
>> namespace)::MockObjectState> > >::_M_emplace_hint_unique<std::piecewise_construct_t
>> const&, std::tuple<void const* const&>, std::tuple<>
>> >(std::_Rb_tree_const_iterator<std::pair<void const* const,
>> testing::(anonymous namespace)::MockObjectState> >,
>> std::piecewise_construct_t const&, std::tuple<void const* const&>&&,
>> std::tuple<>&&) /usr/lib/gcc/x86_64-linux-gnu/
>> 4.9/../../../../include/c++/4.9/bits/stl_tree.h:1794:19
>>     #2 0xc4b713 in std::map<void const*, testing::(anonymous
>> namespace)::MockObjectState, std::less<void const*>,
>> std::allocator<std::pair<void const* const, testing::(anonymous
>> namespace)::MockObjectState> > >::operator[](void const* const&)
>> /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.
>> 9/bits/stl_map.h:500:15
>>     #3 0xc4a2d8 in testing::Mock::Register(void const*,
>> testing::internal::UntypedFunctionMockerBase*)
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googlemock/src/gmock-spec-builders.cc:715:3
>>     #4 0xc4a27c in testing::internal::UntypedFunc
>> tionMockerBase::RegisterOwner(void const*) /mnt/b/sanitizer-buildbot3/san
>> itizer-x86_64-linux-fast/build/llvm/utils/unittest/googlemoc
>> k/src/gmock-spec-builders.cc:285:3
>>     #5 0x4efbc9 in (anonymous namespace)::MockLoopAnalysisHandleTemplate<
>> 18446744073709551615ul>::gmock_run(testing::Matcher<llvm::Loop&> const&,
>> testing::Matcher<llvm::AnalysisManager<llvm::Loop,
>> llvm::LoopStandardAnalysisResults&>&> const&,
>> testing::Matcher<llvm::LoopStandardAnalysisResults&> const&)
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/unittests/Analysis/LoopPassManagerTest.cpp:120:3
>>     #6 0x4ed31b in (anonymous namespace)::MockAnalysisHandleBase<(anonymous
>> namespace)::MockLoopAnalysisHandleTemplate<18446744073709551615ul>,
>> llvm::Loop, llvm::AnalysisManager<llvm::Loop,
>> llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&>::setDefaults()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/unittests/Analysis/LoopPassManagerTest.cpp:82:5
>>     #7 0x4eb262 in (anonymous namespace)::LoopPassManagerTest::LoopPassManagerTest()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/unittests/Analysis/LoopPassManagerTest.cpp:242:3
>>     #8 0x4f44ba in (anonymous namespace)::LoopPassManagerTes
>> t_FunctionPassInvalidationOfLoopAnalyses_Test::LoopPassManag
>> erTest_FunctionPassInvalidationOfLoopAnalyses_Test()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/unittests/Analysis/LoopPassManagerTest.cpp:346:1
>>     #9 0x4f447f in testing::internal::TestFactoryImpl<(anonymous
>> namespace)::LoopPassManagerTest_FunctionPassInvalidationOfLoopAnalyses_Test>::CreateTest()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googletest/include/gtest/internal/
>> gtest-internal.h:484:43
>>     #10 0xc15510 in testing::TestInfo::Run()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googletest/src/gtest.cc:2647:22
>>     #11 0xc15c32 in testing::TestCase::Run()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googletest/src/gtest.cc:2774:28
>>     #12 0xc1c013 in testing::internal::UnitTestImpl::RunAllTests()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googletest/src/gtest.cc:4649:43
>>     #13 0xc1bcab in testing::UnitTest::Run()
>> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build
>> /llvm/utils/unittest/googletest/src/gtest.cc:4257:10
>>     #14 0xc0aef3 in main /mnt/b/sanitizer-buildbot3/san
>> itizer-x86_64-linux-fast/build/llvm/utils/unittest/UnitTestM
>> ain/TestMain.cpp:51:10
>>     #15 0x7fe430cb6f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so
>> .6+0x21f44)
>>     #16 0x414903 in _start (/mnt/b/sanitizer-buildbot3/sa
>> nitizer-x86_64-linux-fast/build/llvm_build_ubsan/unittests/
>> Analysis/AnalysisTests+0x414903)
>>
>>
>>
>> On Tue, Jan 10, 2017 at 10:34 PM Chandler Carruth via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>> Author: chandlerc
>>> Date: Wed Jan 11 00:23:21 2017
>>> New Revision: 291651
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=291651&view=rev
>>> Log:
>>> [PM] Rewrite the loop pass manager to use a worklist and augmented run
>>> arguments much like the CGSCC pass manager.
>>>
>>> This is a major redesign following the pattern establish for the CGSCC
>>> layer to
>>> support updates to the set of loops during the traversal of the loop
>>> nest and
>>> to support invalidation of analyses.
>>>
>>> An additional significant burden in the loop PM is that so many passes
>>> require
>>> access to a large number of function analyses. Manually ensuring these
>>> are
>>> cached, available, and preserved has been a long-standing burden in LLVM
>>> even
>>> with the help of the automatic scheduling in the old pass manager. And
>>> it made
>>> the new pass manager extremely unweildy. With this design, we can
>>> package the
>>> common analyses up while in a function pass and make them immediately
>>> available
>>> to all the loop passes. While in some cases this is unnecessary, I think
>>> the
>>> simplicity afforded is worth it.
>>>
>>> This does not (yet) address loop simplified form or LCSSA form, but
>>> those are
>>> the next things on my radar and I have a clear plan for them.
>>>
>>> While the patch is very large, most of it is either mechanically
>>> updating loop
>>> passes to the new API or the new testing for the loop PM. The code for
>>> it is
>>> reasonably compact.
>>>
>>> I have not yet updated all of the loop passes to correctly leverage the
>>> update
>>> mechanisms demonstrated in the unittests. I'll do that in follow-up
>>> patches
>>> along with improved FileCheck tests for those passes that ensure things
>>> work in
>>> more realistic scenarios. In many cases, there isn't much we can do with
>>> these
>>> until the loop simplified form and LCSSA form are in place.
>>>
>>> Differential Revision: https://reviews.llvm.org/D28292
>>>
>>> Modified:
>>>     llvm/trunk/include/llvm/Analysis/IVUsers.h
>>>     llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h
>>>     llvm/trunk/include/llvm/Analysis/LoopInfo.h
>>>     llvm/trunk/include/llvm/Analysis/LoopPassManager.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/IndVarSimplify.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LICM.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopDeletion.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopInstSimplify.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopRotation.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopStrengthReduce.h
>>>     llvm/trunk/include/llvm/Transforms/Scalar/LoopUnrollPass.h
>>>     llvm/trunk/lib/Analysis/IVUsers.cpp
>>>     llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp
>>>     llvm/trunk/lib/Analysis/LoopInfo.cpp
>>>     llvm/trunk/lib/Analysis/LoopPass.cpp
>>>     llvm/trunk/lib/Analysis/LoopPassManager.cpp
>>>     llvm/trunk/lib/Passes/PassBuilder.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LICM.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
>>>     llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
>>>     llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>>>     llvm/trunk/test/Other/loop-pass-ordering.ll
>>>     llvm/trunk/test/Other/new-pass-manager.ll
>>>     llvm/trunk/test/Other/pass-pipeline-parsing.ll
>>>     llvm/trunk/unittests/Analysis/LoopPassManagerTest.cpp
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Analysis/IVUsers.h?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Analysis/IVUsers.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/IVUsers.h Wed Jan 11 00:23:21 2017
>>> @@ -193,7 +193,8 @@ class IVUsersAnalysis : public AnalysisI
>>>  public:
>>>    typedef IVUsers Result;
>>>
>>> -  IVUsers run(Loop &L, LoopAnalysisManager &AM);
>>> +  IVUsers run(Loop &L, LoopAnalysisManager &AM,
>>> +              LoopStandardAnalysisResults &AR);
>>>  };
>>>
>>>  /// Printer pass for the \c IVUsers for a loop.
>>> @@ -202,7 +203,8 @@ class IVUsersPrinterPass : public PassIn
>>>
>>>  public:
>>>    explicit IVUsersPrinterPass(raw_ostream &OS) : OS(OS) {}
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  }
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Analysis/LoopAccessAnalysis.h?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/LoopAccessAnalysis.h Wed Jan 11
>>> 00:23:21 2017
>>> @@ -753,8 +753,8 @@ class LoopAccessAnalysis
>>>
>>>  public:
>>>    typedef LoopAccessInfo Result;
>>> -  Result run(Loop &, LoopAnalysisManager &);
>>> -  static StringRef name() { return "LoopAccessAnalysis"; }
>>> +
>>> +  Result run(Loop &L, LoopAnalysisManager &AM,
>>> LoopStandardAnalysisResults &AR);
>>>  };
>>>
>>>  /// \brief Printer pass for the \c LoopAccessInfo results.
>>> @@ -764,7 +764,8 @@ class LoopAccessInfoPrinterPass
>>>
>>>  public:
>>>    explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>
>>>  inline Instruction *MemoryDepChecker::Dependence::getSource(
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Analysis/LoopInfo.h?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Wed Jan 11 00:23:21 2017
>>> @@ -853,17 +853,8 @@ public:
>>>    void getAnalysisUsage(AnalysisUsage &AU) const override;
>>>  };
>>>
>>> -/// \brief Pass for printing a loop's contents as LLVM's text IR
>>> assembly.
>>> -class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
>>> -  raw_ostream &OS;
>>> -  std::string Banner;
>>> -
>>> -public:
>>> -  PrintLoopPass();
>>> -  PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
>>> -
>>> -  PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &);
>>> -};
>>> +/// Function to print a loop's contents as LLVM's text IR assembly.
>>> +void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner =
>>> "");
>>>
>>>  } // End llvm namespace
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/LoopPassManager.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Analysis/LoopPassManager.h?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Analysis/LoopPassManager.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/LoopPassManager.h Wed Jan 11
>>> 00:23:21 2017
>>> @@ -8,63 +8,342 @@
>>>  //===------------------------------------------------------
>>> ----------------===//
>>>  /// \file
>>>  ///
>>> -/// This header provides classes for managing passes over loops in LLVM
>>> IR.
>>> +/// This header provides classes for managing a pipeline of passes over
>>> loops
>>> +/// in LLVM IR.
>>> +///
>>> +/// The primary loop pass pipeline is managed in a very particular way
>>> to
>>> +/// provide a set of core guarantees:
>>> +/// 1) Loops are, where possible, in simplified form.
>>> +/// 2) Loops are *always* in LCSSA form.
>>> +/// 3) A collection of Loop-specific analysis results are available:
>>> +///    - LoopInfo
>>> +///    - DominatorTree
>>> +///    - ScalarEvolution
>>> +///    - AAManager
>>> +/// 4) All loop passes preserve #1 (where possible), #2, and #3.
>>> +/// 5) Loop passes run over each loop in the loop nest from the
>>> innermost to
>>> +///    the outermost. Specifically, all inner loops are processed before
>>> +///    passes run over outer loops. When running the pipeline across an
>>> inner
>>> +///    loop creates new inner loops, those are added and processed in
>>> this
>>> +///    order as well.
>>> +///
>>> +/// This process is designed to facilitate transformations which
>>> simplify,
>>> +/// reduce, and remove loops. For passes which are more oriented towards
>>> +/// optimizing loops, especially optimizing loop *nests* instead of
>>> single
>>> +/// loops in isolation, this framework is less interesting.
>>>  ///
>>>  //===------------------------------------------------------
>>> ----------------===//
>>>
>>>  #ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H
>>>  #define LLVM_ANALYSIS_LOOPPASSMANAGER_H
>>>
>>> +#include "llvm/ADT/PostOrderIterator.h"
>>> +#include "llvm/ADT/PriorityWorklist.h"
>>>  #include "llvm/ADT/STLExtras.h"
>>>  #include "llvm/Analysis/AliasAnalysis.h"
>>> +#include "llvm/Analysis/BasicAliasAnalysis.h"
>>> +#include "llvm/Analysis/GlobalsModRef.h"
>>>  #include "llvm/Analysis/LoopInfo.h"
>>>  #include "llvm/Analysis/ScalarEvolution.h"
>>> +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
>>>  #include "llvm/Analysis/TargetLibraryInfo.h"
>>> +#include "llvm/Analysis/TargetTransformInfo.h"
>>>  #include "llvm/IR/Dominators.h"
>>>  #include "llvm/IR/PassManager.h"
>>>
>>>  namespace llvm {
>>>
>>> -extern template class PassManager<Loop>;
>>> -/// \brief The loop pass manager.
>>> -///
>>> -/// See the documentation for the PassManager template for details. It
>>> runs a
>>> -/// sequency of loop passes over each loop that the manager is run
>>> over. This
>>> -/// typedef serves as a convenient way to refer to this construct.
>>> -typedef PassManager<Loop> LoopPassManager;
>>> +// Forward declarations of a update tracking and analysis result
>>> tracking
>>> +// structures used in the API of loop passes that work within this
>>> +// infrastructure.
>>> +class LPMUpdater;
>>> +struct LoopStandardAnalysisResults;
>>>
>>> -extern template class AnalysisManager<Loop>;
>>> +/// Extern template declaration for the analysis set for this IR unit.
>>> +extern template class AllAnalysesOn<Loop>;
>>> +
>>> +extern template class AnalysisManager<Loop, LoopStandardAnalysisResults
>>> &>;
>>>  /// \brief The loop analysis manager.
>>>  ///
>>>  /// See the documentation for the AnalysisManager template for detail
>>>  /// documentation. This typedef serves as a convenient way to refer to
>>> this
>>>  /// construct in the adaptors and proxies used to integrate this into
>>> the larger
>>>  /// pass manager infrastructure.
>>> -typedef AnalysisManager<Loop> LoopAnalysisManager;
>>> +typedef AnalysisManager<Loop, LoopStandardAnalysisResults &>
>>> +    LoopAnalysisManager;
>>> +
>>> +// Explicit specialization and instantiation declarations for the pass
>>> manager.
>>> +// See the comments on the definition of the specialization for details
>>> on how
>>> +// it differs from the primary template.
>>> +template <>
>>> +PreservedAnalyses
>>> +PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
>>> +            LPMUpdater &>::run(Loop &InitialL, LoopAnalysisManager &AM,
>>> +                               LoopStandardAnalysisResults
>>> &AnalysisResults,
>>> +                               LPMUpdater &U);
>>> +extern template class PassManager<Loop, LoopAnalysisManager,
>>> +                                  LoopStandardAnalysisResults &,
>>> LPMUpdater &>;
>>> +
>>> +/// \brief The Loop pass manager.
>>> +///
>>> +/// See the documentation for the PassManager template for details. It
>>> runs
>>> +/// a sequence of Loop passes over each Loop that the manager is run
>>> over. This
>>> +/// typedef serves as a convenient way to refer to this construct.
>>> +typedef PassManager<Loop, LoopAnalysisManager,
>>> LoopStandardAnalysisResults &,
>>> +                    LPMUpdater &>
>>> +    LoopPassManager;
>>> +
>>> +/// A partial specialization of the require analysis template pass to
>>> forward
>>> +/// the extra parameters from a transformation's run method to the
>>> +/// AnalysisManager's getResult.
>>> +template <typename AnalysisT>
>>> +struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
>>> +                           LoopStandardAnalysisResults &, LPMUpdater &>
>>> +    : PassInfoMixin<
>>> +          RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
>>> +                              LoopStandardAnalysisResults &, LPMUpdater
>>> &>> {
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &) {
>>> +    (void)AM.template getResult<AnalysisT>(L, AR);
>>> +    return PreservedAnalyses::all();
>>> +  }
>>> +};
>>> +
>>> +/// An alias template to easily name a require analysis loop pass.
>>> +template <typename AnalysisT>
>>> +using RequireAnalysisLoopPass =
>>> +    RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager,
>>> +                        LoopStandardAnalysisResults &, LPMUpdater &>;
>>>
>>>  /// A proxy from a \c LoopAnalysisManager to a \c Function.
>>>  typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function>
>>>      LoopAnalysisManagerFunctionProxy;
>>>
>>> -/// Specialization of the invalidate method for the \c
>>> -/// LoopAnalysisManagerFunctionProxy's result.
>>> +/// A specialized result for the \c LoopAnalysisManagerFunctionProxy
>>> which
>>> +/// retains a \c LoopInfo reference.
>>> +///
>>> +/// This allows it to collect loop objects for which analysis results
>>> may be
>>> +/// cached in the \c LoopAnalysisManager.
>>> +template <> class LoopAnalysisManagerFunctionProxy::Result {
>>> +public:
>>> +  explicit Result(LoopAnalysisManager &InnerAM, LoopInfo &LI)
>>> +      : InnerAM(&InnerAM), LI(&LI) {}
>>> +  Result(Result &&Arg) : InnerAM(std::move(Arg.InnerAM)), LI(Arg.LI) {
>>> +    // We have to null out the analysis manager in the moved-from state
>>> +    // because we are taking ownership of the responsibilty to clear the
>>> +    // analysis state.
>>> +    Arg.InnerAM = nullptr;
>>> +  }
>>> +  Result &operator=(Result &&RHS) {
>>> +    InnerAM = RHS.InnerAM;
>>> +    LI = RHS.LI;
>>> +    // We have to null out the analysis manager in the moved-from state
>>> +    // because we are taking ownership of the responsibilty to clear the
>>> +    // analysis state.
>>> +    RHS.InnerAM = nullptr;
>>> +    return *this;
>>> +  }
>>> +  ~Result() {
>>> +    // InnerAM is cleared in a moved from state where there is nothing
>>> to do.
>>> +    if (!InnerAM)
>>> +      return;
>>> +
>>> +    // Clear out the analysis manager if we're being destroyed -- it
>>> means we
>>> +    // didn't even see an invalidate call when we got invalidated.
>>> +    InnerAM->clear();
>>> +  }
>>> +
>>> +  /// Accessor for the analysis manager.
>>> +  LoopAnalysisManager &getManager() { return *InnerAM; }
>>> +
>>> +  /// Handler for invalidation of the proxy for a particular function.
>>> +  ///
>>> +  /// If the proxy, \c LoopInfo, and associated analyses are preserved,
>>> this
>>> +  /// will merely forward the invalidation event to any cached loop
>>> analysis
>>> +  /// results for loops within this function.
>>> +  ///
>>> +  /// If the necessary loop infrastructure is not preserved, this will
>>> forcibly
>>> +  /// clear all of the cached analysis results that are keyed on the \c
>>> +  /// LoopInfo for this function.
>>> +  bool invalidate(Function &F, const PreservedAnalyses &PA,
>>> +                  FunctionAnalysisManager::Invalidator &Inv);
>>> +
>>> +private:
>>> +  LoopAnalysisManager *InnerAM;
>>> +  LoopInfo *LI;
>>> +};
>>> +
>>> +/// Provide a specialized run method for the \c
>>> LoopAnalysisManagerFunctionProxy
>>> +/// so it can pass the \c LoopInfo to the result.
>>>  template <>
>>> -bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
>>> -    Function &F, const PreservedAnalyses &PA,
>>> -    FunctionAnalysisManager::Invalidator &Inv);
>>> +LoopAnalysisManagerFunctionProxy::Result
>>> +LoopAnalysisManagerFunctionProxy::run(Function &F,
>>> FunctionAnalysisManager &AM);
>>>
>>>  // Ensure the \c LoopAnalysisManagerFunctionProxy is provided as an
>>> extern
>>>  // template.
>>>  extern template class InnerAnalysisManagerProxy<LoopAnalysisManager,
>>> Function>;
>>>
>>> -extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager,
>>> Loop>;
>>> +extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager,
>>> Loop,
>>> +
>>> LoopStandardAnalysisResults &>;
>>>  /// A proxy from a \c FunctionAnalysisManager to a \c Loop.
>>> -typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>
>>> +typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop,
>>> +                                  LoopStandardAnalysisResults &>
>>>      FunctionAnalysisManagerLoopProxy;
>>>
>>>  /// Returns the minimum set of Analyses that all loop passes must
>>> preserve.
>>>  PreservedAnalyses getLoopPassPreservedAnalyses();
>>>
>>> +namespace internal {
>>> +/// Helper to implement appending of loops onto a worklist.
>>> +///
>>> +/// We want to process loops in postorder, but the worklist is a LIFO
>>> data
>>> +/// structure, so we append to it in *reverse* postorder.
>>> +///
>>> +/// For trees, a preorder traversal is a viable reverse postorder, so we
>>> +/// actually append using a preorder walk algorithm.
>>> +template <typename RangeT>
>>> +inline void appendLoopsToWorklist(RangeT &&Loops,
>>> +                                  SmallPriorityWorklist<Loop *, 4>
>>> &Worklist) {
>>> +  // We use an internal worklist to build up the preorder traversal
>>> without
>>> +  // recursion.
>>> +  SmallVector<Loop *, 4> PreOrderLoops, PreOrderWorklist;
>>> +
>>> +  // We walk the initial sequence of loops in reverse because we
>>> generally want
>>> +  // to visit defs before uses and the worklist is LIFO.
>>> +  for (Loop *RootL : reverse(Loops)) {
>>> +    assert(PreOrderLoops.empty() && "Must start with an empty preorder
>>> walk.");
>>> +    assert(PreOrderWorklist.empty() &&
>>> +           "Must start with an empty preorder walk worklist.");
>>> +    PreOrderWorklist.push_back(RootL);
>>> +    do {
>>> +      Loop *L = PreOrderWorklist.pop_back_val();
>>> +      PreOrderWorklist.append(L->begin(), L->end());
>>> +      PreOrderLoops.push_back(L);
>>> +    } while (!PreOrderWorklist.empty());
>>> +
>>> +    Worklist.insert(std::move(PreOrderLoops));
>>> +    PreOrderLoops.clear();
>>> +  }
>>> +}
>>> +}
>>> +
>>> +/// The adaptor from a function pass to a loop pass directly computes
>>> +/// a standard set of analyses that are especially useful to loop
>>> passes and
>>> +/// makes them available in the API. Loop passes are also expected to
>>> update
>>> +/// all of these so that they remain correct across the entire loop
>>> pipeline.
>>> +struct LoopStandardAnalysisResults {
>>> +  AAResults &AA;
>>> +  AssumptionCache &AC;
>>> +  DominatorTree &DT;
>>> +  LoopInfo &LI;
>>> +  ScalarEvolution &SE;
>>> +  TargetLibraryInfo &TLI;
>>> +  TargetTransformInfo &TTI;
>>> +};
>>> +
>>> +template <typename LoopPassT> class FunctionToLoopPassAdaptor;
>>> +
>>> +/// This class provides an interface for updating the loop pass manager
>>> based
>>> +/// on mutations to the loop nest.
>>> +///
>>> +/// A reference to an instance of this class is passed as an argument
>>> to each
>>> +/// Loop pass, and Loop passes should use it to update LPM
>>> infrastructure if
>>> +/// they modify the loop nest structure.
>>> +class LPMUpdater {
>>> +public:
>>> +  /// This can be queried by loop passes which run other loop passes
>>> (like pass
>>> +  /// managers) to know whether the loop needs to be skipped due to
>>> updates to
>>> +  /// the loop nest.
>>> +  ///
>>> +  /// If this returns true, the loop object may have been deleted, so
>>> passes
>>> +  /// should take care not to touch the object.
>>> +  bool skipCurrentLoop() const { return SkipCurrentLoop; }
>>> +
>>> +  /// Loop passes should use this method to indicate they have deleted
>>> a loop
>>> +  /// from the nest.
>>> +  ///
>>> +  /// Note that this loop must either be the current loop or a subloop
>>> of the
>>> +  /// current loop. This routine must be called prior to removing the
>>> loop from
>>> +  /// the loop nest.
>>> +  ///
>>> +  /// If this is called for the current loop, in addition to clearing
>>> any
>>> +  /// state, this routine will mark that the current loop should be
>>> skipped by
>>> +  /// the rest of the pass management infrastructure.
>>> +  void markLoopAsDeleted(Loop &L) {
>>> +    LAM.clear(L);
>>> +    assert(CurrentL->contains(&L) && "Cannot delete a loop outside of
>>> the "
>>> +                                     "subloop tree currently being
>>> processed.");
>>> +    if (&L == CurrentL)
>>> +      SkipCurrentLoop = true;
>>> +  }
>>> +
>>> +  /// Loop passes should use this method to indicate they have added
>>> new child
>>> +  /// loops of the current loop.
>>> +  ///
>>> +  /// \p NewChildLoops must contain only the immediate children. Any
>>> nested
>>> +  /// loops within them will be visited in postorder as usual for the
>>> loop pass
>>> +  /// manager.
>>> +  void addChildLoops(ArrayRef<Loop *> NewChildLoops) {
>>> +    // Insert ourselves back into the worklist first, as this loop
>>> should be
>>> +    // revisited after all the children have been processed.
>>> +    Worklist.insert(CurrentL);
>>> +
>>> +#ifndef NDEBUG
>>> +    for (Loop *NewL : NewChildLoops)
>>> +      assert(NewL->getParentLoop() == CurrentL && "All of the new loops
>>> must "
>>> +                                                  "be immediate
>>> children of "
>>> +                                                  "the current loop!");
>>> +#endif
>>> +
>>> +    internal::appendLoopsToWorklist(NewChildLoops, Worklist);
>>> +
>>> +    // Also skip further processing of the current loop--it will be
>>> revisited
>>> +    // after all of its newly added children are accounted for.
>>> +    SkipCurrentLoop = true;
>>> +  }
>>> +
>>> +  /// Loop passes should use this method to indicate they have added new
>>> +  /// sibling loops to the current loop.
>>> +  ///
>>> +  /// \p NewSibLoops must only contain the immediate sibling loops. Any
>>> nested
>>> +  /// loops within them will be visited in postorder as usual for the
>>> loop pass
>>> +  /// manager.
>>> +  void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) {
>>> +#ifndef NDEBUG
>>> +    for (Loop *NewL : NewSibLoops)
>>> +      assert(NewL->getParentLoop() == ParentL &&
>>> +             "All of the new loops must be siblings of the current
>>> loop!");
>>> +#endif
>>> +
>>> +    internal::appendLoopsToWorklist(NewSibLoops, Worklist);
>>> +
>>> +    // No need to skip the current loop or revisit it, as sibling loops
>>> +    // shouldn't impact anything.
>>> +  }
>>> +
>>> +private:
>>> +  template <typename LoopPassT> friend class
>>> llvm::FunctionToLoopPassAdaptor;
>>> +
>>> +  /// The \c FunctionToLoopPassAdaptor's worklist of loops to process.
>>> +  SmallPriorityWorklist<Loop *, 4> &Worklist;
>>> +
>>> +  /// The analysis manager for use in the current loop nest.
>>> +  LoopAnalysisManager &LAM;
>>> +
>>> +  Loop *CurrentL;
>>> +  bool SkipCurrentLoop;
>>> +
>>> +#ifndef NDEBUG
>>> +  // In debug builds we also track the parent loop to implement asserts
>>> even in
>>> +  // the face of loop deletion.
>>> +  Loop *ParentL;
>>> +#endif
>>> +
>>> +  LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist,
>>> +             LoopAnalysisManager &LAM)
>>> +      : Worklist(Worklist), LAM(LAM) {}
>>> +};
>>> +
>>>  /// \brief Adaptor that maps from a function to its loops.
>>>  ///
>>>  /// Designed to allow composition of a LoopPass(Manager) and a
>>> @@ -87,42 +366,61 @@ public:
>>>      // Get the loop structure for this function
>>>      LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
>>>
>>> -    // Also precompute all of the function analyses used by loop passes.
>>> -    // FIXME: These should be handed into the loop passes when the loop
>>> pass
>>> -    // management layer is reworked to follow the design of CGSCC.
>>> -    (void)AM.getResult<AAManager>(F);
>>> -    (void)AM.getResult<DominatorTreeAnalysis>(F);
>>> -    (void)AM.getResult<ScalarEvolutionAnalysis>(F);
>>> -    (void)AM.getResult<TargetLibraryAnalysis>(F);
>>> +    // If there are no loops, there is nothing to do here.
>>> +    if (LI.empty())
>>> +      return PreservedAnalyses::all();
>>> +
>>> +    // Get the analysis results needed by loop passes.
>>> +    LoopStandardAnalysisResults LAR = {AM.getResult<AAManager>(F),
>>> +                                       AM.getResult<AssumptionAnalys
>>> is>(F),
>>> +                                       AM.getResult<DominatorTreeAna
>>> lysis>(F),
>>> +                                       AM.getResult<LoopAnalysis>(F),
>>> +                                       AM.getResult<ScalarEvolutionA
>>> nalysis>(F),
>>> +                                       AM.getResult<TargetLibraryAna
>>> lysis>(F),
>>> +                                       AM.getResult<TargetIRAnalysis
>>> >(F)};
>>>
>>>      PreservedAnalyses PA = PreservedAnalyses::all();
>>>
>>> -    // We want to visit the loops in reverse post-order. We'll build
>>> the stack
>>> -    // of loops to visit in Loops by first walking the loops in
>>> pre-order.
>>> -    SmallVector<Loop *, 2> Loops;
>>> -    SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end());
>>> -    while (!WorkList.empty()) {
>>> -      Loop *L = WorkList.pop_back_val();
>>> -      WorkList.insert(WorkList.end(), L->begin(), L->end());
>>> -      Loops.push_back(L);
>>> -    }
>>> -
>>> -    // Now pop each element off of the stack to visit the loops in
>>> reverse
>>> -    // post-order.
>>> -    for (auto *L : reverse(Loops)) {
>>> -      PreservedAnalyses PassPA = Pass.run(*L, LAM);
>>> +    // A postorder worklist of loops to process.
>>> +    SmallPriorityWorklist<Loop *, 4> Worklist;
>>> +
>>> +    // Register the worklist and loop analysis manager so that loop
>>> passes can
>>> +    // update them when they mutate the loop nest structure.
>>> +    LPMUpdater Updater(Worklist, LAM);
>>> +
>>> +    // Add the loop nests in the reverse order of LoopInfo. For some
>>> reason,
>>> +    // they are stored in RPO w.r.t. the control flow graph in
>>> LoopInfo. For
>>> +    // the purpose of unrolling, loop deletion, and LICM, we largely
>>> want to
>>> +    // work forward across the CFG so that we visit defs before uses
>>> and can
>>> +    // propagate simplifications from one loop nest into the next.
>>> +    // FIXME: Consider changing the order in LoopInfo.
>>> +    internal::appendLoopsToWorklist(reverse(LI), Worklist);
>>> +
>>> +    do {
>>> +      Loop *L = Worklist.pop_back_val();
>>> +
>>> +      // Reset the update structure for this loop.
>>> +      Updater.CurrentL = L;
>>> +      Updater.SkipCurrentLoop = false;
>>> +#ifndef NDEBUG
>>> +      Updater.ParentL = L->getParentLoop();
>>> +#endif
>>> +
>>> +      PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater);
>>>        // FIXME: We should verify the set of analyses relevant to Loop
>>> passes
>>>        // are preserved.
>>>
>>> -      // We know that the loop pass couldn't have invalidated any other
>>> loop's
>>> -      // analyses (that's the contract of a loop pass), so directly
>>> handle the
>>> -      // loop analysis manager's invalidation here.
>>> -      LAM.invalidate(*L, PassPA);
>>> +      // If the loop hasn't been deleted, we need to handle
>>> invalidation here.
>>> +      if (!Updater.skipCurrentLoop())
>>> +        // We know that the loop pass couldn't have invalidated any
>>> other
>>> +        // loop's analyses (that's the contract of a loop pass), so
>>> directly
>>> +        // handle the loop analysis manager's invalidation here.
>>> +        LAM.invalidate(*L, PassPA);
>>>
>>>        // Then intersect the preserved set so that invalidation of module
>>>        // analyses will eventually occur when the module pass completes.
>>>        PA.intersect(std::move(PassPA));
>>> -    }
>>> +    } while (!Worklist.empty());
>>>
>>>      // By definition we preserve the proxy. We also preserve all
>>> analyses on
>>>      // Loops. This precludes *any* invalidation of loop analyses by the
>>> proxy,
>>> @@ -130,6 +428,17 @@ public:
>>>      // loop analysis manager incrementally above.
>>>      PA.preserveSet<AllAnalysesOn<Loop>>();
>>>      PA.preserve<LoopAnalysisManagerFunctionProxy>();
>>> +    // We also preserve the set of standard analyses.
>>> +    PA.preserve<AssumptionAnalysis>();
>>> +    PA.preserve<DominatorTreeAnalysis>();
>>> +    PA.preserve<LoopAnalysis>();
>>> +    PA.preserve<ScalarEvolutionAnalysis>();
>>> +    // FIXME: What we really want to do here is preserve an AA
>>> category, but
>>> +    // that concept doesn't exist yet.
>>> +    PA.preserve<AAManager>();
>>> +    PA.preserve<BasicAA>();
>>> +    PA.preserve<GlobalsAA>();
>>> +    PA.preserve<SCEVAA>();
>>>      return PA;
>>>    }
>>>
>>> @@ -144,6 +453,19 @@ FunctionToLoopPassAdaptor<LoopPassT>
>>>  createFunctionToLoopPassAdaptor(LoopPassT Pass) {
>>>    return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass));
>>>  }
>>> +
>>> +/// \brief Pass for printing a loop's contents as textual IR.
>>> +class PrintLoopPass : public PassInfoMixin<PrintLoopPass> {
>>> +  raw_ostream &OS;
>>> +  std::string Banner;
>>> +
>>> +public:
>>> +  PrintLoopPass();
>>> +  PrintLoopPass(raw_ostream &OS, const std::string &Banner = "");
>>> +
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
>>> +                        LoopStandardAnalysisResults &, LPMUpdater &);
>>> +};
>>>  }
>>>
>>>  #endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/IndVarSimplify.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/IndVarSimplify.h?rev=291651&r1=291650&r2=
>>> 291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/IndVarSimplify.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/IndVarSimplify.h Wed Jan
>>> 11 00:23:21 2017
>>> @@ -23,7 +23,8 @@ namespace llvm {
>>>
>>>  class IndVarSimplifyPass : public PassInfoMixin<IndVarSimplifyPass> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  }
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LICM.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LICM.h?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LICM.h (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LICM.h Wed Jan 11
>>> 00:23:21 2017
>>> @@ -42,7 +42,8 @@ namespace llvm {
>>>  /// Performs Loop Invariant Code Motion Pass.
>>>  class LICMPass : public PassInfoMixin<LICMPass> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopDeletion.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopDeletion.h?rev=291651&r1=291650&r2=
>>> 291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopDeletion.h (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopDeletion.h Wed Jan 11
>>> 00:23:21 2017
>>> @@ -24,7 +24,8 @@ namespace llvm {
>>>  class LoopDeletionPass : public PassInfoMixin<LoopDeletionPass> {
>>>  public:
>>>    LoopDeletionPass() {}
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>    bool runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
>>>                LoopInfo &loopInfo);
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopIdiomRecognize.h?rev=291651&r1=291650&
>>> r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h Wed
>>> Jan 11 00:23:21 2017
>>> @@ -25,7 +25,8 @@ namespace llvm {
>>>  /// Performs Loop Idiom Recognize Pass.
>>>  class LoopIdiomRecognizePass : public PassInfoMixin<LoopIdiomRecognizePass>
>>> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopInstSimplify.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopInstSimplify.h?rev=291651&r1=291650&
>>> r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopInstSimplify.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopInstSimplify.h Wed
>>> Jan 11 00:23:21 2017
>>> @@ -23,7 +23,8 @@ namespace llvm {
>>>  /// Performs Loop Inst Simplify Pass.
>>>  class LoopInstSimplifyPass : public PassInfoMixin<LoopInstSimplifyPass>
>>> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopRotation.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopRotation.h?rev=291651&r1=291650&r2=
>>> 291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopRotation.h (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopRotation.h Wed Jan 11
>>> 00:23:21 2017
>>> @@ -24,7 +24,8 @@ namespace llvm {
>>>  class LoopRotatePass : public PassInfoMixin<LoopRotatePass> {
>>>  public:
>>>    LoopRotatePass(bool EnableHeaderDuplication = true);
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>
>>>  private:
>>>    const bool EnableHeaderDuplication;
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopSimplifyCFG.h?rev=291651&r1=291650&r2=
>>> 291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h Wed Jan
>>> 11 00:23:21 2017
>>> @@ -26,7 +26,8 @@ namespace llvm {
>>>  /// Performs basic CFG simplifications to assist other loop passes.
>>>  class LoopSimplifyCFGPass : public PassInfoMixin<LoopSimplifyCFGPass> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopStrengthReduce.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopStrengthReduce.h?rev=291651&r1=291650&
>>> r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopStrengthReduce.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopStrengthReduce.h Wed
>>> Jan 11 00:23:21 2017
>>> @@ -31,7 +31,8 @@ namespace llvm {
>>>  /// Performs Loop Strength Reduce Pass.
>>>  class LoopStrengthReducePass : public PassInfoMixin<LoopStrengthReducePass>
>>> {
>>>  public:
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopUnrollPass.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>>> Transforms/Scalar/LoopUnrollPass.h?rev=291651&r1=291650&r2=
>>> 291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopUnrollPass.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopUnrollPass.h Wed Jan
>>> 11 00:23:21 2017
>>> @@ -23,7 +23,8 @@ struct LoopUnrollPass : public PassInfoM
>>>    Optional<bool> ProvidedRuntime;
>>>    Optional<bool> ProvidedUpperBound;
>>>
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
>>> +                        LoopStandardAnalysisResults &AR, LPMUpdater &U);
>>>  };
>>>  } // end namespace llvm
>>>
>>>
>>> Modified: llvm/trunk/lib/Analysis/IVUsers.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/
>>> IVUsers.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Analysis/IVUsers.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/IVUsers.cpp Wed Jan 11 00:23:21 2017
>>> @@ -36,19 +36,15 @@ using namespace llvm;
>>>
>>>  AnalysisKey IVUsersAnalysis::Key;
>>>
>>> -IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM) {
>>> -  const auto &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  return IVUsers(&L, FAM.getCachedResult<AssumptionAnalysis>(*F),
>>> -                 FAM.getCachedResult<LoopAnalysis>(*F),
>>> -                 FAM.getCachedResult<DominatorTreeAnalysis>(*F),
>>> -                 FAM.getCachedResult<ScalarEvolutionAnalysis>(*F));
>>> +IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM,
>>> +                             LoopStandardAnalysisResults &AR) {
>>> +  return IVUsers(&L, &AR.AC, &AR.LI, &AR.DT, &AR.SE);
>>>  }
>>>
>>> -PreservedAnalyses IVUsersPrinterPass::run(Loop &L, LoopAnalysisManager
>>> &AM) {
>>> -  AM.getResult<IVUsersAnalysis>(L).print(OS);
>>> +PreservedAnalyses IVUsersPrinterPass::run(Loop &L, LoopAnalysisManager
>>> &AM,
>>> +                                          LoopStandardAnalysisResults
>>> &AR,
>>> +                                          LPMUpdater &U) {
>>> +  AM.getResult<IVUsersAnalysis>(L, AR).print(OS);
>>>    return PreservedAnalyses::all();
>>>  }
>>>
>>>
>>> Modified: llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/
>>> LoopAccessAnalysis.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/LoopAccessAnalysis.cpp Wed Jan 11 00:23:21
>>> 2017
>>> @@ -2120,31 +2120,16 @@ INITIALIZE_PASS_END(LoopAccessLegacyAnal
>>>
>>>  AnalysisKey LoopAccessAnalysis::Key;
>>>
>>> -LoopAccessInfo LoopAccessAnalysis::run(Loop &L, LoopAnalysisManager
>>> &AM) {
>>> -  const FunctionAnalysisManager &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> -  Function &F = *L.getHeader()->getParent();
>>> -  auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(F);
>>> -  auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(F);
>>> -  auto *AA = FAM.getCachedResult<AAManager>(F);
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(F);
>>> -  if (!SE)
>>> -    report_fatal_error(
>>> -        "ScalarEvolution must have been cached at a higher level");
>>> -  if (!AA)
>>> -    report_fatal_error("AliasAnalysis must have been cached at a
>>> higher level");
>>> -  if (!DT)
>>> -    report_fatal_error("DominatorTree must have been cached at a
>>> higher level");
>>> -  if (!LI)
>>> -    report_fatal_error("LoopInfo must have been cached at a higher
>>> level");
>>> -  return LoopAccessInfo(&L, SE, TLI, AA, DT, LI);
>>> +LoopAccessInfo LoopAccessAnalysis::run(Loop &L, LoopAnalysisManager &AM,
>>> +                                       LoopStandardAnalysisResults &AR)
>>> {
>>> +  return LoopAccessInfo(&L, &AR.SE, &AR.TLI, &AR.AA, &AR.DT, &AR.LI);
>>>  }
>>>
>>> -PreservedAnalyses LoopAccessInfoPrinterPass::run(Loop &L,
>>> -                                                 LoopAnalysisManager
>>> &AM) {
>>> +PreservedAnalyses
>>> +LoopAccessInfoPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
>>> +                               LoopStandardAnalysisResults &AR,
>>> LPMUpdater &) {
>>>    Function &F = *L.getHeader()->getParent();
>>> -  auto &LAI = AM.getResult<LoopAccessAnalysis>(L);
>>> +  auto &LAI = AM.getResult<LoopAccessAnalysis>(L, AR);
>>>    OS << "Loop access info in function '" << F.getName() << "':\n";
>>>    OS.indent(2) << L.getHeader()->getName() << ":\n";
>>>    LAI.print(OS, 4);
>>>
>>> Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/
>>> LoopInfo.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/LoopInfo.cpp Wed Jan 11 00:23:21 2017
>>> @@ -689,18 +689,13 @@ PreservedAnalyses LoopPrinterPass::run(F
>>>    return PreservedAnalyses::all();
>>>  }
>>>
>>> -PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
>>> -PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string
>>> &Banner)
>>> -    : OS(OS), Banner(Banner) {}
>>> -
>>> -PreservedAnalyses PrintLoopPass::run(Loop &L, AnalysisManager<Loop> &) {
>>> +void llvm::printLoop(Loop &L, raw_ostream &OS, const std::string
>>> &Banner) {
>>>    OS << Banner;
>>>    for (auto *Block : L.blocks())
>>>      if (Block)
>>>        Block->print(OS);
>>>      else
>>>        OS << "Printing <null> block";
>>> -  return PreservedAnalyses::all();
>>>  }
>>>
>>>  //===------------------------------------------------------
>>> ----------------===//
>>>
>>> Modified: llvm/trunk/lib/Analysis/LoopPass.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/
>>> LoopPass.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Analysis/LoopPass.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/LoopPass.cpp Wed Jan 11 00:23:21 2017
>>> @@ -32,13 +32,14 @@ namespace {
>>>  /// PrintLoopPass - Print a Function corresponding to a Loop.
>>>  ///
>>>  class PrintLoopPassWrapper : public LoopPass {
>>> -  PrintLoopPass P;
>>> +  raw_ostream &OS;
>>> +  std::string Banner;
>>>
>>>  public:
>>>    static char ID;
>>> -  PrintLoopPassWrapper() : LoopPass(ID) {}
>>> +  PrintLoopPassWrapper() : LoopPass(ID), OS(dbgs()) {}
>>>    PrintLoopPassWrapper(raw_ostream &OS, const std::string &Banner)
>>> -      : LoopPass(ID), P(OS, Banner) {}
>>> +      : LoopPass(ID), OS(OS), Banner(Banner) {}
>>>
>>>    void getAnalysisUsage(AnalysisUsage &AU) const override {
>>>      AU.setPreservesAll();
>>> @@ -49,8 +50,7 @@ public:
>>>                         [](BasicBlock *BB) { return BB; });
>>>      if (BBI != L->blocks().end() &&
>>>          isFunctionInPrintList((*BBI)->getParent()->getName())) {
>>> -      LoopAnalysisManager DummyLAM;
>>> -      P.run(*L, DummyLAM);
>>> +      printLoop(*L, OS, Banner);
>>>      }
>>>      return false;
>>>    }
>>>
>>> Modified: llvm/trunk/lib/Analysis/LoopPassManager.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/
>>> LoopPassManager.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Analysis/LoopPassManager.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/LoopPassManager.cpp Wed Jan 11 00:23:21 2017
>>> @@ -20,34 +20,191 @@ using namespace llvm;
>>>  // Explicit template instantiations and specialization defininitions
>>> for core
>>>  // template typedefs.
>>>  namespace llvm {
>>> -template class PassManager<Loop>;
>>> -template class AnalysisManager<Loop>;
>>> +template class AllAnalysesOn<Loop>;
>>> +template class AnalysisManager<Loop, LoopStandardAnalysisResults &>;
>>> +template class PassManager<Loop, LoopAnalysisManager,
>>> +                           LoopStandardAnalysisResults &, LPMUpdater &>;
>>>  template class InnerAnalysisManagerProxy<LoopAnalysisManager,
>>> Function>;
>>> -template class OuterAnalysisManagerProxy<FunctionAnalysisManager,
>>> Loop>;
>>> +template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop,
>>> +                                         LoopStandardAnalysisResults &>;
>>>
>>> +/// Explicitly specialize the pass manager's run method to handle loop
>>> nest
>>> +/// structure updates.
>>>  template <>
>>> +PreservedAnalyses
>>> +PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
>>> +            LPMUpdater &>::run(Loop &L, LoopAnalysisManager &AM,
>>> +                               LoopStandardAnalysisResults &AR,
>>> LPMUpdater &U) {
>>> +  PreservedAnalyses PA = PreservedAnalyses::all();
>>> +
>>> +  if (DebugLogging)
>>> +    dbgs() << "Starting Loop pass manager run.\n";
>>> +
>>> +  for (auto &Pass : Passes) {
>>> +    if (DebugLogging)
>>> +      dbgs() << "Running pass: " << Pass->name() << " on " << L;
>>> +
>>> +    PreservedAnalyses PassPA = Pass->run(L, AM, AR, U);
>>> +
>>> +    // If the loop was deleted, abort the run and return to the outer
>>> walk.
>>> +    if (U.skipCurrentLoop()) {
>>> +      PA.intersect(std::move(PassPA));
>>> +      break;
>>> +    }
>>> +
>>> +    // Update the analysis manager as each pass runs and potentially
>>> +    // invalidates analyses.
>>> +    AM.invalidate(L, PassPA);
>>> +
>>> +    // Finally, we intersect the final preserved analyses to compute the
>>> +    // aggregate preserved set for this pass manager.
>>> +    PA.intersect(std::move(PassPA));
>>> +
>>> +    // FIXME: Historically, the pass managers all called the LLVM
>>> context's
>>> +    // yield function here. We don't have a generic way to acquire the
>>> +    // context and it isn't yet clear what the right pattern is for
>>> yielding
>>> +    // in the new pass manager so it is currently omitted.
>>> +    // ...getContext().yield();
>>> +  }
>>> +
>>> +  // Invalidation for the current loop should be handled above, and
>>> other loop
>>> +  // analysis results shouldn't be impacted by runs over this loop.
>>> Therefore,
>>> +  // the remaining analysis results in the AnalysisManager are
>>> preserved. We
>>> +  // mark this with a set so that we don't need to inspect each one
>>> +  // individually.
>>> +  // FIXME: This isn't correct! This loop and all nested loops'
>>> analyses should
>>> +  // be preserved, but unrolling should invalidate the parent loop's
>>> analyses.
>>> +  PA.preserveSet<AllAnalysesOn<Loop>>();
>>> +
>>> +  if (DebugLogging)
>>> +    dbgs() << "Finished Loop pass manager run.\n";
>>> +
>>> +  return PA;
>>> +}
>>> +
>>>  bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
>>>      Function &F, const PreservedAnalyses &PA,
>>>      FunctionAnalysisManager::Invalidator &Inv) {
>>> -  // If this proxy isn't marked as preserved, the set of Function
>>> objects in
>>> -  // the module may have changed. We therefore can't call
>>> -  // InnerAM->invalidate(), because any pointers to Functions it has
>>> may be
>>> -  // stale.
>>> +  // First compute the sequence of IR units covered by this proxy. We
>>> will want
>>> +  // to visit this in postorder, but because this is a tree structure
>>> we can do
>>> +  // this by building a preorder sequence and walking it in reverse.
>>> +  SmallVector<Loop *, 4> PreOrderLoops, PreOrderWorklist;
>>> +  // Note that we want to walk the roots in reverse order because we
>>> will end
>>> +  // up reversing the preorder sequence. However, it happens that the
>>> loop nest
>>> +  // roots are in reverse order within the LoopInfo object. So we just
>>> walk
>>> +  // forward here.
>>> +  // FIXME: If we change the order of LoopInfo we will want to add a
>>> reverse
>>> +  // here.
>>> +  for (Loop *RootL : *LI) {
>>> +    assert(PreOrderWorklist.empty() &&
>>> +           "Must start with an empty preorder walk worklist.");
>>> +    PreOrderWorklist.push_back(RootL);
>>> +    do {
>>> +      Loop *L = PreOrderWorklist.pop_back_val();
>>> +      PreOrderWorklist.append(L->begin(), L->end());
>>> +      PreOrderLoops.push_back(L);
>>> +    } while (!PreOrderWorklist.empty());
>>> +  }
>>> +
>>> +  // If this proxy or the loop info is going to be invalidated, we also
>>> need
>>> +  // to clear all the keys coming from that analysis. We also
>>> completely blow
>>> +  // away the loop analyses if any of the standard analyses provided by
>>> the
>>> +  // loop pass manager go away so that loop analyses can freely use
>>> these
>>> +  // without worrying about declaring dependencies on them etc.
>>> +  // FIXME: It isn't clear if this is the right tradeoff. We could
>>> instead make
>>> +  // loop analyses declare any dependencies on these and use the more
>>> general
>>> +  // invalidation logic below to act on that.
>>>    auto PAC = PA.getChecker<LoopAnalysisManagerFunctionProxy>();
>>> -  if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Loop>>())
>>> -    InnerAM->clear();
>>> +  if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>())
>>> ||
>>> +      Inv.invalidate<AAManager>(F, PA) ||
>>> +      Inv.invalidate<AssumptionAnalysis>(F, PA) ||
>>> +      Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
>>> +      Inv.invalidate<LoopAnalysis>(F, PA) ||
>>> +      Inv.invalidate<ScalarEvolutionAnalysis>(F, PA)) {
>>> +    // Note that the LoopInfo may be stale at this point, however the
>>> loop
>>> +    // objects themselves remain the only viable keys that could be in
>>> the
>>> +    // analysis manager's cache. So we just walk the keys and forcibly
>>> clear
>>> +    // those results. Note that the order doesn't matter here as this
>>> will just
>>> +    // directly destroy the results without calling methods on them.
>>> +    for (Loop *L : PreOrderLoops)
>>> +      InnerAM->clear(*L);
>>> +
>>> +    // We also need to null out the inner AM so that when the object
>>> gets
>>> +    // destroyed as invalid we don't try to clear the inner AM again.
>>> At that
>>> +    // point we won't be able to reliably walk the loops for this
>>> function and
>>> +    // only clear results associated with those loops the way we do
>>> here.
>>> +    // FIXME: Making InnerAM null at this point isn't very nice. Most
>>> analyses
>>> +    // try to remain valid during invalidation. Maybe we should add an
>>> +    // `IsClean` flag?
>>> +    InnerAM = nullptr;
>>> +
>>> +    // Now return true to indicate this *is* invalid and a fresh proxy
>>> result
>>> +    // needs to be built. This is especially important given the null
>>> InnerAM.
>>> +    return true;
>>> +  }
>>> +
>>> +  // Directly check if the relevant set is preserved so we can short
>>> circuit
>>> +  // invalidating loops.
>>> +  bool AreLoopAnalysesPreserved =
>>> +      PA.allAnalysesInSetPreserved<AllAnalysesOn<Loop>>();
>>> +
>>> +  // Since we have a valid LoopInfo we can actually leave the cached
>>> results in
>>> +  // the analysis manager associated with the Loop keys, but we need to
>>> +  // propagate any necessary invalidation logic into them. We'd like to
>>> +  // invalidate things in roughly the same order as they were put into
>>> the
>>> +  // cache and so we walk the preorder list in reverse to form a valid
>>> +  // postorder.
>>> +  for (Loop *L : reverse(PreOrderLoops)) {
>>> +    Optional<PreservedAnalyses> InnerPA;
>>> +
>>> +    // Check to see whether the preserved set needs to be adjusted
>>> based on
>>> +    // function-level analysis invalidation triggering deferred
>>> invalidation
>>> +    // for this loop.
>>> +    if (auto *OuterProxy =
>>> +            InnerAM->getCachedResult<Funct
>>> ionAnalysisManagerLoopProxy>(*L))
>>> +      for (const auto &OuterInvalidationPair :
>>> +           OuterProxy->getOuterInvalidations()) {
>>> +        AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
>>> +        const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
>>> +        if (Inv.invalidate(OuterAnalysisID, F, PA)) {
>>> +          if (!InnerPA)
>>> +            InnerPA = PA;
>>> +          for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
>>> +            InnerPA->abandon(InnerAnalysisID);
>>> +        }
>>> +      }
>>> +
>>> +    // Check if we needed a custom PA set. If so we'll need to run the
>>> inner
>>> +    // invalidation.
>>> +    if (InnerPA) {
>>> +      InnerAM->invalidate(*L, *InnerPA);
>>> +      continue;
>>> +    }
>>>
>>> -  // FIXME: Proper suppor for invalidation isn't yet implemented for
>>> the LPM.
>>> +    // Otherwise we only need to do invalidation if the original PA set
>>> didn't
>>> +    // preserve all Loop analyses.
>>> +    if (!AreLoopAnalysesPreserved)
>>> +      InnerAM->invalidate(*L, PA);
>>> +  }
>>>
>>>    // Return false to indicate that this result is still a valid proxy.
>>>    return false;
>>>  }
>>> +
>>> +template <>
>>> +LoopAnalysisManagerFunctionProxy::Result
>>> +LoopAnalysisManagerFunctionProxy::run(Function &F,
>>> +                                      FunctionAnalysisManager &AM) {
>>> +  return Result(*InnerAM, AM.getResult<LoopAnalysis>(F));
>>> +}
>>>  }
>>>
>>>  PreservedAnalyses llvm::getLoopPassPreservedAnalyses() {
>>>    PreservedAnalyses PA;
>>> +  PA.preserve<AssumptionAnalysis>();
>>>    PA.preserve<DominatorTreeAnalysis>();
>>>    PA.preserve<LoopAnalysis>();
>>> +  PA.preserve<LoopAnalysisManagerFunctionProxy>();
>>>    PA.preserve<ScalarEvolutionAnalysis>();
>>>    // TODO: What we really want to do here is preserve an AA category,
>>> but that
>>>    // concept doesn't exist yet.
>>> @@ -57,3 +214,14 @@ PreservedAnalyses llvm::getLoopPassPrese
>>>    PA.preserve<SCEVAA>();
>>>    return PA;
>>>  }
>>> +
>>> +PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
>>> +PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string
>>> &Banner)
>>> +    : OS(OS), Banner(Banner) {}
>>> +
>>> +PreservedAnalyses PrintLoopPass::run(Loop &L, LoopAnalysisManager &,
>>> +                                     LoopStandardAnalysisResults &,
>>> +                                     LPMUpdater &) {
>>> +  printLoop(L, OS, Banner);
>>> +  return PreservedAnalyses::all();
>>> +}
>>>
>>> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/Pa
>>> ssBuilder.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
>>> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Wed Jan 11 00:23:21 2017
>>> @@ -38,6 +38,7 @@
>>>  #include "llvm/Analysis/LazyValueInfo.h"
>>>  #include "llvm/Analysis/LoopAccessAnalysis.h"
>>>  #include "llvm/Analysis/LoopInfo.h"
>>> +#include "llvm/Analysis/LoopPassManager.h"
>>>  #include "llvm/Analysis/MemoryDependenceAnalysis.h"
>>>  #include "llvm/Analysis/ModuleSummaryAnalysis.h"
>>>  #include "llvm/Analysis/OptimizationDiagnosticInfo.h"
>>> @@ -220,7 +221,8 @@ public:
>>>
>>>  /// \brief No-op loop pass which does nothing.
>>>  struct NoOpLoopPass {
>>> -  PreservedAnalyses run(Loop &L, LoopAnalysisManager &) {
>>> +  PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
>>> +                        LoopStandardAnalysisResults &, LPMUpdater &) {
>>>      return PreservedAnalyses::all();
>>>    }
>>>    static StringRef name() { return "NoOpLoopPass"; }
>>> @@ -233,7 +235,9 @@ class NoOpLoopAnalysis : public Analysis
>>>
>>>  public:
>>>    struct Result {};
>>> -  Result run(Loop &, LoopAnalysisManager &) { return Result(); }
>>> +  Result run(Loop &, LoopAnalysisManager &, LoopStandardAnalysisResults
>>> &) {
>>> +    return Result();
>>> +  }
>>>    static StringRef name() { return "NoOpLoopAnalysis"; }
>>>  };
>>>
>>> @@ -1019,7 +1023,9 @@ bool PassBuilder::parseLoopPass(LoopPass
>>>  #define LOOP_ANALYSIS(NAME, CREATE_PASS)
>>>        \
>>>    if (Name == "require<" NAME ">") {
>>>        \
>>>      LPM.addPass(RequireAnalysisPass<
>>>          \
>>> -                std::remove_reference<decltype(CREATE_PASS)>::type,
>>> Loop>());  \
>>> +                std::remove_reference<decltype(CREATE_PASS)>::type,
>>> Loop,      \
>>> +                LoopAnalysisManager, LoopStandardAnalysisResults &,
>>>         \
>>> +                LPMUpdater &>());
>>>         \
>>>      return true;
>>>        \
>>>    }
>>>         \
>>>    if (Name == "invalidate<" NAME ">") {
>>>         \
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/IndVarSimplify.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -2482,23 +2482,13 @@ bool IndVarSimplify::run(Loop *L) {
>>>    return Changed;
>>>  }
>>>
>>> -PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager
>>> &AM) {
>>> -  auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).
>>> getManager();
>>> +PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager
>>> &AM,
>>> +                                          LoopStandardAnalysisResults
>>> &AR,
>>> +                                          LPMUpdater &) {
>>>    Function *F = L.getHeader()->getParent();
>>>    const DataLayout &DL = F->getParent()->getDataLayout();
>>>
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -
>>> -  assert((LI && SE && DT) &&
>>> -         "Analyses required for indvarsimplify not available!");
>>> -
>>> -  // Optional analyses.
>>> -  auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
>>> -  auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
>>> -
>>> -  IndVarSimplify IVS(LI, SE, DT, DL, TLI, TTI);
>>> +  IndVarSimplify IVS(&AR.LI, &AR.SE, &AR.DT, DL, &AR.TLI, &AR.TTI);
>>>    if (!IVS.run(&L))
>>>      return PreservedAnalyses::all();
>>>
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LICM.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Wed Jan 11 00:23:21 2017
>>> @@ -185,23 +185,20 @@ private:
>>>  };
>>>  }
>>>
>>> -PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM) {
>>> +PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
>>> +                                LoopStandardAnalysisResults &AR,
>>> LPMUpdater &) {
>>>    const auto &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> +      AM.getResult<FunctionAnalysisManagerLoopProxy>(L,
>>> AR).getManager();
>>>    Function *F = L.getHeader()->getParent();
>>>
>>> -  auto *AA = FAM.getCachedResult<AAManager>(*F);
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
>>> -  auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
>>>    auto *ORE = FAM.getCachedResult<Optimizati
>>> onRemarkEmitterAnalysis>(*F);
>>> -  assert((AA && LI && DT && TLI && SE && ORE) &&
>>> -         "Analyses for LICM not available");
>>> +  // FIXME: This should probably be optional rather than required.
>>> +  if (!ORE)
>>> +    report_fatal_error("LICM: OptimizationRemarkEmitterAnalysis not "
>>> +                       "cached at a higher level");
>>>
>>>    LoopInvariantCodeMotion LICM;
>>> -
>>> -  if (!LICM.runOnLoop(&L, AA, LI, DT, TLI, SE, ORE, true))
>>> +  if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.TLI, &AR.SE,
>>> ORE, true))
>>>      return PreservedAnalyses::all();
>>>
>>>    // FIXME: There is no setPreservesCFG in the new PM. When that becomes
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopDeletion.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -215,15 +215,10 @@ bool LoopDeletionPass::runImpl(Loop *L,
>>>    return Changed;
>>>  }
>>>
>>> -PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager
>>> &AM) {
>>> -  auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).
>>> getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  auto &DT = *FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  auto &SE = *FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
>>> -  auto &LI = *FAM.getCachedResult<LoopAnalysis>(*F);
>>> -
>>> -  bool Changed = runImpl(&L, DT, SE, LI);
>>> +PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager
>>> &AM,
>>> +                                        LoopStandardAnalysisResults &AR,
>>> +                                        LPMUpdater &) {
>>> +  bool Changed = runImpl(&L, AR.DT, AR.SE, AR.LI);
>>>    if (!Changed)
>>>      return PreservedAnalyses::all();
>>>
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopDistribute.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -946,10 +946,18 @@ PreservedAnalyses LoopDistributePass::ru
>>>    auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
>>>    auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
>>>
>>> +  // We don't directly need these analyses but they're required for loop
>>> +  // analyses so provide them below.
>>> +  auto &AA = AM.getResult<AAManager>(F);
>>> +  auto &AC = AM.getResult<AssumptionAnalysis>(F);
>>> +  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
>>> +  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
>>> +
>>>    auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).
>>> getManager();
>>>    std::function<const LoopAccessInfo &(Loop &)> GetLAA =
>>>        [&](Loop &L) -> const LoopAccessInfo & {
>>> -    return LAM.getResult<LoopAccessAnalysis>(L);
>>> +    LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI};
>>> +    return LAM.getResult<LoopAccessAnalysis>(L, AR);
>>>    };
>>>
>>>    bool Changed = runImpl(F, &LI, &DT, &SE, &ORE, GetLAA);
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopIdiomRecognize.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -186,24 +186,12 @@ public:
>>>  };
>>>  } // End anonymous namespace.
>>>
>>> -PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L,
>>> -                                              LoopAnalysisManager &AM) {
>>> -  const auto &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  // Use getCachedResult because Loop pass cannot trigger a function
>>> analysis.
>>> -  auto *AA = FAM.getCachedResult<AAManager>(*F);
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
>>> -  auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
>>> -  const auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
>>> +PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L,
>>> LoopAnalysisManager &AM,
>>> +
>>> LoopStandardAnalysisResults &AR,
>>> +                                              LPMUpdater &) {
>>>    const auto *DL = &L.getHeader()->getModule()->getDataLayout();
>>> -  assert((AA && DT && LI && SE && TLI && TTI && DL) &&
>>> -         "Analyses for Loop Idiom Recognition not available");
>>>
>>> -  LoopIdiomRecognize LIR(AA, DT, LI, SE, TLI, TTI, DL);
>>> +  LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, &AR.TLI,
>>> &AR.TTI, DL);
>>>    if (!LIR.runOnLoop(&L))
>>>      return PreservedAnalyses::all();
>>>
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopInstSimplify.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -183,20 +183,10 @@ public:
>>>  };
>>>  }
>>>
>>> -PreservedAnalyses LoopInstSimplifyPass::run(Loop &L,
>>> -                                            LoopAnalysisManager &AM) {
>>> -  const auto &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  // Use getCachedResult because Loop pass cannot trigger a function
>>> analysis.
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  auto *AC = FAM.getCachedResult<AssumptionAnalysis>(*F);
>>> -  const auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
>>> -  assert((LI && AC && TLI) && "Analyses for Loop Inst Simplify not
>>> available");
>>> -
>>> -  if (!SimplifyLoopInst(&L, DT, LI, AC, TLI))
>>> +PreservedAnalyses LoopInstSimplifyPass::run(Loop &L,
>>> LoopAnalysisManager &AM,
>>> +                                            LoopStandardAnalysisResults
>>> &AR,
>>> +                                            LPMUpdater &) {
>>> +  if (!SimplifyLoopInst(&L, &AR.DT, &AR.LI, &AR.AC, &AR.TLI))
>>>      return PreservedAnalyses::all();
>>>
>>>    return getLoopPassPreservedAnalyses();
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopRotation.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -625,20 +625,11 @@ bool LoopRotate::processLoop(Loop *L) {
>>>  LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication)
>>>      : EnableHeaderDuplication(EnableHeaderDuplication) {}
>>>
>>> -PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM)
>>> {
>>> -  auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).
>>> getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  const auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
>>> -  auto *AC = FAM.getCachedResult<AssumptionAnalysis>(*F);
>>> -  assert((LI && TTI && AC) && "Analyses for loop rotation not
>>> available");
>>> -
>>> -  // Optional analyses.
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
>>> +PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
>>> +                                      LoopStandardAnalysisResults &AR,
>>> +                                      LPMUpdater &) {
>>>    int Threshold = EnableHeaderDuplication ? DefaultRotationThreshold :
>>> 0;
>>> -  LoopRotate LR(Threshold, LI, TTI, AC, DT, SE);
>>> +  LoopRotate LR(Threshold, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE);
>>>
>>>    bool Changed = LR.processLoop(&L);
>>>    if (!Changed)
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/Scalar/LoopSimplifyCFG.cpp?rev=291651&r1=291650&r2=291651&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp Wed Jan 11
>>> 00:23:21 2017
>>> @@ -64,16 +64,10 @@ static bool simplifyLoopCFG(Loop &L, Dom
>>>    return Changed;
>>>  }
>>>
>>> -PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager
>>> &AM) {
>>> -  const auto &FAM =
>>> -      AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
>>> -  Function *F = L.getHeader()->getParent();
>>> -
>>> -  auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
>>> -  auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
>>> -  assert((LI && DT) && "Analyses for LoopSimplifyCFG not available");
>>> -
>>> -  if (!simplifyLoopCFG(L, *DT, *LI))
>>> +PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager
>>> &AM,
>>> +                                           LoopStandardAnalysisResults
>>> &AR,
>>> +                                           LPMUpdater &) {
>>> +  if (!simplifyLoopCFG(L, AR.DT, AR.LI))
>>>      return PreservedAnalyses::all();
>>>
>>
>> --
>> Mike
>> Sent from phone
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170111/4d9031ac/attachment-0001.html>


More information about the llvm-commits mailing list