[PM] Complete the cross-layer interfaces with a Module-to-Function
[oota-llvm.git] / include / llvm / IR / PassManager.h
index 4d0c09234b766f846a4bcfac0454bee46b761992..3c9414986e655884dd6bfcfe56e6210043082f0d 100644 (file)
@@ -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);
 
@@ -685,6 +733,50 @@ private:
   FunctionAnalysisManager &FAM;
 };
 
+/// \brief A function analysis which acts as a proxy for a module analysis
+/// manager.
+///
+/// This primarily provides an accessor to a parent module analysis manager to
+/// function passes. Only the const interface of the module analysis manager is
+/// provided to indicate that once inside of a function analysis pass you
+/// cannot request a module analysis to actually run. Instead, the user must
+/// rely on the \c getCachedResult API.
+///
+/// This proxy *doesn't* manage the invalidation in any way. That is handled by
+/// the recursive return path of each layer of the pass manager and the
+/// returned PreservedAnalysis set.
+class ModuleAnalysisManagerFunctionProxy {
+public:
+  /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
+  class Result {
+  public:
+    Result(const ModuleAnalysisManager &MAM) : MAM(MAM) {}
+
+    const ModuleAnalysisManager &getManager() const { return MAM; }
+
+    /// \brief Handle invalidation by ignoring it, this pass is immutable.
+    bool invalidate(Function *) { return false; }
+
+  private:
+    const ModuleAnalysisManager &MAM;
+  };
+
+  static void *ID() { return (void *)&PassID; }
+
+  ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM)
+      : MAM(MAM) {}
+
+  /// \brief Run the analysis pass and create our proxy result object.
+  /// Nothing to see here, it just forwards the \c MAM reference into the
+  /// result.
+  Result run(Function *) { return Result(MAM); }
+
+private:
+  static char PassID;
+
+  const ModuleAnalysisManager &MAM;
+};
+
 /// \brief Trivial adaptor that maps from a module to its functions.
 ///
 /// Designed to allow composition of a FunctionPass(Manager) and