<div dir="ltr">Nice cleanup! I noticed this too when working on the analysis manager stuff.<div><br></div><div>-- Sean Silva</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 19, 2016 at 1:31 AM, Chandler Carruth via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chandlerc<br>
Date: Fri Aug 19 03:31:47 2016<br>
New Revision: 279221<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=279221&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=279221&view=rev</a><br>
Log:<br>
[PM] NFC refactoring: remove the AnalysisManagerBase class, folding it<br>
into the AnalysisManager class template.<br>
<br>
Back when I first added this base class there were separate analysis<br>
managers and some plausible reason why it would be a useful factoring of<br>
common code between them. However, after a lot of refactoring cleaning,<br>
we now have *entirely* shared code. The base class was just an arbitrary<br>
division between code in one class template and a separate class<br>
template. It didn't add anything and forced lots of indirection through<br>
"derived_this" for no real gain.<br>
<br>
We can always factor a base CRTP class out with common code if there is<br>
ever some *other* analysis manager that wants to share a subset of<br>
logic. But for now, folding things into the primary template is<br>
a non-trivial simplification with no down sides I see. It shortens the<br>
code considerably, removes an unhelpful abstraction, and will make<br>
subsequent patches *dramatically* less complex which enhance the<br>
analysis manager infrastructure to effectively cope with invalidation.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/<wbr>PassManager.h<br>
<br>
Modified: llvm/trunk/include/llvm/IR/<wbr>PassManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=279221&r1=279220&r2=279221&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/IR/PassManager.h?rev=<wbr>279221&r1=279220&r2=279221&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/IR/<wbr>PassManager.h (original)<br>
+++ llvm/trunk/include/llvm/IR/<wbr>PassManager.h Fri Aug 19 03:31:47 2016<br>
@@ -302,52 +302,58 @@ extern template class PassManager<Functi<br>
 /// \brief Convenience typedef for a pass manager over functions.<br>
 typedef PassManager<Function> FunctionPassManager;<br>
<br>
-namespace detail {<br>
-<br>
-/// \brief A CRTP base used to implement analysis managers.<br>
-///<br>
-/// This class template serves as the boiler plate of an analysis manager. Any<br>
-/// analysis manager can be implemented on top of this base class. Any<br>
-/// implementation will be required to provide specific hooks:<br>
-///<br>
-/// - getResultImpl<br>
-/// - getCachedResultImpl<br>
-/// - invalidateImpl<br>
-///<br>
-/// The details of the call pattern are within.<br>
+/// \brief A generic analysis pass manager with lazy running and caching of<br>
+/// results.<br>
 ///<br>
-/// Note that there is also a generic analysis manager template which implements<br>
-/// the above required functions along with common datastructures used for<br>
-/// managing analyses. This base class is factored so that if you need to<br>
-/// customize the handling of a specific IR unit, you can do so without<br>
-/// replicating *all* of the boilerplate.<br>
-template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {<br>
-  DerivedT *derived_this() { return static_cast<DerivedT *>(this); }<br>
-  const DerivedT *derived_this() const {<br>
-    return static_cast<const DerivedT *>(this);<br>
-  }<br>
-<br>
-  AnalysisManagerBase(const AnalysisManagerBase &) = delete;<br>
-  AnalysisManagerBase &operator=(const AnalysisManagerBase &) = delete;<br>
-<br>
-protected:<br>
+/// This analysis manager can be used for any IR unit where the address of the<br>
+/// IR unit sufficies as its identity. It manages the cache for a unit of IR via<br>
+/// the address of each unit of IR cached.<br>
+template <typename IRUnitT><br>
+class AnalysisManager {<br>
   typedef detail::AnalysisResultConcept<<wbr>IRUnitT> ResultConceptT;<br>
   typedef detail::AnalysisPassConcept<<wbr>IRUnitT> PassConceptT;<br>
<br>
-  // FIXME: Provide template aliases for the models when we're using C++11 in<br>
-  // a mode supporting them.<br>
+public:<br>
+  // Most public APIs are inherited from the CRTP base class.<br>
+<br>
+  /// \brief Construct an empty analysis manager.<br>
+  ///<br>
+  /// A flag can be passed to indicate that the manager should perform debug<br>
+  /// logging.<br>
+  AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}<br>
<br>
   // We have to explicitly define all the special member functions because MSVC<br>
   // refuses to generate them.<br>
-  AnalysisManagerBase() {}<br>
-  AnalysisManagerBase(<wbr>AnalysisManagerBase &&Arg)<br>
-      : AnalysisPasses(std::move(Arg.<wbr>AnalysisPasses)) {}<br>
-  AnalysisManagerBase &operator=(AnalysisManagerBase &&RHS) {<br>
+  AnalysisManager(<wbr>AnalysisManager &&Arg)<br>
+      : AnalysisPasses(std::move(Arg.<wbr>AnalysisPasses)),<br>
+        AnalysisResults(std::move(Arg.<wbr>AnalysisResults)),<br>
+        DebugLogging(std::move(Arg.<wbr>DebugLogging)) {}<br>
+  AnalysisManager &operator=(AnalysisManager &&RHS) {<br>
     AnalysisPasses = std::move(RHS.AnalysisPasses);<br>
+    AnalysisResults = std::move(RHS.AnalysisResults)<wbr>;<br>
+    DebugLogging = std::move(RHS.DebugLogging);<br>
     return *this;<br>
   }<br>
<br>
-public:<br>
+  /// \brief Returns true if the analysis manager has an empty results cache.<br>
+  bool empty() const {<br>
+    assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&<br>
+           "The storage and index of analysis results disagree on how many "<br>
+           "there are!");<br>
+    return AnalysisResults.empty();<br>
+  }<br>
+<br>
+  /// \brief Clear the analysis result cache.<br>
+  ///<br>
+  /// This routine allows cleaning up when the set of IR units itself has<br>
+  /// potentially changed, and thus we can't even look up a a result and<br>
+  /// invalidate it directly. Notably, this does *not* call invalidate functions<br>
+  /// as there is nothing to be done for them.<br>
+  void clear() {<br>
+    AnalysisResults.clear();<br>
+    AnalysisResultLists.clear();<br>
+  }<br>
+<br>
   /// \brief Get the result of an analysis pass for this module.<br>
   ///<br>
   /// If there is not a valid cached result in the manager already, this will<br>
@@ -356,8 +362,7 @@ public:<br>
     assert(AnalysisPasses.count(<wbr>PassT::ID()) &&<br>
            "This analysis pass was not registered prior to being queried");<br>
<br>
-    ResultConceptT &ResultConcept =<br>
-        derived_this()->getResultImpl(<wbr>PassT::ID(), IR);<br>
+    ResultConceptT &ResultConcept = getResultImpl(PassT::ID(), IR);<br>
     typedef detail::AnalysisResultModel<<wbr>IRUnitT, PassT, typename PassT::Result><br>
         ResultModelT;<br>
     return static_cast<ResultModelT &>(ResultConcept).Result;<br>
@@ -373,8 +378,7 @@ public:<br>
     assert(AnalysisPasses.count(<wbr>PassT::ID()) &&<br>
            "This analysis pass was not registered prior to being queried");<br>
<br>
-    ResultConceptT *ResultConcept =<br>
-        derived_this()-><wbr>getCachedResultImpl(PassT::ID(<wbr>), IR);<br>
+    ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(<wbr>), IR);<br>
     if (!ResultConcept)<br>
       return nullptr;<br>
<br>
@@ -421,7 +425,7 @@ public:<br>
   template <typename PassT> void invalidate(IRUnitT &IR) {<br>
     assert(AnalysisPasses.count(<wbr>PassT::ID()) &&<br>
            "This analysis pass was not registered prior to being invalidated");<br>
-    derived_this()-><wbr>invalidateImpl(PassT::ID(), IR);<br>
+    invalidateImpl(PassT::ID(), IR);<br>
   }<br>
<br>
   /// \brief Invalidate analyses cached for an IR unit.<br>
@@ -432,10 +436,55 @@ public:<br>
   /// analyis pass which has been successfully invalidated and thus can be<br>
   /// preserved going forward. The updated set is returned.<br>
   PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) {<br>
-    return derived_this()-><wbr>invalidateImpl(IR, std::move(PA));<br>
+    // Short circuit for a common case of all analyses being preserved.<br>
+    if (PA.areAllPreserved())<br>
+      return PA;<br>
+<br>
+    if (DebugLogging)<br>
+      dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName()<br>
+             << "\n";<br>
+<br>
+    // Clear all the invalidated results associated specifically with this<br>
+    // function.<br>
+    SmallVector<void *, 8> InvalidatedPassIDs;<br>
+    AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];<br>
+    for (typename AnalysisResultListT::iterator I = ResultsList.begin(),<br>
+                                                E = ResultsList.end();<br>
+         I != E;) {<br>
+      void *PassID = I->first;<br>
+<br>
+      // Pass the invalidation down to the pass itself to see if it thinks it is<br>
+      // necessary. The analysis pass can return false if no action on the part<br>
+      // of the analysis manager is required for this invalidation event.<br>
+      if (I->second->invalidate(IR, PA)) {<br>
+        if (DebugLogging)<br>
+          dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name(<wbr>)<br>
+                 << "\n";<br>
+<br>
+        InvalidatedPassIDs.push_back(<wbr>I->first);<br>
+        I = ResultsList.erase(I);<br>
+      } else {<br>
+        ++I;<br>
+      }<br>
+<br>
+      // After handling each pass, we mark it as preserved. Once we've<br>
+      // invalidated any stale results, the rest of the system is allowed to<br>
+      // start preserving this analysis again.<br>
+      PA.preserve(PassID);<br>
+    }<br>
+    while (!InvalidatedPassIDs.empty())<br>
+      AnalysisResults.erase(<br>
+          std::make_pair(<wbr>InvalidatedPassIDs.pop_back_<wbr>val(), &IR));<br>
+    if (ResultsList.empty())<br>
+      AnalysisResultLists.erase(&IR)<wbr>;<br>
+<br>
+    return PA;<br>
   }<br>
<br>
-protected:<br>
+private:<br>
+  AnalysisManager(const AnalysisManager &) = delete;<br>
+  AnalysisManager &operator=(const AnalysisManager &) = delete;<br>
+<br>
   /// \brief Lookup a registered analysis pass.<br>
   PassConceptT &lookupPass(void *PassID) {<br>
     typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(PassID);<br>
@@ -452,75 +501,6 @@ protected:<br>
     return *PI->second;<br>
   }<br>
<br>
-private:<br>
-  /// \brief Map type from module analysis pass ID to pass concept pointer.<br>
-  typedef DenseMap<void *, std::unique_ptr<PassConceptT>> AnalysisPassMapT;<br>
-<br>
-  /// \brief Collection of module analysis passes, indexed by ID.<br>
-  AnalysisPassMapT AnalysisPasses;<br>
-};<br>
-<br>
-} // End namespace detail<br>
-<br>
-/// \brief A generic analysis pass manager with lazy running and caching of<br>
-/// results.<br>
-///<br>
-/// This analysis manager can be used for any IR unit where the address of the<br>
-/// IR unit sufficies as its identity. It manages the cache for a unit of IR via<br>
-/// the address of each unit of IR cached.<br>
-template <typename IRUnitT><br>
-class AnalysisManager<br>
-    : public detail::AnalysisManagerBase<<wbr>AnalysisManager<IRUnitT>, IRUnitT> {<br>
-  friend class detail::AnalysisManagerBase<<wbr>AnalysisManager<IRUnitT>, IRUnitT>;<br>
-  typedef detail::AnalysisManagerBase<<wbr>AnalysisManager<IRUnitT>, IRUnitT> BaseT;<br>
-  typedef typename BaseT::ResultConceptT ResultConceptT;<br>
-  typedef typename BaseT::PassConceptT PassConceptT;<br>
-<br>
-public:<br>
-  // Most public APIs are inherited from the CRTP base class.<br>
-<br>
-  /// \brief Construct an empty analysis manager.<br>
-  ///<br>
-  /// A flag can be passed to indicate that the manager should perform debug<br>
-  /// logging.<br>
-  AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}<br>
-<br>
-  // We have to explicitly define all the special member functions because MSVC<br>
-  // refuses to generate them.<br>
-  AnalysisManager(<wbr>AnalysisManager &&Arg)<br>
-      : BaseT(std::move(static_cast<<wbr>BaseT &>(Arg))),<br>
-        AnalysisResults(std::move(Arg.<wbr>AnalysisResults)),<br>
-        DebugLogging(std::move(Arg.<wbr>DebugLogging)) {}<br>
-  AnalysisManager &operator=(AnalysisManager &&RHS) {<br>
-    BaseT::operator=(std::move(<wbr>static_cast<BaseT &>(RHS)));<br>
-    AnalysisResults = std::move(RHS.AnalysisResults)<wbr>;<br>
-    DebugLogging = std::move(RHS.DebugLogging);<br>
-    return *this;<br>
-  }<br>
-<br>
-  /// \brief Returns true if the analysis manager has an empty results cache.<br>
-  bool empty() const {<br>
-    assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&<br>
-           "The storage and index of analysis results disagree on how many "<br>
-           "there are!");<br>
-    return AnalysisResults.empty();<br>
-  }<br>
-<br>
-  /// \brief Clear the analysis result cache.<br>
-  ///<br>
-  /// This routine allows cleaning up when the set of IR units itself has<br>
-  /// potentially changed, and thus we can't even look up a a result and<br>
-  /// invalidate it directly. Notably, this does *not* call invalidate functions<br>
-  /// as there is nothing to be done for them.<br>
-  void clear() {<br>
-    AnalysisResults.clear();<br>
-    AnalysisResultLists.clear();<br>
-  }<br>
-<br>
-private:<br>
-  AnalysisManager(const AnalysisManager &) = delete;<br>
-  AnalysisManager &operator=(const AnalysisManager &) = delete;<br>
-<br>
   /// \brief Get an analysis result, running the pass if necessary.<br>
   ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) {<br>
     typename AnalysisResultMapT::iterator RI;<br>
@@ -569,52 +549,11 @@ private:<br>
     AnalysisResults.erase(RI);<br>
   }<br>
<br>
-  /// \brief Invalidate the results for a function..<br>
-  PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) {<br>
-    // Short circuit for a common case of all analyses being preserved.<br>
-    if (PA.areAllPreserved())<br>
-      return PA;<br>
-<br>
-    if (DebugLogging)<br>
-      dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName()<br>
-             << "\n";<br>
-<br>
-    // Clear all the invalidated results associated specifically with this<br>
-    // function.<br>
-    SmallVector<void *, 8> InvalidatedPassIDs;<br>
-    AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];<br>
-    for (typename AnalysisResultListT::iterator I = ResultsList.begin(),<br>
-                                                E = ResultsList.end();<br>
-         I != E;) {<br>
-      void *PassID = I->first;<br>
-<br>
-      // Pass the invalidation down to the pass itself to see if it thinks it is<br>
-      // necessary. The analysis pass can return false if no action on the part<br>
-      // of the analysis manager is required for this invalidation event.<br>
-      if (I->second->invalidate(IR, PA)) {<br>
-        if (DebugLogging)<br>
-          dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name(<wbr>)<br>
-                 << "\n";<br>
-<br>
-        InvalidatedPassIDs.push_back(<wbr>I->first);<br>
-        I = ResultsList.erase(I);<br>
-      } else {<br>
-        ++I;<br>
-      }<br>
-<br>
-      // After handling each pass, we mark it as preserved. Once we've<br>
-      // invalidated any stale results, the rest of the system is allowed to<br>
-      // start preserving this analysis again.<br>
-      PA.preserve(PassID);<br>
-    }<br>
-    while (!InvalidatedPassIDs.empty())<br>
-      AnalysisResults.erase(<br>
-          std::make_pair(<wbr>InvalidatedPassIDs.pop_back_<wbr>val(), &IR));<br>
-    if (ResultsList.empty())<br>
-      AnalysisResultLists.erase(&IR)<wbr>;<br>
+  /// \brief Map type from module analysis pass ID to pass concept pointer.<br>
+  typedef DenseMap<void *, std::unique_ptr<PassConceptT>> AnalysisPassMapT;<br>
<br>
-    return PA;<br>
-  }<br>
+  /// \brief Collection of module analysis passes, indexed by ID.<br>
+  AnalysisPassMapT AnalysisPasses;<br>
<br>
   /// \brief List of function analysis pass IDs and associated concept pointers.<br>
   ///<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>