[NewPassManager] Add assertions when getting statefull cached analysis.
authorAlina Sbirlea <asbirlea@google.com>
Tue, 14 Jan 2020 18:27:20 +0000 (10:27 -0800)
committerAlina Sbirlea <asbirlea@google.com>
Wed, 13 May 2020 19:38:38 +0000 (12:38 -0700)
Summary:
Analyses that are statefull should not be retrieved through a proxy from
an outer IR unit, as these analyses are only invalidated at the end of
the inner IR unit manager.
This patch disallows getting the outer manager and provides an API to
get a cached analysis through the proxy. If the analysis is not
stateless, the call to getCachedResult will assert.

Reviewers: chandlerc

Subscribers: mehdi_amini, eraman, hiraditya, zzheng, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D72893

19 files changed:
clang/test/CodeGen/thinlto-distributed-newpm.ll
llvm/include/llvm/Analysis/AliasAnalysis.h
llvm/include/llvm/Analysis/CGSCCPassManager.h
llvm/include/llvm/IR/PassManager.h
llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
llvm/lib/Analysis/CGSCCPassManager.cpp
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
llvm/lib/Transforms/IPO/Inliner.cpp
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
llvm/unittests/IR/PassManagerTest.cpp
llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp

index 5740c6f..013da3c 100644 (file)
 ; CHECK-O: Running pass: PostOrderFunctionAttrsPass on (main)
 ; CHECK-O: Invalidating all non-preserved analyses for: (main)
 ; CHECK-O: Clearing all analysis results for: main
-; CHECK-O: Invalidating analysis: FunctionAnalysisManagerCGSCCProxy on (main)
 ; CHECK-O3: Running pass: ArgumentPromotionPass on (main)
-; CHECK-O2: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
-; CHECK-O: Running analysis: FunctionAnalysisManagerCGSCCProxy on (main)
 ; CHECK-O3: Running analysis: TargetIRAnalysis on main
 ; CHECK-O: Running analysis: PassInstrumentationAnalysis on main
 ; CHECK-O3: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
index 95b4c2a..c35ee2f 100644 (file)
@@ -1185,8 +1185,8 @@ private:
   static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM,
                                     AAResults &AAResults) {
     auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
-    auto &MAM = MAMProxy.getManager();
-    if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent())) {
+    if (auto *R =
+            MAMProxy.template getCachedResult<AnalysisT>(*F.getParent())) {
       AAResults.addAAResult(*R);
       MAMProxy
           .template registerOuterAnalysisInvalidation<AnalysisT, AAManager>();
index 4c51917..b5b5868 100644 (file)
@@ -380,10 +380,15 @@ class FunctionAnalysisManagerCGSCCProxy
 public:
   class Result {
   public:
+    explicit Result() : FAM(nullptr) {}
     explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
 
+    void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
     /// Accessor for the analysis manager.
-    FunctionAnalysisManager &getManager() { return *FAM; }
+    FunctionAnalysisManager &getManager() {
+      assert(FAM);
+      return *FAM;
+    }
 
     bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
                     CGSCCAnalysisManager::Invalidator &Inv);
@@ -415,7 +420,8 @@ using CGSCCAnalysisManagerFunctionProxy =
 /// update result struct for the overall CGSCC walk.
 LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
     LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
-    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
+    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM);
 
 /// Helper to update the call graph after running a CGSCC pass.
 ///
@@ -425,7 +431,8 @@ LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
 /// update result struct for the overall CGSCC walk.
 LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
     LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
-    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
+    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM);
 
 /// Adaptor that maps from a SCC to its functions.
 ///
@@ -516,7 +523,7 @@ public:
       auto PAC = PA.getChecker<LazyCallGraphAnalysis>();
       if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
         CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N,
-                                                              AM, UR);
+                                                              AM, UR, FAM);
         assert(
             CG.lookupSCC(*N) == CurrentC &&
             "Current SCC not updated to the SCC containing the current node!");
@@ -719,6 +726,7 @@ public:
       // Update the analysis manager with each run and intersect the total set
       // of preserved analyses so we're ready to iterate.
       AM.invalidate(*C, PassPA);
+
       PA.intersect(std::move(PassPA));
     }
 
@@ -754,6 +762,10 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
   // Get the call graph for this module.
   LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
 
+  // Get Function analysis manager from its proxy.
+  FunctionAnalysisManager &FAM =
+      AM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M)->getManager();
+
   // We keep worklists to allow us to push more work onto the pass manager as
   // the passes are run.
   SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;
@@ -829,11 +841,12 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
           continue;
         }
 
-        // Ensure we can proxy analysis updates from from the CGSCC analysis
-        // manager into the Function analysis manager by getting a proxy here.
-        // FIXME: This seems like a bit of a hack. We should find a cleaner
-        // or more costructive way to ensure this happens.
-        (void)CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG);
+        // Ensure we can proxy analysis updates from the CGSCC analysis manager
+        // into the the Function analysis manager by getting a proxy here.
+        // This also needs to update the FunctionAnalysisManager, as this may be
+        // the first time we see this SCC.
+        CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+            FAM);
 
         // Each time we visit a new SCC pulled off the worklist,
         // a transformation of a child SCC may have also modified this parent
@@ -888,6 +901,13 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
           C = UR.UpdatedC ? UR.UpdatedC : C;
           RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
 
+          if (UR.UpdatedC) {
+            // If we're updating the SCC, also update the FAM inside the proxy's
+            // result.
+            CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+                FAM);
+          }
+
           // If the CGSCC pass wasn't able to provide a valid updated SCC,
           // the current SCC may simply need to be skipped if invalid.
           if (UR.InvalidatedSCCs.count(C)) {
index 89f764f..e7fb0b5 100644 (file)
@@ -799,6 +799,16 @@ public:
     return &static_cast<ResultModelT *>(ResultConcept)->Result;
   }
 
+  /// Verify that the given Result cannot be invalidated, assert otherwise.
+  template <typename PassT>
+  void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const {
+    PreservedAnalyses PA = PreservedAnalyses::none();
+    SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
+    Invalidator Inv(IsResultInvalidated, AnalysisResults);
+    assert(!Result->invalidate(IR, PA, Inv) &&
+           "Cached result cannot be invalidated");
+  }
+
   /// Register an analysis pass with the manager.
   ///
   /// The parameter is a callable whose result is an analysis pass. This allows
@@ -1064,7 +1074,24 @@ public:
   public:
     explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
 
-    const AnalysisManagerT &getManager() const { return *OuterAM; }
+    /// Get a cached analysis. If the analysis can be invalidated, this will
+    /// assert.
+    template <typename PassT, typename IRUnitTParam>
+    typename PassT::Result *getCachedResult(IRUnitTParam &IR) const {
+      typename PassT::Result *Res =
+          OuterAM->template getCachedResult<PassT>(IR);
+      if (Res)
+        OuterAM->template verifyNotInvalidated<PassT>(IR, Res);
+      return Res;
+    }
+
+    /// Method provided for unit testing, not intended for general use.
+    template <typename PassT, typename IRUnitTParam>
+    bool cachedResultExists(IRUnitTParam &IR) const {
+      typename PassT::Result *Res =
+          OuterAM->template getCachedResult<PassT>(IR);
+      return Res != nullptr;
+    }
 
     /// When invalidation occurs, remove any registered invalidation events.
     bool invalidate(
index 728028d..6103859 100644 (file)
@@ -49,6 +49,7 @@ class CallGraphUpdater {
   LazyCallGraph::SCC *SCC = nullptr;
   CGSCCAnalysisManager *AM = nullptr;
   CGSCCUpdateResult *UR = nullptr;
+  FunctionAnalysisManager *FAM = nullptr;
   ///}
 
 public:
@@ -68,6 +69,8 @@ public:
     this->SCC = &SCC;
     this->AM = &AM;
     this->UR = &UR;
+    FAM =
+        &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(SCC, LCG).getManager();
   }
   ///}
 
index d4d9658..64bd6df 100644 (file)
@@ -68,6 +68,10 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
   // a pointer that we can update.
   LazyCallGraph::SCC *C = &InitialC;
 
+  // Get Function analysis manager from its proxy.
+  FunctionAnalysisManager &FAM =
+      AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*C)->getManager();
+
   for (auto &Pass : Passes) {
     if (DebugLogging)
       dbgs() << "Running pass: " << Pass->name() << " on " << *C << "\n";
@@ -90,6 +94,12 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
 
     // Update the SCC if necessary.
     C = UR.UpdatedC ? UR.UpdatedC : C;
+    if (UR.UpdatedC) {
+      // If C is updated, also create a proxy and update FAM inside the result.
+      auto *ResultFAMCP =
+          &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+      ResultFAMCP->updateFAM(FAM);
+    }
 
     // If the CGSCC pass wasn't able to provide a valid updated SCC, the
     // current SCC may simply need to be skipped if invalid.
@@ -223,23 +233,22 @@ FunctionAnalysisManagerCGSCCProxy::Result
 FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C,
                                        CGSCCAnalysisManager &AM,
                                        LazyCallGraph &CG) {
-  // Collect the FunctionAnalysisManager from the Module layer and use that to
-  // build the proxy result.
-  //
-  // This allows us to rely on the FunctionAnalysisMangaerModuleProxy to
-  // invalidate the function analyses.
-  auto &MAM = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
+  // Note: unconditionally getting checking that the proxy exists may get it at
+  // this point. There are cases when this is being run unnecessarily, but
+  // it is cheap and having the assertion in place is more valuable.
+  auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
   Module &M = *C.begin()->getFunction().getParent();
-  auto *FAMProxy = MAM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M);
-  assert(FAMProxy && "The CGSCC pass manager requires that the FAM module "
-                     "proxy is run on the module prior to entering the CGSCC "
-                     "walk.");
-
-  // Note that we special-case invalidation handling of this proxy in the CGSCC
-  // analysis manager's Module proxy. This avoids the need to do anything
-  // special here to recompute all of this if ever the FAM's module proxy goes
-  // away.
-  return Result(FAMProxy->getManager());
+  bool ProxyExists =
+      MAMProxy.cachedResultExists<FunctionAnalysisManagerModuleProxy>(M);
+  assert(ProxyExists &&
+         "The CGSCC pass manager requires that the FAM module proxy is run "
+         "on the module prior to entering the CGSCC walk");
+  (void)ProxyExists;
+
+  // We just return an empty result. The caller will use the updateFAM interface
+  // to correctly register the relevant FunctionAnalysisManager based on the
+  // context in which this proxy is run.
+  return Result();
 }
 
 bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
@@ -249,8 +258,8 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
   if (PA.areAllPreserved())
     return false; // This is still a valid proxy.
 
-  // If this proxy isn't marked as preserved, then even if the result remains
-  // valid, the key itself may no longer be valid, so we clear everything.
+  // All updates to preserve valid results are done below, so we don't need to
+  // invalidate this proxy.
   //
   // Note that in order to preserve this proxy, a module pass must ensure that
   // the FAM has been completely updated to handle the deletion of functions.
@@ -262,7 +271,7 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
     for (LazyCallGraph::Node &N : C)
       FAM->clear(N.getFunction(), N.getFunction().getName());
 
-    return true;
+    return false;
   }
 
   // Directly check if the relevant set is preserved.
@@ -311,9 +320,10 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
 
 } // end namespace llvm
 
-/// When a new SCC is created for the graph and there might be function
-/// analysis results cached for the functions now in that SCC two forms of
-/// updates are required.
+/// When a new SCC is created for the graph we first update the
+/// FunctionAnalysisManager in the Proxy's result.
+/// As there might be function analysis results cached for the functions now in
+/// that SCC, two forms of  updates are required.
 ///
 /// First, a proxy from the SCC to the FunctionAnalysisManager needs to be
 /// created so that any subsequent invalidation events to the SCC are
@@ -325,10 +335,9 @@ bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
 /// function analyses so that they don't retain stale handles.
 static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C,
                                          LazyCallGraph &G,
-                                         CGSCCAnalysisManager &AM) {
-  // Get the relevant function analysis manager.
-  auto &FAM =
-      AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).getManager();
+                                         CGSCCAnalysisManager &AM,
+                                         FunctionAnalysisManager &FAM) {
+  AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).updateFAM(FAM);
 
   // Now walk the functions in this SCC and invalidate any function analysis
   // results that might have outer dependencies on an SCC analysis.
@@ -392,8 +401,10 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
 
   // If we had a cached FAM proxy originally, we will want to create more of
   // them for each SCC that was split off.
-  bool NeedFAMProxy =
-      AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC) != nullptr;
+  FunctionAnalysisManager *FAM = nullptr;
+  if (auto *FAMProxy =
+          AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC))
+    FAM = &FAMProxy->getManager();
 
   // We need to propagate an invalidation call to all but the newly current SCC
   // because the outer pass manager won't do that for us after splitting them.
@@ -407,8 +418,8 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
   AM.invalidate(*OldC, PA);
 
   // Ensure the now-current SCC's function analyses are updated.
-  if (NeedFAMProxy)
-    updateNewSCCFunctionAnalyses(*C, G, AM);
+  if (FAM)
+    updateNewSCCFunctionAnalyses(*C, G, AM, *FAM);
 
   for (SCC &NewC : llvm::reverse(make_range(std::next(NewSCCRange.begin()),
                                             NewSCCRange.end()))) {
@@ -418,8 +429,8 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
     LLVM_DEBUG(dbgs() << "Enqueuing a newly formed SCC:" << NewC << "\n");
 
     // Ensure new SCCs' function analyses are updated.
-    if (NeedFAMProxy)
-      updateNewSCCFunctionAnalyses(NewC, G, AM);
+    if (FAM)
+      updateNewSCCFunctionAnalyses(NewC, G, AM, *FAM);
 
     // Also propagate a normal invalidation to the new SCC as only the current
     // will get one from the pass manager infrastructure.
@@ -430,7 +441,8 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
 
 static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
     LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
-    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, bool FunctionPass) {
+    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM, bool FunctionPass) {
   using Node = LazyCallGraph::Node;
   using Edge = LazyCallGraph::Edge;
   using SCC = LazyCallGraph::SCC;
@@ -686,7 +698,7 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
       // analysis manager, we need to create a proxy in the new current SCC as
       // the invalidated SCCs had their functions moved.
       if (HasFunctionAnalysisProxy)
-        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G).updateFAM(FAM);
 
       // Any analyses cached for this SCC are no longer precise as the shape
       // has changed by introducing this cycle. However, we have taken care to
@@ -738,13 +750,15 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
 
 LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForFunctionPass(
     LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
-    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
-  return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR,
+    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM) {
+  return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,
                                            /* FunctionPass */ true);
 }
 LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForCGSCCPass(
     LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
-    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
-  return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR,
+    CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM) {
+  return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,
                                            /* FunctionPass */ false);
 }
index 1e0bdc1..e1ac5e9 100644 (file)
@@ -1470,7 +1470,8 @@ updateCallGraphAfterCoroutineSplit(Function &F, const coro::Shape &Shape,
 static void updateCallGraphAfterCoroutineSplit(
     LazyCallGraph::Node &N, const coro::Shape &Shape,
     const SmallVectorImpl<Function *> &Clones, LazyCallGraph::SCC &C,
-    LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
+    LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+    FunctionAnalysisManager &FAM) {
   if (!Shape.CoroBegin)
     return;
 
@@ -1501,7 +1502,7 @@ static void updateCallGraphAfterCoroutineSplit(
   // update of its own. Function passes run by the adaptor are not permitted to
   // add new edges of any kind to the graph, and the new edges inserted by this
   // pass would be misattributed to that unrelated function pass.
-  updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR);
+  updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM);
 }
 
 // When we see the coroutine the first time, we insert an indirect call to a
@@ -1647,6 +1648,9 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
   //     non-zero number of nodes, so we assume that here and grab the first
   //     node's function's module.
   Module &M = *C.begin()->getFunction().getParent();
+  auto &FAM =
+      AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+
   if (!declaresCoroSplitIntrinsics(M))
     return PreservedAnalyses::all();
 
@@ -1695,7 +1699,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
 
     SmallVector<Function *, 4> Clones;
     const coro::Shape Shape = splitCoroutine(F, Clones);
-    updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR);
+    updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM);
   }
 
   if (PrepareFn)
index 336dca8..e18039e 100644 (file)
@@ -667,13 +667,13 @@ InlinerPass::~InlinerPass() {
 PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
                                    CGSCCAnalysisManager &AM, LazyCallGraph &CG,
                                    CGSCCUpdateResult &UR) {
-  const ModuleAnalysisManager &MAM =
-      AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG).getManager();
+  const auto &MAMProxy =
+      AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
   bool Changed = false;
 
   assert(InitialC.size() > 0 && "Cannot handle an empty SCC!");
   Module &M = *InitialC.begin()->getFunction().getParent();
-  ProfileSummaryInfo *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(M);
+  ProfileSummaryInfo *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(M);
 
   if (!ImportedFunctionsStats &&
       InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
@@ -779,16 +779,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
 
     LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n");
 
-    // Get a FunctionAnalysisManager via a proxy for this particular node. We
-    // do this each time we visit a node as the SCC may have changed and as
-    // we're going to mutate this particular function we want to make sure the
-    // proxy is in place to forward any invalidation events. We can use the
-    // manager we get here for looking up results for functions other than this
-    // node however because those functions aren't going to be mutated by this
-    // pass.
-    FunctionAnalysisManager &FAM =
-        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).getManager();
-
     // Get the remarks emission analysis for the caller.
     auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
 
@@ -968,8 +958,13 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
     // essentially do all of the same things as a function pass and we can
     // re-use the exact same logic for updating the call graph to reflect the
     // change.
+
+    // Inside the update, we also update the FunctionAnalysisManager in the
+    // proxy for this particular SCC. We do this as the SCC may have changed and
+    // as we're going to mutate this particular function we want to make sure
+    // the proxy is in place to forward any invalidation events.
     LazyCallGraph::SCC *OldC = C;
-    C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR);
+    C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR, FAM);
     LLVM_DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n");
     RC = &C->getOuterRefSCC();
 
@@ -1015,8 +1010,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
     // Get the necessary information out of the call graph and nuke the
     // function there. Also, cclear out any cached analyses.
     auto &DeadC = *CG.lookupSCC(*CG.lookup(*DeadF));
-    FunctionAnalysisManager &FAM =
-        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(DeadC, CG).getManager();
     FAM.clear(*DeadF, DeadF->getName());
     AM.clear(DeadC, DeadC.getName());
     auto &DeadRC = DeadC.getOuterRefSCC();
index 8464826..afdff91 100644 (file)
@@ -3723,10 +3723,9 @@ PreservedAnalyses InstCombinePass::run(Function &F,
   auto *LI = AM.getCachedResult<LoopAnalysis>(F);
 
   auto *AA = &AM.getResult<AAManager>(F);
-  const ModuleAnalysisManager &MAM =
-      AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+  auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
   ProfileSummaryInfo *PSI =
-      MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+      MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
   auto *BFI = (PSI && PSI->hasProfileSummary()) ?
       &AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
 
index 93326c8..1d679ff 100644 (file)
@@ -1170,9 +1170,8 @@ AddressSanitizerPass::AddressSanitizerPass(bool CompileKernel, bool Recover,
 PreservedAnalyses AddressSanitizerPass::run(Function &F,
                                             AnalysisManager<Function> &AM) {
   auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
-  auto &MAM = MAMProxy.getManager();
   Module &M = *F.getParent();
-  if (auto *R = MAM.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
+  if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
     const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F);
     AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope);
     if (Sanitizer.instrumentFunction(F, TLI))
index 420baf1..a99c58b 100644 (file)
@@ -2093,8 +2093,7 @@ PreservedAnalyses ControlHeightReductionPass::run(
   auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
   auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
   auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
-  auto &MAM = MAMProxy.getManager();
-  auto &PSI = *MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+  auto &PSI = *MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
   auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
   bool Changed = CHR(F, BFI, DT, PSI, RI, ORE).run();
index c72ce92..fa3bc5f 100644 (file)
@@ -979,8 +979,8 @@ PreservedAnalyses ConstantHoistingPass::run(Function &F,
   auto BFI = ConstHoistWithBlockFrequency
                  ? &AM.getResult<BlockFrequencyAnalysis>(F)
                  : nullptr;
-  auto &MAM = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-  auto *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+  auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+  auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
   if (!runImpl(F, TTI, DT, BFI, F.getEntryBlock(), PSI))
     return PreservedAnalyses::all();
 
index c98d652..989653d 100644 (file)
@@ -696,8 +696,8 @@ PreservedAnalyses LoopLoadEliminationPass::run(Function &F,
   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
   auto &AA = AM.getResult<AAManager>(F);
   auto &AC = AM.getResult<AssumptionAnalysis>(F);
-  auto &MAM = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-  auto *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+  auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+  auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
   auto *BFI = (PSI && PSI->hasProfileSummary()) ?
       &AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
   MemorySSA *MSSA = EnableMSSALoopDependency
index 0406592..e94eb40 100644 (file)
@@ -1409,10 +1409,9 @@ PreservedAnalyses LoopUnrollPass::run(Function &F,
   if (auto *LAMProxy = AM.getCachedResult<LoopAnalysisManagerFunctionProxy>(F))
     LAM = &LAMProxy->getManager();
 
-  const ModuleAnalysisManager &MAM =
-      AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+  auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
   ProfileSummaryInfo *PSI =
-      MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+      MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
   auto *BFI = (PSI && PSI->hasProfileSummary()) ?
       &AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
 
index 8060e50..cded14b 100644 (file)
@@ -92,7 +92,7 @@ void CallGraphUpdater::reanalyzeFunction(Function &Fn) {
   } else if (LCG) {
     LazyCallGraph::Node &N = LCG->get(Fn);
     LazyCallGraph::SCC *C = LCG->lookupSCC(N);
-    updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR);
+    updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
   }
 }
 
index f05a226..4159042 100644 (file)
@@ -8072,10 +8072,9 @@ PreservedAnalyses LoopVectorizePass::run(Function &F,
       LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI, MSSA};
       return LAM.getResult<LoopAccessAnalysis>(L, AR);
     };
-    const ModuleAnalysisManager &MAM =
-        AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+    auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
     ProfileSummaryInfo *PSI =
-        MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+        MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
     LoopVectorizeResult Result =
         runImpl(F, SE, LI, TTI, DT, BFI, &TLI, DB, AA, AC, GetLAA, ORE, PSI);
     if (!Result.MadeAnyChange)
index 15e8164..7a9e588 100644 (file)
@@ -304,15 +304,28 @@ TEST_F(CGSCCPassManagerTest, Basic) {
                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
         ++SCCPassRunCount1;
 
-        const ModuleAnalysisManager &MAM =
-            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
-        FunctionAnalysisManager &FAM =
-            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+        // Note: The proper way to get to a module pass from a CGSCC pass is
+        // through the ModuleAnalysisManagerCGSCCProxy:
+        // ```
+        // const auto &MAMProxy =
+        //    AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+        // ```
+        // However getting a stateful analysis is incorrect usage, and the call
+        // to getCachedResult below asserts:
+        // ```
+        // if (TestModuleAnalysis::Result *TMA =
+        //        MAMProxy.getCachedResult<TestModuleAnalysis>(
+        //            *C.begin()->getFunction().getParent()))
+        //   AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
+        // ```
+        // For the purposes of this unittest, use the above MAM directly.
         if (TestModuleAnalysis::Result *TMA =
                 MAM.getCachedResult<TestModuleAnalysis>(
                     *C.begin()->getFunction().getParent()))
           AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
 
+        FunctionAnalysisManager &FAM =
+            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
         TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
         AnalyzedSCCFunctionCount1 += AR.FunctionCount;
         for (LazyCallGraph::Node &N : C) {
@@ -376,19 +389,16 @@ TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
   // required module pass above.
   CGSCCPassManager CGPM1(/*DebugLogging*/ true);
   int CountFoundModuleAnalysis1 = 0;
-  CGPM1.addPass(
-      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
-                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
-            *C.begin()->getFunction().getParent());
-
-        if (TMA)
-          ++CountFoundModuleAnalysis1;
-
-        return PreservedAnalyses::all();
-      }));
+  CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
+                                  CGSCCAnalysisManager &AM, LazyCallGraph &CG,
+                                  CGSCCUpdateResult &UR) {
+    const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+    if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+            *C.begin()->getFunction().getParent()))
+      ++CountFoundModuleAnalysis1;
+
+    return PreservedAnalyses::all();
+  }));
   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
 
   // The second CGSCC run checks that the module analysis got preserved the
@@ -398,12 +408,10 @@ TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
   CGPM2.addPass(
       LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                         LazyCallGraph &CG, CGSCCUpdateResult &UR) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
-            *C.begin()->getFunction().getParent());
-
-        if (TMA)
+        const auto &MAMProxy =
+            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+        if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+                *C.begin()->getFunction().getParent()))
           ++CountFoundModuleAnalysis2;
 
         // Only fail to preserve analyses on one SCC and make sure that gets
@@ -417,19 +425,16 @@ TEST_F(CGSCCPassManagerTest, TestSCCPassInvalidatesModuleAnalysis) {
   // should have been invalidated by the above CGSCC run.
   CGSCCPassManager CGPM3(/*DebugLogging*/ true);
   int CountFoundModuleAnalysis3 = 0;
-  CGPM3.addPass(
-      LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
-                        LazyCallGraph &CG, CGSCCUpdateResult &UR) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
-            *C.begin()->getFunction().getParent());
-
-        if (TMA)
-          ++CountFoundModuleAnalysis3;
+  CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
+                                  CGSCCAnalysisManager &AM, LazyCallGraph &CG,
+                                  CGSCCUpdateResult &UR) {
+    const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+    if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+            *C.begin()->getFunction().getParent()))
+      ++CountFoundModuleAnalysis3;
 
-        return PreservedAnalyses::none();
-      }));
+    return PreservedAnalyses::none();
+  }));
   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
 
   MPM.run(*M, MAM);
@@ -456,17 +461,14 @@ TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysi
   // Start true and mark false if we ever failed to find a module analysis
   // because we expect this to succeed for each SCC.
   bool FoundModuleAnalysis1 = true;
-  FPM1.addPass(
-      LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
+  FPM1.addPass(LambdaFunctionPass([&](Function &F,
+                                      FunctionAnalysisManager &AM) {
+    const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+    if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+      FoundModuleAnalysis1 = false;
 
-        if (!TMA)
-          FoundModuleAnalysis1 = false;
-
-        return PreservedAnalyses::all();
-      }));
+    return PreservedAnalyses::all();
+  }));
   CGSCCPassManager CGPM1(/*DebugLogging*/ true);
   CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
@@ -477,20 +479,17 @@ TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysi
   // Again, start true and mark false if we ever failed to find a module analysis
   // because we expect this to succeed for each SCC.
   bool FoundModuleAnalysis2 = true;
-  FPM2.addPass(
-      LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
-
-        if (!TMA)
-          FoundModuleAnalysis2 = false;
-
-        // Only fail to preserve analyses on one SCC and make sure that gets
-        // propagated.
-        return F.getName() == "h2" ? PreservedAnalyses::none()
-                                   : PreservedAnalyses::all();
-      }));
+  FPM2.addPass(LambdaFunctionPass([&](Function &F,
+                                      FunctionAnalysisManager &AM) {
+    const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+    if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+      FoundModuleAnalysis2 = false;
+
+    // Only fail to preserve analyses on one SCC and make sure that gets
+    // propagated.
+    return F.getName() == "h2" ? PreservedAnalyses::none()
+                               : PreservedAnalyses::all();
+  }));
   CGSCCPassManager CGPM2(/*DebugLogging*/ true);
   CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
@@ -501,17 +500,14 @@ TEST_F(CGSCCPassManagerTest, TestFunctionPassInsideCGSCCInvalidatesModuleAnalysi
   // Start false and mark true if we ever *succeeded* to find a module
   // analysis, as we expect this to fail for every function.
   bool FoundModuleAnalysis3 = false;
-  FPM3.addPass(
-      LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
-        const auto &MAM =
-            AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-        auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
+  FPM3.addPass(LambdaFunctionPass([&](Function &F,
+                                      FunctionAnalysisManager &AM) {
+    const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+    if (MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+      FoundModuleAnalysis3 = true;
 
-        if (TMA)
-          FoundModuleAnalysis3 = true;
-
-        return PreservedAnalyses::none();
-      }));
+    return PreservedAnalyses::none();
+  }));
   CGSCCPassManager CGPM3(/*DebugLogging*/ true);
   CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
   MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
@@ -880,7 +876,8 @@ struct TestIndirectSCCAnalysis
     }
   };
 
-  TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
+  TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM)
+      : Runs(Runs), MAM(MAM) {}
 
   /// Run the analysis pass over the function and return a result.
   Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
@@ -889,9 +886,11 @@ struct TestIndirectSCCAnalysis
     auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
 
     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
-    const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
     // For the test, we insist that the module analysis starts off in the
-    // cache.
+    // cache. Getting a cached result that isn't stateless triggers an assert.
+    // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
+    //  *C.begin()->getFunction().getParent());
+    // Use MAM, for the purposes of this unittest.
     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
         *C.begin()->getFunction().getParent());
     // Register the dependency as module analysis dependencies have to be
@@ -907,6 +906,7 @@ private:
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
 };
 
 AnalysisKey TestIndirectSCCAnalysis::Key;
@@ -974,7 +974,9 @@ struct TestIndirectFunctionAnalysis
     }
   };
 
-  TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
+  TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM,
+                               CGSCCAnalysisManager &CGAM)
+      : Runs(Runs), MAM(MAM), CGAM(CGAM) {}
 
   /// Run the analysis pass over the function and return a result.
   Result run(Function &F, FunctionAnalysisManager &AM) {
@@ -982,21 +984,23 @@ struct TestIndirectFunctionAnalysis
     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
 
     auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
-    const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
     // For the test, we insist that the module analysis starts off in the
-    // cache.
+    // cache. Getting a cached result that isn't stateless triggers an assert.
+    // Use MAM, for the purposes of this unittest.
     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
     // Register the dependency as module analysis dependencies have to be
     // pre-registered on the proxy.
     ModuleProxy.registerOuterAnalysisInvalidation<
         TestModuleAnalysis, TestIndirectFunctionAnalysis>();
 
-    // For thet test we assume this is run inside a CGSCC pass manager.
+    // For the test we assume this is run inside a CGSCC pass manager.
+    // Use MAM, for the purposes of this unittest.
     const LazyCallGraph &CG =
         *MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
     auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
-    const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
     // For the test, we insist that the CGSCC analysis starts off in the cache.
+    // Getting a cached result that isn't stateless triggers an assert.
+    // Use CGAM, for the purposes of this unittest.
     auto &SCCDep =
         *CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
     // Register the dependency as CGSCC analysis dependencies have to be
@@ -1012,6 +1016,8 @@ private:
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
+  CGSCCAnalysisManager &CGAM;
 };
 
 AnalysisKey TestIndirectFunctionAnalysis::Key;
@@ -1024,7 +1030,7 @@ TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
       DoublyIndirectSCCAnalysisRuns = 0;
   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
   CGAM.registerPass(
-      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
   CGAM.registerPass([&] {
     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
   });
@@ -1032,7 +1038,8 @@ TEST_F(CGSCCPassManagerTest, TestIndirectAnalysisInvalidation) {
   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
   FAM.registerPass([&] {
-    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+                                        CGAM);
   });
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1142,7 +1149,7 @@ TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
       DoublyIndirectSCCAnalysisRuns = 0;
   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
   CGAM.registerPass(
-      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
   CGAM.registerPass([&] {
     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
   });
@@ -1150,7 +1157,8 @@ TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
   FAM.registerPass([&] {
-    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+                                        CGAM);
   });
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1199,7 +1207,7 @@ TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
 
         // Now update the call graph.
         auto &NewC =
-            updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
+            updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
         assert(&NewC != &C && "Should get a new SCC due to update!");
         (void)&NewC;
 
@@ -1245,7 +1253,7 @@ TEST_F(CGSCCPassManagerTest, TestAnalysisInvalidationCGSCCUpdate) {
 
         // Now update the call graph.
         auto &NewC =
-            updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
+            updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
         assert(&NewC != &C && "Should get a new SCC due to update!");
         (void)&NewC;
 
@@ -1337,6 +1345,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) {
         if (C.getName() != "(h3, h1, h2)")
           return;
 
+        auto &FAM =
+            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
         Function *FnX = M->getFunction("x");
         Function *FnH1 = M->getFunction("h1");
         Function *FnH2 = M->getFunction("h2");
@@ -1355,7 +1365,7 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses0) {
         auto &H2N = *llvm::find_if(
             C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
         ASSERT_NO_FATAL_FAILURE(
-            updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR));
+            updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM));
       }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1372,6 +1382,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) {
     if (C.getName() != "(h3, h1, h2)")
       return;
 
+    auto &FAM =
+        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
     Function *FnX = M->getFunction("x");
     Function *FnH1 = M->getFunction("h1");
     Function *FnH2 = M->getFunction("h2");
@@ -1389,8 +1401,9 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses1) {
 
     auto &H2N = *llvm::find_if(
         C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
-    ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR),
-                 "Any new calls should be modeled as");
+    ASSERT_DEATH(
+        updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM),
+        "Any new calls should be modeled as");
   }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1406,6 +1419,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) {
         if (C.getName() != "(f)")
           return;
 
+        auto &FAM =
+            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
         Function *FnF = M->getFunction("f");
         Function *FnH2 = M->getFunction("h2");
         ASSERT_NE(FnF, nullptr);
@@ -1418,7 +1433,7 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses2) {
         auto &FN = *llvm::find_if(
             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
         ASSERT_NO_FATAL_FAILURE(
-            updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR));
+            updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
       }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1435,6 +1450,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) {
     if (C.getName() != "(f)")
       return;
 
+    auto &FAM =
+        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
     Function *FnF = M->getFunction("f");
     Function *FnH2 = M->getFunction("h2");
     ASSERT_NE(FnF, nullptr);
@@ -1446,8 +1463,9 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses3) {
 
     auto &FN = *llvm::find_if(
         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
-    ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR),
-                 "Any new calls should be modeled as");
+    ASSERT_DEATH(
+        updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
+        "Any new calls should be modeled as");
   }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1463,6 +1481,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) {
         if (C.getName() != "(f)")
           return;
 
+        auto &FAM =
+            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
         Function *FnF = M->getFunction("f");
         Function *FnewF = Function::Create(FnF->getFunctionType(),
                                            FnF->getLinkage(), "newF", *M);
@@ -1483,7 +1503,7 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses4) {
             C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
 
         ASSERT_NO_FATAL_FAILURE(
-            updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR));
+            updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
       }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1500,6 +1520,8 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) {
     if (C.getName() != "(f)")
       return;
 
+    auto &FAM =
+        AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
     Function *FnF = M->getFunction("f");
     Function *FnewF =
         Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M);
@@ -1519,8 +1541,9 @@ TEST_F(CGSCCPassManagerTest, TestUpdateCGAndAnalysisManagerForPasses5) {
     auto &FN = *llvm::find_if(
         C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
 
-    ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR),
-                 "Any new calls should be modeled as");
+    ASSERT_DEATH(
+        updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
+        "Any new calls should be modeled as");
   }));
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1701,6 +1724,9 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewRefSCC) {
   CGPM.addPass(LambdaSCCPassNoPreserve(
       [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
           CGSCCUpdateResult &UR) {
+        auto &FAM =
+            AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+
         for (auto &N : C) {
           auto &F = N.getFunction();
           if (F.getName() != "f")
@@ -1728,7 +1754,7 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewRefSCC) {
                                             "f.ref", &*F.begin()->begin());
 
           ASSERT_NO_FATAL_FAILURE(
-              updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR))
+              updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM))
               << "Updating the call graph with a demoted, self-referential "
                  "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
                  "caused a fatal failure";
index 5b1f902..4924dec 100644 (file)
@@ -107,20 +107,23 @@ struct TestPreservingModulePass : PassInfoMixin<TestPreservingModulePass> {
 
 struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
   TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
-                   int &AnalyzedFunctionCount,
+                   int &AnalyzedFunctionCount, ModuleAnalysisManager &MAM,
                    bool OnlyUseCachedResults = false)
       : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
-        AnalyzedFunctionCount(AnalyzedFunctionCount),
+        AnalyzedFunctionCount(AnalyzedFunctionCount), MAM(MAM),
         OnlyUseCachedResults(OnlyUseCachedResults) {}
 
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
     ++RunCount;
 
-    const ModuleAnalysisManager &MAM =
-        AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+    // Getting a cached result that isn't stateless through the proxy will
+    // trigger an assert:
+    // auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+    // Use MAM, for the purposes of this unittest.
     if (TestModuleAnalysis::Result *TMA =
-            MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
+            MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) {
       AnalyzedFunctionCount += TMA->FunctionCount;
+    }
 
     if (OnlyUseCachedResults) {
       // Hack to force the use of the cached interface.
@@ -139,6 +142,7 @@ struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
   int &RunCount;
   int &AnalyzedInstrCount;
   int &AnalyzedFunctionCount;
+  ModuleAnalysisManager &MAM;
   bool OnlyUseCachedResults;
 };
 
@@ -436,8 +440,9 @@ TEST_F(PassManagerTest, Basic) {
     {
       // Pointless scope to test move assignment.
       FunctionPassManager NestedFPM(/*DebugLogging*/ true);
-      NestedFPM.addPass(TestFunctionPass(
-          FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
+      NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1,
+                                         AnalyzedInstrCount1,
+                                         AnalyzedFunctionCount1, MAM));
       FPM = std::move(NestedFPM);
     }
     NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
@@ -455,7 +460,7 @@ TEST_F(PassManagerTest, Basic) {
   {
     FunctionPassManager FPM(/*DebugLogging*/ true);
     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
-                                 AnalyzedFunctionCount2));
+                                 AnalyzedFunctionCount2, MAM));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
 
@@ -468,7 +473,7 @@ TEST_F(PassManagerTest, Basic) {
   {
     FunctionPassManager FPM(/*DebugLogging*/ true);
     FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
-                                 AnalyzedFunctionCount3));
+                                 AnalyzedFunctionCount3, MAM));
     FPM.addPass(TestInvalidationFunctionPass("f"));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
@@ -482,7 +487,7 @@ TEST_F(PassManagerTest, Basic) {
   {
     FunctionPassManager FPM;
     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
-                                 AnalyzedFunctionCount4));
+                                 AnalyzedFunctionCount4, MAM));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
 
@@ -495,7 +500,7 @@ TEST_F(PassManagerTest, Basic) {
     FunctionPassManager FPM(/*DebugLogging*/ true);
     FPM.addPass(TestInvalidationFunctionPass("f"));
     FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
-                                 AnalyzedFunctionCount5,
+                                 AnalyzedFunctionCount5, MAM,
                                  /*OnlyUseCachedResults=*/true));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
@@ -612,21 +617,22 @@ struct TestIndirectFunctionAnalysis
     }
   };
 
-  TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
+  TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM)
+      : Runs(Runs), MAM(MAM) {}
 
   /// Run the analysis pass over the function and return a result.
   Result run(Function &F, FunctionAnalysisManager &AM) {
     ++Runs;
     auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
-    auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
-    const ModuleAnalysisManager &MAM = Proxy.getManager();
+    auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
     // For the test, we insist that the module analysis starts off in the
-    // cache.
+    // cache. Getting a cached result that isn't stateless trigger an assert.
+    // Use MAM, for the purposes of this unittest.
     auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
     // And register the dependency as module analysis dependencies have to be
     // pre-registered on the proxy.
-    Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
-                                            TestIndirectFunctionAnalysis>();
+    MAMProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
+                                               TestIndirectFunctionAnalysis>();
     return Result(FDep, MDep);
   }
 
@@ -635,6 +641,7 @@ private:
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
 };
 
 AnalysisKey TestIndirectFunctionAnalysis::Key;
@@ -693,16 +700,16 @@ struct LambdaPass : public PassInfoMixin<LambdaPass> {
 
 TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
   FunctionAnalysisManager FAM(/*DebugLogging*/ true);
+  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
   int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
       IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
   FAM.registerPass(
-      [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
+      [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns, MAM); });
   FAM.registerPass([&] {
     return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
   });
 
-  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
   MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
   MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
index 9926396..cecc6ff 100644 (file)
@@ -779,9 +779,11 @@ TEST_F(LoopPassManagerTest, IndirectOuterPassInvalidation) {
       .WillByDefault(Invoke([&](Loop &L, LoopAnalysisManager &AM,
                                 LoopStandardAnalysisResults &AR) {
         auto &FAMP = AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR);
-        auto &FAM = FAMP.getManager();
         Function &F = *L.getHeader()->getParent();
-        if (FAM.getCachedResult<FunctionAnalysis>(F))
+        // This call will assert when trying to get the actual analysis if the
+        // FunctionAnalysis can be invalidated. Only check its existence.
+        // Alternatively, use FAM above, for the purposes of this unittest.
+        if (FAMP.cachedResultExists<FunctionAnalysis>(F))
           FAMP.registerOuterAnalysisInvalidation<FunctionAnalysis,
                                                  LoopAnalysis>();
         return MLAHandle.getResult();