[PM] Factor the overwhelming majority of the interface boiler plate out
authorChandler Carruth <chandlerc@gmail.com>
Tue, 26 Nov 2013 11:24:37 +0000 (11:24 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 26 Nov 2013 11:24:37 +0000 (11:24 +0000)
of the two analysis managers into a CRTP base class that can be shared
and re-used in building any analysis manager. This will in turn simplify
adding yet another analysis manager to the system.

The base class provides all of the interface sugar for the analysis
manager delegating the functionality back through DerivedT methods which
operate on simple pass IDs. It also provides the pass registration,
storage, and lookup system which is common across the various
formulations of analysis managers.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195747 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/PassManager.h
lib/IR/PassManager.cpp

index 3c9414986e655884dd6bfcfe56e6210043082f0d..ddb9ea8f7f9f159c53ab2f335b1823af9bc7e333 100644 (file)
@@ -439,23 +439,43 @@ private:
   std::vector<polymorphic_ptr<FunctionPassConcept> > Passes;
 };
 
   std::vector<polymorphic_ptr<FunctionPassConcept> > Passes;
 };
 
-/// \brief A module analysis pass manager with lazy running and caching of
-/// results.
-class ModuleAnalysisManager {
-public:
-  ModuleAnalysisManager() {}
+namespace detail {
+
+/// \brief A CRTP base used to implement analysis managers.
+///
+/// This class template serves as the boiler plate of an analysis manager. Any
+/// analysis manager can be implemented on top of this base class. Any
+/// implementation will be required to provide specific hooks:
+///
+/// - getResultImpl
+/// - getCachedResultImpl
+/// - invalidateImpl
+///
+/// The details of the call pattern are within.
+template <typename DerivedT, typename IRUnitT>
+class AnalysisManagerBase {
+  DerivedT *derived_this() { return static_cast<DerivedT *>(this); }
+  const DerivedT *derived_this() const { return static_cast<const DerivedT *>(this); }
+
+protected:
+  typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT;
+  typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT;
 
 
+  // FIXME: Provide template aliases for the models when we're using C++11 in
+  // a mode supporting them.
+
+public:
   /// \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.
   /// \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.
-  template <typename PassT> const typename PassT::Result &getResult(Module *M) {
-    assert(ModuleAnalysisPasses.count(PassT::ID()) &&
+  template <typename PassT> const typename PassT::Result &getResult(IRUnitT IR) {
+    assert(AnalysisPasses.count(PassT::ID()) &&
            "This analysis pass was not registered prior to being queried");
 
            "This analysis pass was not registered prior to being queried");
 
-    const detail::AnalysisResultConcept<Module *> &ResultConcept =
-        getResultImpl(PassT::ID(), M);
-    typedef detail::AnalysisResultModel<Module *, PassT, typename PassT::Result>
+    const ResultConceptT &ResultConcept =
+        derived_this()->getResultImpl(PassT::ID(), IR);
+    typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
         ResultModelT;
     return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
         ResultModelT;
     return static_cast<const ResultModelT &>(ResultConcept).Result;
   }
@@ -466,69 +486,100 @@ public:
   ///
   /// \returns null if there is no cached result.
   template <typename PassT>
   ///
   /// \returns null if there is no cached result.
   template <typename PassT>
-  const typename PassT::Result *getCachedResult(Module *M) const {
-    assert(ModuleAnalysisPasses.count(PassT::ID()) &&
+  const typename PassT::Result *getCachedResult(IRUnitT IR) const {
+    assert(AnalysisPasses.count(PassT::ID()) &&
            "This analysis pass was not registered prior to being queried");
 
            "This analysis pass was not registered prior to being queried");
 
-    const detail::AnalysisResultConcept<Module *> *ResultConcept =
-        getCachedResultImpl(PassT::ID(), M);
+    const ResultConceptT *ResultConcept =
+        derived_this()->getCachedResultImpl(PassT::ID(), IR);
     if (!ResultConcept)
       return 0;
 
     if (!ResultConcept)
       return 0;
 
-    typedef detail::AnalysisResultModel<Module *, PassT, typename PassT::Result>
+    typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
         ResultModelT;
     return &static_cast<const ResultModelT *>(ResultConcept)->Result;
   }
 
   /// \brief Register an analysis pass with the manager.
   ///
         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
-  /// analysis
-  /// manager. Whomever is setting up analysis passes must use this to
-  /// populate
+  /// 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) {
   /// the manager with all of the analysis passes available.
   template <typename PassT> void registerPass(PassT Pass) {
-    assert(!ModuleAnalysisPasses.count(PassT::ID()) &&
+    assert(!AnalysisPasses.count(PassT::ID()) &&
            "Registered the same analysis pass twice!");
            "Registered the same analysis pass twice!");
-    ModuleAnalysisPasses[PassT::ID()] =
-        new detail::AnalysisPassModel<Module *, ModuleAnalysisManager, PassT>(
-            llvm_move(Pass));
+    typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT;
+    AnalysisPasses[PassT::ID()] = new PassModelT(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) {
   }
 
   /// \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) {
-    assert(ModuleAnalysisPasses.count(PassT::ID()) &&
+    assert(AnalysisPasses.count(PassT::ID()) &&
            "This analysis pass was not registered prior to being invalidated");
            "This analysis pass was not registered prior to being invalidated");
-    invalidateImpl(PassT::ID(), M);
+    derived_this()->invalidateImpl(PassT::ID(), M);
   }
 
   }
 
-  /// \brief Invalidate analyses cached for an IR Module.
+  /// \brief Invalidate analyses cached for an IR unit.
   ///
   /// Walk through all of the analyses pertaining to this module and invalidate
   /// them unless they are preserved by the PreservedAnalyses set.
   ///
   /// Walk through all of the analyses pertaining to this module and invalidate
   /// them unless they are preserved by the PreservedAnalyses set.
-  void invalidate(Module *M, const PreservedAnalyses &PA);
+  void invalidate(IRUnitT IR, const PreservedAnalyses &PA) {
+    derived_this()->invalidateImpl(IR, PA);
+  }
+
+protected:
+  /// \brief Lookup a registered analysis pass.
+  PassConceptT &lookupPass(void *PassID) {
+    typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(PassID);
+    assert(PI != AnalysisPasses.end() &&
+           "Analysis passes must be registered prior to being queried!");
+    return *PI->second;
+  }
+
+  /// \brief Lookup a registered analysis pass.
+  const PassConceptT &lookupPass(void *PassID) const {
+    typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(PassID);
+    assert(PI != AnalysisPasses.end() &&
+           "Analysis passes must be registered prior to being queried!");
+    return *PI->second;
+  }
+
+private:
+  /// \brief Map type from module analysis pass ID to pass concept pointer.
+  typedef DenseMap<void *, polymorphic_ptr<PassConceptT> > AnalysisPassMapT;
+
+  /// \brief Collection of module analysis passes, indexed by ID.
+  AnalysisPassMapT AnalysisPasses;
+};
+
+}
+
+/// \brief A module analysis pass manager with lazy running and caching of
+/// results.
+class ModuleAnalysisManager
+    : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> {
+  friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>;
+  typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT;
+  typedef typename BaseT::ResultConceptT ResultConceptT;
+  typedef typename BaseT::PassConceptT PassConceptT;
+
+public:
+  // Public methods provided by the base class.
 
 private:
   /// \brief Get a module pass result, running the pass if necessary.
 
 private:
   /// \brief Get a module pass result, running the pass if necessary.
-  const detail::AnalysisResultConcept<Module *> &getResultImpl(void *PassID,
-                                                               Module *M);
+  const ResultConceptT &getResultImpl(void *PassID, Module *M);
 
   /// \brief Get a cached module pass result or return null.
 
   /// \brief Get a cached module pass result or return null.
-  const detail::AnalysisResultConcept<Module *> *
-  getCachedResultImpl(void *PassID, Module *M) const;
+  const ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const;
 
   /// \brief Invalidate a module pass result.
   void invalidateImpl(void *PassID, Module *M);
 
 
   /// \brief Invalidate a module pass result.
   void invalidateImpl(void *PassID, Module *M);
 
-  /// \brief Map type from module analysis pass ID to pass concept pointer.
-  typedef DenseMap<void *, polymorphic_ptr<detail::AnalysisPassConcept<
-                               Module *, ModuleAnalysisManager> > >
-      ModuleAnalysisPassMapT;
-
-  /// \brief Collection of module analysis passes, indexed by ID.
-  ModuleAnalysisPassMapT ModuleAnalysisPasses;
+  /// \brief Invalidate results across a module.
+  void invalidateImpl(Module *M, const PreservedAnalyses &PA);
 
   /// \brief Map type from module analysis pass ID to pass result concept pointer.
   typedef DenseMap<void *,
 
   /// \brief Map type from module analysis pass ID to pass result concept pointer.
   typedef DenseMap<void *,
@@ -541,75 +592,15 @@ private:
 
 /// \brief A function analysis manager to coordinate and cache analyses run over
 /// a module.
 
 /// \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>
-  const typename PassT::Result &getResult(Function *F) {
-    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 *, PassT,
-                                        typename PassT::Result> ResultModelT;
-    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;
-  }
+class FunctionAnalysisManager
+    : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> {
+  friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>;
+  typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> BaseT;
+  typedef typename BaseT::ResultConceptT ResultConceptT;
+  typedef typename BaseT::PassConceptT PassConceptT;
 
 
-  /// \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) {
-    assert(!FunctionAnalysisPasses.count(PassT::ID()) &&
-           "Registered the same analysis pass twice!");
-    FunctionAnalysisPasses[PassT::ID()] = new detail::AnalysisPassModel<
-        Function *, FunctionAnalysisManager, 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) {
-    assert(FunctionAnalysisPasses.count(PassT::ID()) &&
-           "This analysis pass was not registered prior to being invalidated");
-    invalidateImpl(PassT::ID(), F);
-  }
-
-  /// \brief Invalidate analyses cached for an IR Function.
-  ///
-  /// Walk through all of the analyses cache for this IR function and
-  /// invalidate them unless they are preserved by the provided
-  /// PreservedAnalyses set.
-  void invalidate(Function *F, const PreservedAnalyses &PA);
+public:
+  // Most public APIs are inherited from the CRTP base class.
 
   /// \brief Returns true if the analysis manager has an empty results cache.
   bool empty() const;
 
   /// \brief Returns true if the analysis manager has an empty results cache.
   bool empty() const;
@@ -624,23 +615,16 @@ public:
 
 private:
   /// \brief Get a function pass result, running the pass if necessary.
 
 private:
   /// \brief Get a function pass result, running the pass if necessary.
-  const detail::AnalysisResultConcept<Function *> &getResultImpl(void *PassID,
-                                                                 Function *F);
+  const ResultConceptT &getResultImpl(void *PassID, Function *F);
 
   /// \brief Get a cached function pass result or return null.
 
   /// \brief Get a cached function pass result or return null.
-  const detail::AnalysisResultConcept<Function *> *
-  getCachedResultImpl(void *PassID, Function *F) const;
+  const ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const;
 
   /// \brief Invalidate a function pass result.
   void invalidateImpl(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<detail::AnalysisPassConcept<
-                               Function *, FunctionAnalysisManager> > >
-      FunctionAnalysisPassMapT;
-
-  /// \brief Collection of function analysis passes, indexed by ID.
-  FunctionAnalysisPassMapT FunctionAnalysisPasses;
+  /// \brief Invalidate the results for a function..
+  void invalidateImpl(Function *F, const PreservedAnalyses &PA);
 
   /// \brief List of function analysis pass IDs and associated concept pointers.
   ///
 
   /// \brief List of function analysis pass IDs and associated concept pointers.
   ///
index 05aea0743aef3dd5441215b9297d24dc54160415..30b46b01c1def2527fb2a1bb975be58017a66800 100644 (file)
@@ -23,37 +23,22 @@ PreservedAnalyses ModulePassManager::run(Module *M, ModuleAnalysisManager *AM) {
   return PA;
 }
 
   return PA;
 }
 
-void ModuleAnalysisManager::invalidate(Module *M, const PreservedAnalyses &PA) {
-  // 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, PA))
-      ModuleAnalysisResults.erase(I);
-}
-
-const detail::AnalysisResultConcept<Module *> &
+const ModuleAnalysisManager::ResultConceptT &
 ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
   ModuleAnalysisResultMapT::iterator RI;
   bool Inserted;
   llvm::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
       PassID, polymorphic_ptr<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<detail::AnalysisResultConcept<Module *> >()));
 
-  if (Inserted) {
-    // We don't have a cached result for this result. Look up the pass and run
-    // it to produce a result, which we then add to the cache.
-    ModuleAnalysisPassMapT::const_iterator PI =
-        ModuleAnalysisPasses.find(PassID);
-    assert(PI != ModuleAnalysisPasses.end() &&
-           "Analysis passes must be registered prior to being queried!");
-    RI->second = PI->second->run(M, this);
-  }
+  // If we don't have a cached result for this module, look up the pass and run
+  // it to produce a result, which we then add to the cache.
+  if (Inserted)
+    RI->second = lookupPass(PassID).run(M, this);
 
   return *RI->second;
 }
 
 
   return *RI->second;
 }
 
-const detail::AnalysisResultConcept<Module *> *
+const ModuleAnalysisManager::ResultConceptT *
 ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const {
   ModuleAnalysisResultMapT::const_iterator RI = ModuleAnalysisResults.find(PassID);
   return RI == ModuleAnalysisResults.end() ? 0 : &*RI->second;
 ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const {
   ModuleAnalysisResultMapT::const_iterator RI = ModuleAnalysisResults.find(PassID);
   return RI == ModuleAnalysisResults.end() ? 0 : &*RI->second;
@@ -63,6 +48,17 @@ void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) {
   ModuleAnalysisResults.erase(PassID);
 }
 
   ModuleAnalysisResults.erase(PassID);
 }
 
+void ModuleAnalysisManager::invalidateImpl(Module *M,
+                                           const PreservedAnalyses &PA) {
+  // 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, PA))
+      ModuleAnalysisResults.erase(I);
+}
+
 PreservedAnalyses FunctionPassManager::run(Function *F, FunctionAnalysisManager *AM) {
   PreservedAnalyses PA = PreservedAnalyses::all();
   for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
 PreservedAnalyses FunctionPassManager::run(Function *F, FunctionAnalysisManager *AM) {
   PreservedAnalyses PA = PreservedAnalyses::all();
   for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
@@ -74,25 +70,6 @@ PreservedAnalyses FunctionPassManager::run(Function *F, FunctionAnalysisManager
   return PA;
 }
 
   return PA;
 }
 
-void FunctionAnalysisManager::invalidate(Function *F, const PreservedAnalyses &PA) {
-  // 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, PA)) {
-      InvalidatedPassIDs.push_back(I->first);
-      I = ResultsList.erase(I);
-    } else {
-      ++I;
-    }
-  while (!InvalidatedPassIDs.empty())
-    FunctionAnalysisResults.erase(
-        std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
-}
-
 bool FunctionAnalysisManager::empty() const {
   assert(FunctionAnalysisResults.empty() ==
              FunctionAnalysisResultLists.empty() &&
 bool FunctionAnalysisManager::empty() const {
   assert(FunctionAnalysisResults.empty() ==
              FunctionAnalysisResultLists.empty() &&
@@ -106,29 +83,25 @@ void FunctionAnalysisManager::clear() {
   FunctionAnalysisResultLists.clear();
 }
 
   FunctionAnalysisResultLists.clear();
 }
 
-const detail::AnalysisResultConcept<Function *> &
+const FunctionAnalysisManager::ResultConceptT &
 FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
   FunctionAnalysisResultMapT::iterator RI;
   bool Inserted;
   llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
       std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator()));
 
 FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
   FunctionAnalysisResultMapT::iterator RI;
   bool Inserted;
   llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
       std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator()));
 
+  // If we don't have a cached result for this function, look up the pass and
+  // run it to produce a result, which we then add to the cache.
   if (Inserted) {
   if (Inserted) {
-    // We don't have a cached result for this result. Look up the pass and run
-    // it to produce a result, which we then add to the cache.
-    FunctionAnalysisPassMapT::const_iterator PI =
-        FunctionAnalysisPasses.find(PassID);
-    assert(PI != FunctionAnalysisPasses.end() &&
-           "Analysis passes must be registered prior to being queried!");
     FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
     FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
-    ResultList.push_back(std::make_pair(PassID, PI->second->run(F, this)));
+    ResultList.push_back(std::make_pair(PassID, lookupPass(PassID).run(F, this)));
     RI->second = llvm::prior(ResultList.end());
   }
 
   return *RI->second->second;
 }
 
     RI->second = llvm::prior(ResultList.end());
   }
 
   return *RI->second->second;
 }
 
-const detail::AnalysisResultConcept<Function *> *
+const FunctionAnalysisManager::ResultConceptT *
 FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const {
   FunctionAnalysisResultMapT::const_iterator RI =
       FunctionAnalysisResults.find(std::make_pair(PassID, F));
 FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const {
   FunctionAnalysisResultMapT::const_iterator RI =
       FunctionAnalysisResults.find(std::make_pair(PassID, F));
@@ -144,6 +117,26 @@ void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) {
   FunctionAnalysisResultLists[F].erase(RI->second);
 }
 
   FunctionAnalysisResultLists[F].erase(RI->second);
 }
 
+void FunctionAnalysisManager::invalidateImpl(Function *F,
+                                             const PreservedAnalyses &PA) {
+  // 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, PA)) {
+      InvalidatedPassIDs.push_back(I->first);
+      I = ResultsList.erase(I);
+    } else {
+      ++I;
+    }
+  while (!InvalidatedPassIDs.empty())
+    FunctionAnalysisResults.erase(
+        std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
+}
+
 char FunctionAnalysisManagerModuleProxy::PassID;
 
 FunctionAnalysisManagerModuleProxy::Result
 char FunctionAnalysisManagerModuleProxy::PassID;
 
 FunctionAnalysisManagerModuleProxy::Result