[llvm] r195525 - [PM] Add support to the analysis managers to query explicitly for cached

Chandler Carruth chandlerc at gmail.com
Fri Nov 22 16:38:43 PST 2013


Author: chandlerc
Date: Fri Nov 22 18:38:42 2013
New Revision: 195525

URL: http://llvm.org/viewvc/llvm-project?rev=195525&view=rev
Log:
[PM] Add support to the analysis managers to query explicitly for cached
results.

This is the last piece of infrastructure needed to effectively support
querying *up* the analysis layers. The next step will be to introduce
a proxy which provides access to those layers with appropriate use of
const to direct queries to the safe interface.

Modified:
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/lib/IR/PassManager.cpp
    llvm/trunk/unittests/IR/PassManagerTest.cpp

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=195525&r1=195524&r2=195525&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Fri Nov 22 18:38:42 2013
@@ -460,6 +460,26 @@ public:
     return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
 
+  /// \brief Get the cached result of an analysis pass for this module.
+  ///
+  /// This method never runs the analysis.
+  ///
+  /// \returns null if there is no cached result.
+  template <typename PassT>
+  const typename PassT::Result *getCachedResult(Module *M) const {
+    assert(ModuleAnalysisPasses.count(PassT::ID()) &&
+           "This analysis pass was not registered prior to being queried");
+
+    const detail::AnalysisResultConcept<Module *> *ResultConcept =
+        getCachedResultImpl(PassT::ID(), M);
+    if (!ResultConcept)
+      return 0;
+
+    typedef detail::AnalysisResultModel<Module *, PassT, typename PassT::Result>
+        ResultModelT;
+    return &static_cast<const ResultModelT *>(ResultConcept)->Result;
+  }
+
   /// \brief Register an analysis pass with the manager.
   ///
   /// This provides an initialized and set-up analysis pass to the
@@ -495,6 +515,10 @@ private:
   const detail::AnalysisResultConcept<Module *> &getResultImpl(void *PassID,
                                                                Module *M);
 
+  /// \brief Get a cached module pass result or return null.
+  const detail::AnalysisResultConcept<Module *> *
+  getCachedResultImpl(void *PassID, Module *M) const;
+
   /// \brief Invalidate a module pass result.
   void invalidateImpl(void *PassID, Module *M);
 
@@ -537,6 +561,26 @@ public:
     return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
 
+  /// \brief Get the cached result of an analysis pass for a function if
+  /// available.
+  ///
+  /// Does not run the analysis ever.
+  /// \returns null if a cached result is not available.
+  template <typename PassT>
+  const typename PassT::Result *getCachedResult(Function *F) {
+    assert(FunctionAnalysisPasses.count(PassT::ID()) &&
+           "This analysis pass was not registered prior to being queried");
+
+    const detail::AnalysisResultConcept<Function *> *ResultConcept =
+        getCachedResultImpl(PassT::ID(), F);
+    if (!ResultConcept)
+      return 0;
+
+    typedef detail::AnalysisResultModel<Function *, PassT,
+                                        typename PassT::Result> ResultModelT;
+    return &static_cast<const ResultModelT *>(ResultConcept)->Result;
+  }
+
   /// \brief Register an analysis pass with the manager.
   ///
   /// This provides an initialized and set-up analysis pass to the
@@ -583,6 +627,10 @@ private:
   const detail::AnalysisResultConcept<Function *> &getResultImpl(void *PassID,
                                                                  Function *F);
 
+  /// \brief Get a cached function pass result or return null.
+  const detail::AnalysisResultConcept<Function *> *
+  getCachedResultImpl(void *PassID, Function *F) const;
+
   /// \brief Invalidate a function pass result.
   void invalidateImpl(void *PassID, Function *F);
 

Modified: llvm/trunk/lib/IR/PassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=195525&r1=195524&r2=195525&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassManager.cpp (original)
+++ llvm/trunk/lib/IR/PassManager.cpp Fri Nov 22 18:38:42 2013
@@ -53,6 +53,12 @@ ModuleAnalysisManager::getResultImpl(voi
   return *RI->second;
 }
 
+const detail::AnalysisResultConcept<Module *> *
+ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const {
+  ModuleAnalysisResultMapT::const_iterator RI = ModuleAnalysisResults.find(PassID);
+  return RI == ModuleAnalysisResults.end() ? 0 : &*RI->second;
+}
+
 void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) {
   ModuleAnalysisResults.erase(PassID);
 }
@@ -122,6 +128,13 @@ FunctionAnalysisManager::getResultImpl(v
   return *RI->second->second;
 }
 
+const detail::AnalysisResultConcept<Function *> *
+FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const {
+  FunctionAnalysisResultMapT::const_iterator RI =
+      FunctionAnalysisResults.find(std::make_pair(PassID, F));
+  return RI == FunctionAnalysisResults.end() ? 0 : &*RI->second->second;
+}
+
 void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) {
   FunctionAnalysisResultMapT::iterator RI =
       FunctionAnalysisResults.find(std::make_pair(PassID, F));

Modified: llvm/trunk/unittests/IR/PassManagerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=195525&r1=195524&r2=195525&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PassManagerTest.cpp (original)
+++ llvm/trunk/unittests/IR/PassManagerTest.cpp Fri Nov 22 18:38:42 2013
@@ -69,28 +69,46 @@ struct TestPreservingModulePass {
 };
 
 struct TestMinPreservingModulePass {
-  PreservedAnalyses run(Module *M) {
+  PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
     PreservedAnalyses PA;
+
+    // Check that we can get cached result objects for modules.
+    const FunctionAnalysisManagerModuleProxy::Result *R =
+        AM->getCachedResult<FunctionAnalysisManagerModuleProxy>(M);
+    (void)R; // FIXME: We should test this better by querying an actual analysis
+             // pass in interesting ways.
+
     PA.preserve<FunctionAnalysisManagerModuleProxy>();
     return PA;
   }
 };
 
 struct TestFunctionPass {
-  TestFunctionPass(int &RunCount, int &AnalyzedInstrCount)
-      : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {}
+  TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
+                   bool OnlyUseCachedResults = false)
+      : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
+        OnlyUseCachedResults(OnlyUseCachedResults) {}
 
   PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) {
     ++RunCount;
 
-    const TestAnalysisPass::Result &AR = AM->getResult<TestAnalysisPass>(F);
-    AnalyzedInstrCount += AR.InstructionCount;
+    if (OnlyUseCachedResults) {
+      // Hack to force the use of the cached interface.
+      if (const TestAnalysisPass::Result *AR =
+              AM->getCachedResult<TestAnalysisPass>(F))
+        AnalyzedInstrCount += AR->InstructionCount;
+    } else {
+      // Typical path just runs the analysis as needed.
+      const TestAnalysisPass::Result &AR = AM->getResult<TestAnalysisPass>(F);
+      AnalyzedInstrCount += AR.InstructionCount;
+    }
 
     return PreservedAnalyses::all();
   }
 
   int &RunCount;
   int &AnalyzedInstrCount;
+  bool OnlyUseCachedResults;
 };
 
 // A test function pass that invalidates all function analyses for a function
@@ -178,6 +196,15 @@ TEST_F(PassManagerTest, Basic) {
   FPM4.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4));
   MPM.addPass(createModuleToFunctionPassAdaptor(FPM4));
 
+  // A fifth function pass manager but which uses only cached results.
+  FunctionPassManager FPM5;
+  int FunctionPassRunCount5 = 0;
+  int AnalyzedInstrCount5 = 0;
+  FPM5.addPass(TestInvalidationFunctionPass("f"));
+  FPM5.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
+                                /*OnlyUseCachedResults=*/true));
+  MPM.addPass(createModuleToFunctionPassAdaptor(FPM5));
+
   MPM.run(M.get(), &MAM);
 
   // Validate module pass counters.
@@ -192,6 +219,8 @@ TEST_F(PassManagerTest, Basic) {
   EXPECT_EQ(5, AnalyzedInstrCount3);
   EXPECT_EQ(3, FunctionPassRunCount4);
   EXPECT_EQ(5, AnalyzedInstrCount4);
+  EXPECT_EQ(3, FunctionPassRunCount5);
+  EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
 
   // Validate the analysis counters:
   //   first run over 3 functions, then module pass invalidates





More information about the llvm-commits mailing list