[llvm] r195189 - [PM] Split the analysis manager into a function-specific interface and

Chandler Carruth chandlerc at gmail.com
Tue Nov 19 20:01:38 PST 2013


Author: chandlerc
Date: Tue Nov 19 22:01:38 2013
New Revision: 195189

URL: http://llvm.org/viewvc/llvm-project?rev=195189&view=rev
Log:
[PM] Split the analysis manager into a function-specific interface and
a module-specific interface. This is the first of many steps necessary
to generalize the infrastructure such that we can support both
a Module-to-Function and Module-to-SCC-to-Function pass manager
nestings.

After a *lot* of attempts that never worked and didn't even make it to
a committable state, it became clear that I had gotten the layering
design of analyses flat out wrong. Four days later, I think I have most
of the plan for how to correct this, and I'm starting to reshape the
code into it. This is just a baby step I'm afraid, but starts separating
the fundamentally distinct concepts of function analysis passes and
module analysis passes so that in subsequent steps we can effectively
layer them, and have a consistent design for the eventual SCC layer.

As part of this, I've started some interface changes to make passes more
regular. The module pass accepts the module in the run method, and some
of the constructor parameters are gone. I'm still working out exactly
where constructor parameters vs. method parameters will be used, so
I expect this to fluctuate a bit.

This actually makes the invalidation less "correct" at this phase,
because now function passes don't invalidate module analysis passes, but
that was actually somewhat of a misfeature. It will return in a better
factored form which can scale to other units of IR. The documentation
has gotten less verbose and helpful.

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=195189&r1=195188&r2=195189&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Tue Nov 19 22:01:38 2013
@@ -74,20 +74,99 @@ template <typename T, typename PassT> st
   PassT Pass;
 };
 
+/// \brief Abstract concept of an analysis result.
+///
+/// This concept is parameterized over the IR unit that this result pertains
+/// to.
+template <typename IRUnitT> struct AnalysisResultConcept {
+  virtual ~AnalysisResultConcept() {}
+  virtual AnalysisResultConcept *clone() = 0;
+
+  /// \brief Method to try and mark a result as invalid.
+  ///
+  /// When the outer \c AnalysisManager detects a change in some underlying
+  /// unit of the IR, it will call this method on all of the results cached.
+  ///
+  /// \returns true if the result should indeed be invalidated (the default).
+  virtual bool invalidate(IRUnitT *IR) = 0;
+};
+
+/// \brief Wrapper to model the analysis result concept.
+///
+/// Can wrap any type which implements a suitable invalidate member and model
+/// the AnalysisResultConcept for the AnalysisManager.
+template <typename IRUnitT, typename ResultT>
+struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> {
+  AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {}
+  virtual AnalysisResultModel *clone() {
+    return new AnalysisResultModel(Result);
+  }
+
+  /// \brief The model delegates to the \c ResultT method.
+  virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); }
+
+  ResultT Result;
+};
+
+/// \brief Abstract concept of an analysis pass.
+///
+/// This concept is parameterized over the IR unit that it can run over and
+/// produce an analysis result.
+template <typename IRUnitT> struct AnalysisPassConcept {
+  virtual ~AnalysisPassConcept() {}
+  virtual AnalysisPassConcept *clone() = 0;
+
+  /// \brief Method to run this analysis over a unit of IR.
+  /// \returns The analysis result object to be queried by users, the caller
+  /// takes ownership.
+  virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT *IR) = 0;
+};
+
+/// \brief Wrapper to model the analysis pass concept.
+///
+/// Can wrap any type which implements a suitable \c run method. The method
+/// must accept the IRUnitT as an argument and produce an object which can be
+/// wrapped in a \c AnalysisResultModel.
+template <typename PassT>
+struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> {
+  AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {}
+  virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
+
+  // FIXME: Replace PassT::IRUnitT with type traits when we use C++11.
+  typedef typename PassT::IRUnitT IRUnitT;
+
+  // FIXME: Replace PassT::Result with type traits when we use C++11.
+  typedef AnalysisResultModel<IRUnitT, typename PassT::Result> ResultModelT;
+
+  /// \brief The model delegates to the \c PassT::run method.
+  ///
+  /// The return is wrapped in an \c AnalysisResultModel.
+  virtual ResultModelT *run(IRUnitT *IR) {
+    return new ResultModelT(Pass.run(IR));
+  }
+
+  PassT Pass;
+};
+
 }
 
-class AnalysisManager;
+class ModuleAnalysisManager;
 
 class ModulePassManager {
 public:
-  ModulePassManager(Module *M, AnalysisManager *AM = 0) : M(M), AM(AM) {}
+  explicit ModulePassManager(ModuleAnalysisManager *AM = 0) : AM(AM) {}
+
+  /// \brief Run all of the module passes in this module pass manager over
+  /// a module.
+  ///
+  /// This method should only be called for a single module as there is the
+  /// expectation that the lifetime of a pass is bounded to that of a module.
+  void run(Module *M);
 
   template <typename ModulePassT> void addPass(ModulePassT Pass) {
     Passes.push_back(new ModulePassModel<ModulePassT>(llvm_move(Pass)));
   }
 
-  void run();
-
 private:
   // Pull in the concept type and model template specialized for modules.
   typedef detail::PassConcept<Module *> ModulePassConcept;
@@ -96,14 +175,15 @@ private:
     ModulePassModel(PassT Pass) : detail::PassModel<Module *, PassT>(Pass) {}
   };
 
-  Module *M;
-  AnalysisManager *AM;
+  ModuleAnalysisManager *AM;
   std::vector<polymorphic_ptr<ModulePassConcept> > Passes;
 };
 
+class FunctionAnalysisManager;
+
 class FunctionPassManager {
 public:
-  FunctionPassManager(AnalysisManager *AM = 0) : AM(AM) {}
+  explicit FunctionPassManager(FunctionAnalysisManager *AM = 0) : AM(AM) {}
 
   template <typename FunctionPassT> void addPass(FunctionPassT Pass) {
     Passes.push_back(new FunctionPassModel<FunctionPassT>(llvm_move(Pass)));
@@ -120,58 +200,30 @@ private:
         : detail::PassModel<Function *, PassT>(Pass) {}
   };
 
-  AnalysisManager *AM;
+  FunctionAnalysisManager *AM;
   std::vector<polymorphic_ptr<FunctionPassConcept> > Passes;
 };
 
-
-/// \brief An analysis manager to coordinate and cache analyses run over
-/// a module.
-///
-/// The analysis manager is typically used by passes in a pass pipeline
-/// (consisting potentially of several individual pass managers) over a module
-/// of IR. It provides registration of available analyses, declaring
-/// requirements on support for specific analyses, running of an specific
-/// analysis over a specific unit of IR to compute an analysis result, and
-/// caching of the analysis results to reuse them across multiple passes.
-///
-/// It is the responsibility of callers to use the invalidation API to
-/// invalidate analysis results when the IR they correspond to changes. The
-/// \c ModulePassManager and \c FunctionPassManager do this automatically.
-class AnalysisManager {
+/// \brief A module analysis pass manager with lazy running and caching of
+/// results.
+class ModuleAnalysisManager {
 public:
-  AnalysisManager(Module *M) : M(M) {}
+  ModuleAnalysisManager() {}
 
   /// \brief Get the result of an analysis pass for this module.
   ///
   /// If there is not a valid cached result in the manager already, this will
   /// re-run the analysis to produce a valid result.
-  ///
-  /// The module passed in must be the same module as the analysis manager was
-  /// constructed around.
-  template <typename PassT>
-  const typename PassT::Result &getResult(Module *M) {
+  template <typename PassT> const typename PassT::Result &getResult(Module *M) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module>::value),
+                       "The analysis pass must be over a Module.");
     assert(ModuleAnalysisPasses.count(PassT::ID()) &&
            "This analysis pass was not registered prior to being queried");
 
-    const AnalysisResultConcept<Module> &ResultConcept =
+    const detail::AnalysisResultConcept<Module> &ResultConcept =
         getResultImpl(PassT::ID(), M);
-    typedef AnalysisResultModel<Module, typename PassT::Result> ResultModelT;
-    return static_cast<const ResultModelT &>(ResultConcept).Result;
-  }
-
-  /// \brief Get the result of an analysis pass for a function.
-  ///
-  /// If there is not a valid cached result in the manager already, this will
-  /// re-run the analysis to produce a valid result.
-  template <typename PassT>
-  const typename PassT::Result &getResult(Function *F) {
-    assert(FunctionAnalysisPasses.count(PassT::ID()) &&
-           "This analysis pass was not registered prior to being queried");
-
-    const AnalysisResultConcept<Function> &ResultConcept =
-        getResultImpl(PassT::ID(), F);
-    typedef AnalysisResultModel<Function, typename PassT::Result> ResultModelT;
+    typedef detail::AnalysisResultModel<Module, typename PassT::Result>
+        ResultModelT;
     return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
 
@@ -182,24 +234,26 @@ public:
   /// manager. Whomever is setting up analysis passes must use this to
   /// populate
   /// the manager with all of the analysis passes available.
-  template <typename PassT> void registerAnalysisPass(PassT Pass) {
-    registerAnalysisPassImpl<PassT>(llvm_move(Pass));
+  template <typename PassT> void registerPass(PassT Pass) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module>::value),
+                       "The analysis pass must be over a Module.");
+    assert(!ModuleAnalysisPasses.count(PassT::ID()) &&
+           "Registered the same analysis pass twice!");
+    ModuleAnalysisPasses[PassT::ID()] =
+        new detail::AnalysisPassModel<PassT>(llvm_move(Pass));
   }
 
   /// \brief Invalidate a specific analysis pass for an IR module.
   ///
   /// Note that the analysis result can disregard invalidation.
   template <typename PassT> void invalidate(Module *M) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module>::value),
+                       "The analysis pass must be over a Module.");
+    assert(ModuleAnalysisPasses.count(PassT::ID()) &&
+           "This analysis pass was not registered prior to being invalidated");
     invalidateImpl(PassT::ID(), M);
   }
 
-  /// \brief Invalidate a specific analysis pass for an IR function.
-  ///
-  /// Note that the analysis result can disregard invalidation.
-  template <typename PassT> void invalidate(Function *F) {
-    invalidateImpl(PassT::ID(), F);
-  }
-
   /// \brief Invalidate analyses cached for an IR Module.
   ///
   /// Note that specific analysis results can disregard invalidation by
@@ -209,141 +263,100 @@ public:
   /// around.
   void invalidateAll(Module *M);
 
-  /// \brief Invalidate analyses cached for an IR Function.
-  ///
-  /// Note that specific analysis results can disregard invalidation by
-  /// overriding the invalidate method.
-  void invalidateAll(Function *F);
-
 private:
-  /// \brief Abstract concept of an analysis result.
-  ///
-  /// This concept is parameterized over the IR unit that this result pertains
-  /// to.
-  template <typename IRUnitT> struct AnalysisResultConcept {
-    virtual ~AnalysisResultConcept() {}
-    virtual AnalysisResultConcept *clone() = 0;
-
-    /// \brief Method to try and mark a result as invalid.
-    ///
-    /// When the outer \c AnalysisManager detects a change in some underlying
-    /// unit of the IR, it will call this method on all of the results cached.
-    ///
-    /// \returns true if the result should indeed be invalidated (the default).
-    virtual bool invalidate(IRUnitT *IR) = 0;
-  };
-
-  /// \brief Wrapper to model the analysis result concept.
-  ///
-  /// Can wrap any type which implements a suitable invalidate member and model
-  /// the AnalysisResultConcept for the AnalysisManager.
-  template <typename IRUnitT, typename ResultT>
-  struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> {
-    AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {}
-    virtual AnalysisResultModel *clone() {
-      return new AnalysisResultModel(Result);
-    }
-
-    /// \brief The model delegates to the \c ResultT method.
-    virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); }
-
-    ResultT Result;
-  };
-
-  /// \brief Abstract concept of an analysis pass.
-  ///
-  /// This concept is parameterized over the IR unit that it can run over and
-  /// produce an analysis result.
-  template <typename IRUnitT> struct AnalysisPassConcept {
-    virtual ~AnalysisPassConcept() {}
-    virtual AnalysisPassConcept *clone() = 0;
-
-    /// \brief Method to run this analysis over a unit of IR.
-    /// \returns The analysis result object to be queried by users, the caller
-    /// takes ownership.
-    virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT *IR) = 0;
-  };
-
-  /// \brief Wrapper to model the analysis pass concept.
-  ///
-  /// Can wrap any type which implements a suitable \c run method. The method
-  /// must accept the IRUnitT as an argument and produce an object which can be
-  /// wrapped in a \c AnalysisResultModel.
-  template <typename PassT>
-  struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> {
-    AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {}
-    virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
-
-    // FIXME: Replace PassT::IRUnitT with type traits when we use C++11.
-    typedef typename PassT::IRUnitT IRUnitT;
-
-    // FIXME: Replace PassT::Result with type traits when we use C++11.
-    typedef AnalysisResultModel<IRUnitT, typename PassT::Result> ResultModelT;
-
-    /// \brief The model delegates to the \c PassT::run method.
-    ///
-    /// The return is wrapped in an \c AnalysisResultModel.
-    virtual ResultModelT *run(IRUnitT *IR) {
-      return new ResultModelT(Pass.run(IR));
-    }
-
-    PassT Pass;
-  };
-
-
   /// \brief Get a module pass result, running the pass if necessary.
-  const AnalysisResultConcept<Module> &getResultImpl(void *PassID, Module *M);
-
-  /// \brief Get a function pass result, running the pass if necessary.
-  const AnalysisResultConcept<Function> &getResultImpl(void *PassID,
-                                                       Function *F);
+  const detail::AnalysisResultConcept<Module> &getResultImpl(void *PassID,
+                                                             Module *M);
 
   /// \brief Invalidate a module pass result.
   void invalidateImpl(void *PassID, Module *M);
 
-  /// \brief Invalidate a function pass result.
-  void invalidateImpl(void *PassID, Function *F);
+  /// \brief Map type from module analysis pass ID to pass concept pointer.
+  typedef DenseMap<void *,
+                   polymorphic_ptr<detail::AnalysisPassConcept<Module> > >
+      ModuleAnalysisPassMapT;
 
+  /// \brief Collection of module analysis passes, indexed by ID.
+  ModuleAnalysisPassMapT ModuleAnalysisPasses;
 
-  /// \brief Module pass specific implementation of registration.
+  /// \brief Map type from module analysis pass ID to pass result concept pointer.
+  typedef DenseMap<void *,
+                   polymorphic_ptr<detail::AnalysisResultConcept<Module> > >
+      ModuleAnalysisResultMapT;
+
+  /// \brief Cache of computed module analysis results for this module.
+  ModuleAnalysisResultMapT ModuleAnalysisResults;
+};
+
+/// \brief A function analysis manager to coordinate and cache analyses run over
+/// a module.
+class FunctionAnalysisManager {
+public:
+  FunctionAnalysisManager() {}
+
+  /// \brief Get the result of an analysis pass for a function.
+  ///
+  /// If there is not a valid cached result in the manager already, this will
+  /// re-run the analysis to produce a valid result.
   template <typename PassT>
-  typename enable_if<is_same<typename PassT::IRUnitT, Module> >::type
-  registerAnalysisPassImpl(PassT Pass) {
-    assert(!ModuleAnalysisPasses.count(PassT::ID()) &&
-           "Registered the same analysis pass twice!");
-    ModuleAnalysisPasses[PassT::ID()] =
-        new AnalysisPassModel<PassT>(llvm_move(Pass));
+  const typename PassT::Result &getResult(Function *F) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function>::value),
+                       "The analysis pass must be over a Function.");
+    assert(FunctionAnalysisPasses.count(PassT::ID()) &&
+           "This analysis pass was not registered prior to being queried");
+
+    const detail::AnalysisResultConcept<Function> &ResultConcept =
+        getResultImpl(PassT::ID(), F);
+    typedef detail::AnalysisResultModel<Function, typename PassT::Result>
+        ResultModelT;
+    return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
 
-  /// \brief Function pass specific implementation of registration.
-  template <typename PassT>
-  typename enable_if<is_same<typename PassT::IRUnitT, Function> >::type
-  registerAnalysisPassImpl(PassT Pass) {
+  /// \brief Register an analysis pass with the manager.
+  ///
+  /// This provides an initialized and set-up analysis pass to the
+  /// analysis
+  /// manager. Whomever is setting up analysis passes must use this to
+  /// populate
+  /// the manager with all of the analysis passes available.
+  template <typename PassT> void registerPass(PassT Pass) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function>::value),
+                       "The analysis pass must be over a Function.");
     assert(!FunctionAnalysisPasses.count(PassT::ID()) &&
            "Registered the same analysis pass twice!");
     FunctionAnalysisPasses[PassT::ID()] =
-        new AnalysisPassModel<PassT>(llvm_move(Pass));
+        new detail::AnalysisPassModel<PassT>(llvm_move(Pass));
   }
 
+  /// \brief Invalidate a specific analysis pass for an IR module.
+  ///
+  /// Note that the analysis result can disregard invalidation.
+  template <typename PassT> void invalidate(Function *F) {
+    LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function>::value),
+                       "The analysis pass must be over a Function.");
+    assert(FunctionAnalysisPasses.count(PassT::ID()) &&
+           "This analysis pass was not registered prior to being invalidated");
+    invalidateImpl(PassT::ID(), F);
+  }
 
-  /// \brief Map type from module analysis pass ID to pass concept pointer.
-  typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Module> > >
-  ModuleAnalysisPassMapT;
-
-  /// \brief Collection of module analysis passes, indexed by ID.
-  ModuleAnalysisPassMapT ModuleAnalysisPasses;
-
-  /// \brief Map type from module analysis pass ID to pass result concept pointer.
-  typedef DenseMap<void *, polymorphic_ptr<AnalysisResultConcept<Module> > >
-  ModuleAnalysisResultMapT;
+  /// \brief Invalidate analyses cached for an IR Function.
+  ///
+  /// Note that specific analysis results can disregard invalidation by
+  /// overriding the invalidate method.
+  void invalidateAll(Function *F);
 
-  /// \brief Cache of computed module analysis results for this module.
-  ModuleAnalysisResultMapT ModuleAnalysisResults;
+private:
+  /// \brief Get a function pass result, running the pass if necessary.
+  const detail::AnalysisResultConcept<Function> &getResultImpl(void *PassID,
+                                                               Function *F);
 
+  /// \brief Invalidate a function pass result.
+  void invalidateImpl(void *PassID, Function *F);
 
   /// \brief Map type from function analysis pass ID to pass concept pointer.
-  typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Function> > >
-  FunctionAnalysisPassMapT;
+  typedef DenseMap<void *,
+                   polymorphic_ptr<detail::AnalysisPassConcept<Function> > >
+      FunctionAnalysisPassMapT;
 
   /// \brief Collection of function analysis passes, indexed by ID.
   FunctionAnalysisPassMapT FunctionAnalysisPasses;
@@ -353,12 +366,13 @@ private:
   /// Requires iterators to be valid across appending new entries and arbitrary
   /// erases. Provides both the pass ID and concept pointer such that it is
   /// half of a bijection and provides storage for the actual result concept.
-  typedef std::list<
-      std::pair<void *, polymorphic_ptr<AnalysisResultConcept<Function> > > >
-  FunctionAnalysisResultListT;
+  typedef std::list<std::pair<
+      void *, polymorphic_ptr<detail::AnalysisResultConcept<Function> > > >
+      FunctionAnalysisResultListT;
 
   /// \brief Map type from function pointer to our custom list type.
-  typedef DenseMap<Function *, FunctionAnalysisResultListT> FunctionAnalysisResultListMapT;
+  typedef DenseMap<Function *, FunctionAnalysisResultListT>
+  FunctionAnalysisResultListMapT;
 
   /// \brief Map from function to a list of function analysis results.
   ///
@@ -370,14 +384,11 @@ private:
   /// iterator into a particular result list.
   typedef DenseMap<std::pair<void *, Function *>,
                    FunctionAnalysisResultListT::iterator>
-  FunctionAnalysisResultMapT;
+      FunctionAnalysisResultMapT;
 
   /// \brief Map from an analysis ID and function to a particular cached
   /// analysis result.
   FunctionAnalysisResultMapT FunctionAnalysisResults;
-
-  /// \brief Module handle for the \c AnalysisManager.
-  Module *M;
 };
 
 }

Modified: llvm/trunk/lib/IR/PassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=195189&r1=195188&r2=195189&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassManager.cpp (original)
+++ llvm/trunk/lib/IR/PassManager.cpp Tue Nov 19 22:01:38 2013
@@ -12,27 +12,14 @@
 
 using namespace llvm;
 
-void ModulePassManager::run() {
+void ModulePassManager::run(Module *M) {
   for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
     if (Passes[Idx]->run(M))
-      if (AM) AM->invalidateAll(M);
+      if (AM)
+        AM->invalidateAll(M);
 }
 
-bool FunctionPassManager::run(Module *M) {
-  bool Changed = false;
-  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
-    for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
-      if (Passes[Idx]->run(I)) {
-        Changed = true;
-        if (AM) AM->invalidateAll(I);
-      }
-  return Changed;
-}
-
-void AnalysisManager::invalidateAll(Function *F) {
-  assert(F->getParent() == M && "Invalidating a function from another module!");
-
-  // First invalidate any module results we still have laying about.
+void ModuleAnalysisManager::invalidateAll(Module *M) {
   // FIXME: This is a total hack based on the fact that erasure doesn't
   // invalidate iteration for DenseMap.
   for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(),
@@ -40,67 +27,14 @@ void AnalysisManager::invalidateAll(Func
        I != E; ++I)
     if (I->second->invalidate(M))
       ModuleAnalysisResults.erase(I);
-
-  // Now clear all the invalidated results associated specifically with this
-  // function.
-  SmallVector<void *, 8> InvalidatedPassIDs;
-  FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F];
-  for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
-                                             E = ResultsList.end();
-       I != E;)
-    if (I->second->invalidate(F)) {
-      InvalidatedPassIDs.push_back(I->first);
-      I = ResultsList.erase(I);
-    } else {
-      ++I;
-    }
-  while (!InvalidatedPassIDs.empty())
-    FunctionAnalysisResults.erase(
-        std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
 }
 
-void AnalysisManager::invalidateAll(Module *M) {
-  // First invalidate any module results we still have laying about.
-  // FIXME: This is a total hack based on the fact that erasure doesn't
-  // invalidate iteration for DenseMap.
-  for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(),
-                                          E = ModuleAnalysisResults.end();
-       I != E; ++I)
-    if (I->second->invalidate(M))
-      ModuleAnalysisResults.erase(I);
-
-  // Now walk all of the functions for which there are cached results, and
-  // attempt to invalidate each of those as the entire module may have changed.
-  // FIXME: How do we handle functions which have been deleted or RAUWed?
-  SmallVector<void *, 8> InvalidatedPassIDs;
-  for (FunctionAnalysisResultListMapT::iterator
-           FI = FunctionAnalysisResultLists.begin(),
-           FE = FunctionAnalysisResultLists.end();
-       FI != FE; ++FI) {
-    Function *F = FI->first;
-    FunctionAnalysisResultListT &ResultsList = FI->second;
-    for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
-                                               E = ResultsList.end();
-         I != E;)
-      if (I->second->invalidate(F)) {
-        InvalidatedPassIDs.push_back(I->first);
-        I = ResultsList.erase(I);
-      } else {
-        ++I;
-      }
-    while (!InvalidatedPassIDs.empty())
-      FunctionAnalysisResults.erase(
-          std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
-  }
-}
-
-const AnalysisManager::AnalysisResultConcept<Module> &
-AnalysisManager::getResultImpl(void *PassID, Module *M) {
-  assert(M == this->M && "Wrong module used when querying the AnalysisManager");
+const detail::AnalysisResultConcept<Module> &
+ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
   ModuleAnalysisResultMapT::iterator RI;
   bool Inserted;
   llvm::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
-      PassID, polymorphic_ptr<AnalysisResultConcept<Module> >()));
+      PassID, polymorphic_ptr<detail::AnalysisResultConcept<Module> >()));
 
   if (Inserted) {
     // We don't have a cached result for this result. Look up the pass and run
@@ -115,10 +49,43 @@ AnalysisManager::getResultImpl(void *Pas
   return *RI->second;
 }
 
-const AnalysisManager::AnalysisResultConcept<Function> &
-AnalysisManager::getResultImpl(void *PassID, Function *F) {
-  assert(F->getParent() == M && "Analyzing a function from another module!");
+void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) {
+  ModuleAnalysisResults.erase(PassID);
+}
+
+bool FunctionPassManager::run(Module *M) {
+  bool Changed = false;
+  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+    for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
+      if (Passes[Idx]->run(I)) {
+        Changed = true;
+        if (AM)
+          AM->invalidateAll(I);
+      }
+  return Changed;
+}
+
+void FunctionAnalysisManager::invalidateAll(Function *F) {
+  // Clear all the invalidated results associated specifically with this
+  // function.
+  SmallVector<void *, 8> InvalidatedPassIDs;
+  FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F];
+  for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
+                                             E = ResultsList.end();
+       I != E;)
+    if (I->second->invalidate(F)) {
+      InvalidatedPassIDs.push_back(I->first);
+      I = ResultsList.erase(I);
+    } else {
+      ++I;
+    }
+  while (!InvalidatedPassIDs.empty())
+    FunctionAnalysisResults.erase(
+        std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
+}
 
+const detail::AnalysisResultConcept<Function> &
+FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
   FunctionAnalysisResultMapT::iterator RI;
   bool Inserted;
   llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
@@ -139,15 +106,7 @@ AnalysisManager::getResultImpl(void *Pas
   return *RI->second->second;
 }
 
-void AnalysisManager::invalidateImpl(void *PassID, Module *M) {
-  assert(M == this->M && "Invalidating a pass over a different module!");
-  ModuleAnalysisResults.erase(PassID);
-}
-
-void AnalysisManager::invalidateImpl(void *PassID, Function *F) {
-  assert(F->getParent() == M &&
-         "Invalidating a pass over a function from another module!");
-
+void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) {
   FunctionAnalysisResultMapT::iterator RI =
       FunctionAnalysisResults.find(std::make_pair(PassID, F));
   if (RI == FunctionAnalysisResults.end())

Modified: llvm/trunk/unittests/IR/PassManagerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=195189&r1=195188&r2=195189&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PassManagerTest.cpp (original)
+++ llvm/trunk/unittests/IR/PassManagerTest.cpp Tue Nov 19 22:01:38 2013
@@ -61,9 +61,9 @@ struct TestModulePass {
 };
 
 struct TestFunctionPass {
-  TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount)
-      : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {
-  }
+  TestFunctionPass(FunctionAnalysisManager &AM, int &RunCount,
+                   int &AnalyzedInstrCount)
+      : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {}
 
   bool run(Function *F) {
     ++RunCount;
@@ -74,7 +74,7 @@ struct TestFunctionPass {
     return true;
   }
 
-  AnalysisManager &AM;
+  FunctionAnalysisManager &AM;
   int &RunCount;
   int &AnalyzedInstrCount;
 };
@@ -106,10 +106,10 @@ public:
 };
 
 TEST_F(PassManagerTest, Basic) {
-  AnalysisManager AM(M.get());
-  AM.registerAnalysisPass(TestAnalysisPass());
+  FunctionAnalysisManager AM;
+  AM.registerPass(TestAnalysisPass());
 
-  ModulePassManager MPM(M.get(), &AM);
+  ModulePassManager MPM;
   FunctionPassManager FPM(&AM);
 
   // Count the runs over a module.
@@ -122,10 +122,9 @@ TEST_F(PassManagerTest, Basic) {
   FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount));
   MPM.addPass(FPM);
 
-  MPM.run();
+  MPM.run(M.get());
   EXPECT_EQ(1, ModulePassRunCount);
   EXPECT_EQ(3, FunctionPassRunCount);
   EXPECT_EQ(5, AnalyzedInstrCount);
 }
-
 }





More information about the llvm-commits mailing list