[clang] bd541b2 - [NewPassManager] Add assertions when getting statefull cached analysis.

Alina Sbirlea via cfe-commits cfe-commits at lists.llvm.org
Wed May 13 12:41:32 PDT 2020


Author: Alina Sbirlea
Date: 2020-05-13T12:38:38-07:00
New Revision: bd541b217f4d750391677144ccaa586874236f38

URL: https://github.com/llvm/llvm-project/commit/bd541b217f4d750391677144ccaa586874236f38
DIFF: https://github.com/llvm/llvm-project/commit/bd541b217f4d750391677144ccaa586874236f38.diff

LOG: [NewPassManager] Add assertions when getting statefull cached analysis.

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

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGen/thinlto-distributed-newpm.ll b/clang/test/CodeGen/thinlto-distributed-newpm.ll
index 5740c6f616be..013da3c9af4c 100644
--- a/clang/test/CodeGen/thinlto-distributed-newpm.ll
+++ b/clang/test/CodeGen/thinlto-distributed-newpm.ll
@@ -85,10 +85,7 @@
 ; 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{{.*}}>

diff  --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index 95b4c2a482b2..c35ee2f499de 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -1185,8 +1185,8 @@ class AAManager : public AnalysisInfoMixin<AAManager> {
   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>();

diff  --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 4c5191797f59..b5b58686d958 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -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 @@ class CGSCCToFunctionPassAdaptor
       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 @@ class DevirtSCCRepeatedPass
       // 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)) {

diff  --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 89f764ff081e..e7fb0b5e7543 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -799,6 +799,16 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
     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 @@ class OuterAnalysisManagerProxy
   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(

diff  --git a/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h b/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
index 728028d0d114..6103859ca959 100644
--- a/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
+++ b/llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
@@ -49,6 +49,7 @@ class CallGraphUpdater {
   LazyCallGraph::SCC *SCC = nullptr;
   CGSCCAnalysisManager *AM = nullptr;
   CGSCCUpdateResult *UR = nullptr;
+  FunctionAnalysisManager *FAM = nullptr;
   ///}
 
 public:
@@ -68,6 +69,8 @@ class CallGraphUpdater {
     this->SCC = &SCC;
     this->AM = &AM;
     this->UR = &UR;
+    FAM =
+        &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(SCC, LCG).getManager();
   }
   ///}
 

diff  --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp
index d4d965852a36..64bd6dfe67ab 100644
--- a/llvm/lib/Analysis/CGSCCPassManager.cpp
+++ b/llvm/lib/Analysis/CGSCCPassManager.cpp
@@ -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);
 }

diff  --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index 1e0bdc168e5b..e1ac5e92cbd9 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -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)

diff  --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index 336dca81d214..e18039e7d0a1 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -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();

diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 84648260830b..afdff9141e69 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -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;
 

diff  --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 93326c8fd13a..1d679ffe0b60 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -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))

diff  --git a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
index 420baf113018..a99c58b74fb1 100644
--- a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
@@ -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();

diff  --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
index c72ce92432a2..fa3bc5f82a3d 100644
--- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
@@ -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();
 

diff  --git a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
index c98d652645ed..989653dc876a 100644
--- a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
@@ -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

diff  --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
index 0406592dd894..e94eb4009d98 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -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;
 

diff  --git a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
index 8060e50abee9..cded14b9cc0a 100644
--- a/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
+++ b/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
@@ -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);
   }
 }
 

diff  --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index f05a22682e90..4159042faa37 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -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)

diff  --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
index 15e816412896..7a9e588a50c9 100644
--- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
+++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
@@ -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 @@ struct TestIndirectSCCAnalysis
   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 @@ struct TestIndirectFunctionAnalysis
   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";

diff  --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp
index 5b1f9025df99..4924dec00749 100644
--- a/llvm/unittests/IR/PassManagerTest.cpp
+++ b/llvm/unittests/IR/PassManagerTest.cpp
@@ -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 @@ struct TestIndirectFunctionAnalysis
   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); });

diff  --git a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
index 9926396509ce..cecc6ff183cf 100644
--- a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
+++ b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
@@ -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();


        


More information about the cfe-commits mailing list