asbirlea updated this revision to Diff 254378.
asbirlea added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Update clang test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72893/new/

https://reviews.llvm.org/D72893

Files:
  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: llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
===================================================================
--- llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
+++ llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
@@ -779,9 +779,11 @@
       .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();
Index: llvm/unittests/IR/PassManagerTest.cpp
===================================================================
--- llvm/unittests/IR/PassManagerTest.cpp
+++ llvm/unittests/IR/PassManagerTest.cpp
@@ -107,20 +107,23 @@
 
 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 @@
   int &RunCount;
   int &AnalyzedInstrCount;
   int &AnalyzedFunctionCount;
+  ModuleAnalysisManager &MAM;
   bool OnlyUseCachedResults;
 };
 
@@ -436,8 +440,9 @@
     {
       // 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 @@
   {
     FunctionPassManager FPM(/*DebugLogging*/ true);
     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
-                                 AnalyzedFunctionCount2));
+                                 AnalyzedFunctionCount2, MAM));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
 
@@ -468,7 +473,7 @@
   {
     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 @@
   {
     FunctionPassManager FPM;
     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
-                                 AnalyzedFunctionCount4));
+                                 AnalyzedFunctionCount4, MAM));
     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
   }
 
@@ -495,7 +500,7 @@
     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 @@
     }
   };
 
-  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 @@
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
 };
 
 AnalysisKey TestIndirectFunctionAnalysis::Key;
@@ -693,16 +700,16 @@
 
 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: llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
===================================================================
--- llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
+++ llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
@@ -303,15 +303,28 @@
                         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) {
@@ -375,19 +388,16 @@
   // 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
@@ -397,12 +407,10 @@
   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
@@ -416,19 +424,16 @@
   // 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);
@@ -455,17 +460,14 @@
   // 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)));
@@ -476,20 +478,17 @@
   // 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)));
@@ -500,17 +499,14 @@
   // 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)));
@@ -879,7 +875,8 @@
     }
   };
 
-  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,
@@ -888,9 +885,11 @@
     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
@@ -906,6 +905,7 @@
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
 };
 
 AnalysisKey TestIndirectSCCAnalysis::Key;
@@ -973,7 +973,9 @@
     }
   };
 
-  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) {
@@ -981,21 +983,23 @@
     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
@@ -1011,6 +1015,8 @@
   static AnalysisKey Key;
 
   int &Runs;
+  ModuleAnalysisManager &MAM;
+  CGSCCAnalysisManager &CGAM;
 };
 
 AnalysisKey TestIndirectFunctionAnalysis::Key;
@@ -1023,7 +1029,7 @@
       DoublyIndirectSCCAnalysisRuns = 0;
   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
   CGAM.registerPass(
-      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
   CGAM.registerPass([&] {
     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
   });
@@ -1031,7 +1037,8 @@
   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
   FAM.registerPass([&] {
-    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+                                        CGAM);
   });
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1141,7 +1148,7 @@
       DoublyIndirectSCCAnalysisRuns = 0;
   CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
   CGAM.registerPass(
-      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+      [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
   CGAM.registerPass([&] {
     return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
   });
@@ -1149,7 +1156,8 @@
   int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
   FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
   FAM.registerPass([&] {
-    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+    return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+                                        CGAM);
   });
 
   ModulePassManager MPM(/*DebugLogging*/ true);
@@ -1198,7 +1206,7 @@
 
         // 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;
 
@@ -1244,7 +1252,7 @@
 
         // 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;
 
@@ -1336,6 +1344,8 @@
         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");
@@ -1354,7 +1364,7 @@
         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);
@@ -1371,6 +1381,8 @@
     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");
@@ -1388,8 +1400,9 @@
 
     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);
@@ -1405,6 +1418,8 @@
         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);
@@ -1417,7 +1432,7 @@
         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);
@@ -1434,6 +1449,8 @@
     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);
@@ -1445,8 +1462,9 @@
 
     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);
@@ -1462,6 +1480,8 @@
         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);
@@ -1482,7 +1502,7 @@
             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);
@@ -1499,6 +1519,8 @@
     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);
@@ -1518,8 +1540,9 @@
     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);
@@ -1696,6 +1719,9 @@
   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")
@@ -1723,7 +1749,7 @@
                                             "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: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
===================================================================
--- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8000,10 +8000,9 @@
       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());
     bool Changed =
         runImpl(F, SE, LI, TTI, DT, BFI, &TLI, DB, AA, AC, GetLAA, ORE, PSI);
     if (!Changed)
Index: llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
===================================================================
--- llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
+++ llvm/lib/Transforms/Utils/CallGraphUpdater.cpp
@@ -85,7 +85,7 @@
   } 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: llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -1409,10 +1409,9 @@
   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: llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
+++ llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp
@@ -697,8 +697,8 @@
   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: llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
+++ llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
@@ -975,8 +975,8 @@
   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: llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
+++ llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
@@ -2101,8 +2101,7 @@
   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: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1168,9 +1168,8 @@
 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: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3799,10 +3799,9 @@
   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: llvm/lib/Transforms/IPO/Inliner.cpp
===================================================================
--- llvm/lib/Transforms/IPO/Inliner.cpp
+++ llvm/lib/Transforms/IPO/Inliner.cpp
@@ -876,13 +876,13 @@
 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) {
@@ -988,17 +988,6 @@
 
     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);
 
@@ -1181,8 +1170,12 @@
     // 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();
 
@@ -1228,9 +1221,7 @@
     // 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: llvm/lib/Transforms/Coroutines/CoroSplit.cpp
===================================================================
--- llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -1477,7 +1477,8 @@
 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;
 
@@ -1508,7 +1509,7 @@
   // 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
@@ -1654,6 +1655,9 @@
   //     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();
 
@@ -1702,7 +1706,7 @@
 
     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: llvm/lib/Analysis/CGSCCPassManager.cpp
===================================================================
--- llvm/lib/Analysis/CGSCCPassManager.cpp
+++ llvm/lib/Analysis/CGSCCPassManager.cpp
@@ -69,6 +69,10 @@
   // 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";
@@ -91,6 +95,12 @@
 
     // 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.
@@ -224,23 +234,22 @@
 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
+  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;
+
+  // Create a new empty Result. This needs to have the FunctionAnalysisManager
+  // inside through the updateFAM() API whenever the FAM's module proxy goes
   // away.
-  return Result(FAMProxy->getManager());
+  return Result();
 }
 
 bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
@@ -250,8 +259,8 @@
   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.
@@ -263,7 +272,7 @@
     for (LazyCallGraph::Node &N : C)
       FAM->clear(N.getFunction(), N.getFunction().getName());
 
-    return true;
+    return false;
   }
 
   // Directly check if the relevant set is preserved.
@@ -312,9 +321,10 @@
 
 } // 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
@@ -326,10 +336,10 @@
 /// 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) {
+  auto *ResultFAMCP = &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G);
+  ResultFAMCP->updateFAM(FAM);
 
   // Now walk the functions in this SCC and invalidate any function analysis
   // results that might have outer dependencies on an SCC analysis.
@@ -395,6 +405,10 @@
   // them for each SCC that was split off.
   bool NeedFAMProxy =
       AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC) != nullptr;
+  FunctionAnalysisManager *FAM = nullptr;
+  if (NeedFAMProxy)
+    FAM =
+        &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*OldC, G).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.
@@ -409,7 +423,7 @@
 
   // Ensure the now-current SCC's function analyses are updated.
   if (NeedFAMProxy)
-    updateNewSCCFunctionAnalyses(*C, G, AM);
+    updateNewSCCFunctionAnalyses(*C, G, AM, *FAM);
 
   for (SCC &NewC : llvm::reverse(make_range(std::next(NewSCCRange.begin()),
                                             NewSCCRange.end()))) {
@@ -420,7 +434,7 @@
 
     // Ensure new SCCs' function analyses are updated.
     if (NeedFAMProxy)
-      updateNewSCCFunctionAnalyses(NewC, G, AM);
+      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.
@@ -431,7 +445,8 @@
 
 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,8 +701,11 @@
       // If one of the invalidated SCCs had a cached proxy to a function
       // 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);
+      if (HasFunctionAnalysisProxy) {
+        auto *ResultFAMCP =
+            &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+        ResultFAMCP->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
@@ -739,13 +757,15 @@
 
 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: llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
===================================================================
--- llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
+++ llvm/include/llvm/Transforms/Utils/CallGraphUpdater.h
@@ -49,6 +49,7 @@
   LazyCallGraph::SCC *SCC = nullptr;
   CGSCCAnalysisManager *AM = nullptr;
   CGSCCUpdateResult *UR = nullptr;
+  FunctionAnalysisManager *FAM = nullptr;
   ///}
 
 public:
@@ -68,6 +69,8 @@
     this->SCC = &SCC;
     this->AM = &AM;
     this->UR = &UR;
+    FAM =
+        &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(SCC, LCG).getManager();
   }
   ///}
 
Index: llvm/include/llvm/IR/PassManager.h
===================================================================
--- llvm/include/llvm/IR/PassManager.h
+++ llvm/include/llvm/IR/PassManager.h
@@ -785,7 +785,8 @@
   ///
   /// \returns null if there is no cached result.
   template <typename PassT>
-  typename PassT::Result *getCachedResult(IRUnitT &IR) const {
+  typename PassT::Result *getCachedResult(IRUnitT &IR,
+                                          bool calledFromProxy = false) const {
     assert(AnalysisPasses.count(PassT::ID()) &&
            "This analysis pass was not registered prior to being queried");
 
@@ -797,7 +798,15 @@
         detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
                                     PreservedAnalyses, Invalidator>;
 
-    return &static_cast<ResultModelT *>(ResultConcept)->Result;
+    auto *RetRes = &static_cast<ResultModelT *>(ResultConcept)->Result;
+    if (calledFromProxy) {
+      PreservedAnalyses PA = PreservedAnalyses::none();
+      SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
+      Invalidator Inv(IsResultInvalidated, AnalysisResults);
+      assert(!RetRes->invalidate(IR, PA, Inv) &&
+             "Cached result cannot be invalidated");
+    }
+    return RetRes;
   }
 
   /// Register an analysis pass with the manager.
@@ -1065,7 +1074,22 @@
   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, true);
+      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: llvm/include/llvm/Analysis/CGSCCPassManager.h
===================================================================
--- llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -381,10 +381,15 @@
 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);
@@ -416,7 +421,8 @@
 /// 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.
 ///
@@ -426,7 +432,8 @@
 /// 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.
 ///
@@ -517,7 +524,7 @@
       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!");
@@ -720,6 +727,7 @@
       // 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));
     }
 
@@ -755,6 +763,10 @@
   // 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;
@@ -830,11 +842,13 @@
           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.
+        auto *ResultFAMCP =
+            &CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG);
+        ResultFAMCP->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
@@ -889,6 +903,14 @@
           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.
+            ResultFAMCP =
+                &CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG);
+            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.
           if (UR.InvalidatedSCCs.count(C)) {
Index: llvm/include/llvm/Analysis/AliasAnalysis.h
===================================================================
--- llvm/include/llvm/Analysis/AliasAnalysis.h
+++ llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -1185,8 +1185,8 @@
   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: clang/test/CodeGen/thinlto-distributed-newpm.ll
===================================================================
--- clang/test/CodeGen/thinlto-distributed-newpm.ll
+++ 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{{.*}}>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to