[llvm] [LegacyPM] Drop analysis groups (PR #101670)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 2 06:17:02 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: Alexis Engelke (aengelke)

<details>
<summary>Changes</summary>

This improves the performance of recordAvailableAnalysis and freePass so that they don't need to call getPassInfo(), which acquires a lock on every call.

The performance-wise interesting part is only in LegacyPassManager.cpp, everything else is just cleanup.

While the port of the back-end to the new pass manager is progressing, we can sill make minor and low-effort improvements to the legacy PM -- I'd expect that this will still be in use for some time. [c-t-t](http://llvm-compile-time-tracker.com/compare.php?from=e7f9d8e5c3e49e729c69aaa9be3322f7902370b8&to=648e9e3f4b07010a5f0b05ce4cdbc357973d8740&stat=instructions:u)

---

Patch is 22.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/101670.diff


8 Files Affected:

- (modified) llvm/docs/WritingAnLLVMPass.rst (-118) 
- (modified) llvm/include/llvm/Pass.h (+1-2) 
- (modified) llvm/include/llvm/PassInfo.h (+1-27) 
- (modified) llvm/include/llvm/PassRegistry.h (-7) 
- (modified) llvm/include/llvm/PassSupport.h (-91) 
- (modified) llvm/lib/IR/LegacyPassManager.cpp (+5-37) 
- (modified) llvm/lib/IR/Pass.cpp (-13) 
- (modified) llvm/lib/IR/PassRegistry.cpp (-39) 


``````````diff
diff --git a/llvm/docs/WritingAnLLVMPass.rst b/llvm/docs/WritingAnLLVMPass.rst
index 2b5809827f757..d2afa3913ee07 100644
--- a/llvm/docs/WritingAnLLVMPass.rst
+++ b/llvm/docs/WritingAnLLVMPass.rst
@@ -580,124 +580,6 @@ it is active.  For example:
     // A DominatorSet is active.  This code will update it.
   }
 
-Implementing Analysis Groups
-----------------------------
-
-Now that we understand the basics of how passes are defined, how they are used,
-and how they are required from other passes, it's time to get a little bit
-fancier.  All of the pass relationships that we have seen so far are very
-simple: one pass depends on one other specific pass to be run before it can
-run.  For many applications, this is great, for others, more flexibility is
-required.
-
-In particular, some analyses are defined such that there is a single simple
-interface to the analysis results, but multiple ways of calculating them.
-Consider alias analysis for example.  The most trivial alias analysis returns
-"may alias" for any alias query.  The most sophisticated analysis a
-flow-sensitive, context-sensitive interprocedural analysis that can take a
-significant amount of time to execute (and obviously, there is a lot of room
-between these two extremes for other implementations).  To cleanly support
-situations like this, the LLVM Pass Infrastructure supports the notion of
-Analysis Groups.
-
-Analysis Group Concepts
-^^^^^^^^^^^^^^^^^^^^^^^
-
-An Analysis Group is a single simple interface that may be implemented by
-multiple different passes.  Analysis Groups can be given human readable names
-just like passes, but unlike passes, they need not derive from the ``Pass``
-class.  An analysis group may have one or more implementations, one of which is
-the "default" implementation.
-
-Analysis groups are used by client passes just like other passes are: the
-``AnalysisUsage::addRequired()`` and ``Pass::getAnalysis()`` methods.  In order
-to resolve this requirement, the :ref:`PassManager
-<writing-an-llvm-pass-passmanager>` scans the available passes to see if any
-implementations of the analysis group are available.  If none is available, the
-default implementation is created for the pass to use.  All standard rules for
-:ref:`interaction between passes <writing-an-llvm-pass-interaction>` still
-apply.
-
-Although :ref:`Pass Registration <writing-an-llvm-pass-registration>` is
-optional for normal passes, all analysis group implementations must be
-registered, and must use the :ref:`INITIALIZE_AG_PASS
-<writing-an-llvm-pass-RegisterAnalysisGroup>` template to join the
-implementation pool.  Also, a default implementation of the interface **must**
-be registered with :ref:`RegisterAnalysisGroup
-<writing-an-llvm-pass-RegisterAnalysisGroup>`.
-
-As a concrete example of an Analysis Group in action, consider the
-`AliasAnalysis <https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_
-analysis group.  The default implementation of the alias analysis interface
-(the `basic-aa <https://llvm.org/doxygen/structBasicAliasAnalysis.html>`_ pass)
-just does a few simple checks that don't require significant analysis to
-compute (such as: two different globals can never alias each other, etc).
-Passes that use the `AliasAnalysis
-<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_ interface (for
-example the `gvn <https://llvm.org/doxygen/classllvm_1_1GVN.html>`_ pass), do not
-care which implementation of alias analysis is actually provided, they just use
-the designated interface.
-
-From the user's perspective, commands work just like normal.  Issuing the
-command ``opt -gvn ...`` will cause the ``basic-aa`` class to be instantiated
-and added to the pass sequence.  Issuing the command ``opt -somefancyaa -gvn
-...`` will cause the ``gvn`` pass to use the ``somefancyaa`` alias analysis
-(which doesn't actually exist, it's just a hypothetical example) instead.
-
-.. _writing-an-llvm-pass-RegisterAnalysisGroup:
-
-Using ``RegisterAnalysisGroup``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``RegisterAnalysisGroup`` template is used to register the analysis group
-itself, while the ``INITIALIZE_AG_PASS`` is used to add pass implementations to
-the analysis group.  First, an analysis group should be registered, with a
-human readable name provided for it.  Unlike registration of passes, there is
-no command line argument to be specified for the Analysis Group Interface
-itself, because it is "abstract":
-
-.. code-block:: c++
-
-  static RegisterAnalysisGroup<AliasAnalysis> A("Alias Analysis");
-
-Once the analysis is registered, passes can declare that they are valid
-implementations of the interface by using the following code:
-
-.. code-block:: c++
-
-  namespace {
-    // Declare that we implement the AliasAnalysis interface
-    INITIALIZE_AG_PASS(FancyAA, AliasAnalysis , "somefancyaa",
-        "A more complex alias analysis implementation",
-        false,  // Is CFG Only?
-        true,   // Is Analysis?
-        false); // Is default Analysis Group implementation?
-  }
-
-This just shows a class ``FancyAA`` that uses the ``INITIALIZE_AG_PASS`` macro
-both to register and to "join" the `AliasAnalysis
-<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_ analysis group.
-Every implementation of an analysis group should join using this macro.
-
-.. code-block:: c++
-
-  namespace {
-    // Declare that we implement the AliasAnalysis interface
-    INITIALIZE_AG_PASS(BasicAA, AliasAnalysis, "basic-aa",
-        "Basic Alias Analysis (default AA impl)",
-        false, // Is CFG Only?
-        true,  // Is Analysis?
-        true); // Is default Analysis Group implementation?
-  }
-
-Here we show how the default implementation is specified (using the final
-argument to the ``INITIALIZE_AG_PASS`` template).  There must be exactly one
-default implementation available at all times for an Analysis Group to be used.
-Only default implementation can derive from ``ImmutablePass``.  Here we declare
-that the `BasicAliasAnalysis
-<https://llvm.org/doxygen/structBasicAliasAnalysis.html>`_ pass is the default
-implementation for the interface.
-
 Pass Statistics
 ===============
 
diff --git a/llvm/include/llvm/Pass.h b/llvm/include/llvm/Pass.h
index 44b6dd95cc278..463137bdbfcaf 100644
--- a/llvm/include/llvm/Pass.h
+++ b/llvm/include/llvm/Pass.h
@@ -276,8 +276,7 @@ class ModulePass : public Pass {
 
 //===----------------------------------------------------------------------===//
 /// ImmutablePass class - This class is used to provide information that does
-/// not need to be run.  This is useful for things like target information and
-/// "basic" versions of AnalysisGroups.
+/// not need to be run.  This is useful for things like target information.
 ///
 class ImmutablePass : public ModulePass {
 public:
diff --git a/llvm/include/llvm/PassInfo.h b/llvm/include/llvm/PassInfo.h
index 686fc044ebcb3..380d6698d0c80 100644
--- a/llvm/include/llvm/PassInfo.h
+++ b/llvm/include/llvm/PassInfo.h
@@ -37,8 +37,6 @@ class PassInfo {
   const void *PassID;
   const bool IsCFGOnlyPass = false;      // Pass only looks at the CFG.
   const bool IsAnalysis;                 // True if an analysis pass.
-  const bool IsAnalysisGroup;            // True if an analysis group.
-  std::vector<const PassInfo *> ItfImpl; // Interfaces implemented by this pass
   NormalCtor_t NormalCtor = nullptr;
 
 public:
@@ -47,13 +45,7 @@ class PassInfo {
   PassInfo(StringRef name, StringRef arg, const void *pi, NormalCtor_t normal,
            bool isCFGOnly, bool is_analysis)
       : PassName(name), PassArgument(arg), PassID(pi), IsCFGOnlyPass(isCFGOnly),
-        IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) {}
-
-  /// PassInfo ctor - Do not call this directly, this should only be invoked
-  /// through RegisterPass. This version is for use by analysis groups; it
-  /// does not auto-register the pass.
-  PassInfo(StringRef name, const void *pi)
-      : PassName(name), PassID(pi), IsAnalysis(false), IsAnalysisGroup(true) {}
+        IsAnalysis(is_analysis), NormalCtor(normal) {}
 
   PassInfo(const PassInfo &) = delete;
   PassInfo &operator=(const PassInfo &) = delete;
@@ -73,9 +65,6 @@ class PassInfo {
   /// Return true if this PassID implements the specified ID pointer.
   bool isPassID(const void *IDPtr) const { return PassID == IDPtr; }
 
-  /// isAnalysisGroup - Return true if this is an analysis group, not a normal
-  /// pass.
-  bool isAnalysisGroup() const { return IsAnalysisGroup; }
   bool isAnalysis() const { return IsAnalysis; }
 
   /// isCFGOnlyPass - return true if this pass only looks at the CFG for the
@@ -94,25 +83,10 @@ class PassInfo {
 
   /// createPass() - Use this method to create an instance of this pass.
   Pass *createPass() const {
-    assert((!isAnalysisGroup() || NormalCtor) &&
-           "No default implementation found for analysis group!");
     assert(NormalCtor &&
            "Cannot call createPass on PassInfo without default ctor!");
     return NormalCtor();
   }
-
-  /// addInterfaceImplemented - This method is called when this pass is
-  /// registered as a member of an analysis group with the RegisterAnalysisGroup
-  /// template.
-  void addInterfaceImplemented(const PassInfo *ItfPI) {
-    ItfImpl.push_back(ItfPI);
-  }
-
-  /// getInterfacesImplemented - Return a list of all of the analysis group
-  /// interfaces implemented by this pass.
-  const std::vector<const PassInfo*> &getInterfacesImplemented() const {
-    return ItfImpl;
-  }
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/PassRegistry.h b/llvm/include/llvm/PassRegistry.h
index 5d7f3a84a6be7..003c0ac4c374b 100644
--- a/llvm/include/llvm/PassRegistry.h
+++ b/llvm/include/llvm/PassRegistry.h
@@ -68,13 +68,6 @@ class PassRegistry {
   /// registry.  Required in order to use the pass with a PassManager.
   void registerPass(const PassInfo &PI, bool ShouldFree = false);
 
-  /// registerAnalysisGroup - Register an analysis group (or a pass implementing
-  // an analysis group) with the registry.  Like registerPass, this is required
-  // in order for a PassManager to be able to use this group/pass.
-  void registerAnalysisGroup(const void *InterfaceID, const void *PassID,
-                             PassInfo &Registeree, bool isDefault,
-                             bool ShouldFree = false);
-
   /// enumerateWith - Enumerate the registered passes, calling the provided
   /// PassRegistrationListener's passEnumerate() callback on each of them.
   void enumerateWith(PassRegistrationListener *L);
diff --git a/llvm/include/llvm/PassSupport.h b/llvm/include/llvm/PassSupport.h
index 774ece89bf01e..d3ba32f22efe1 100644
--- a/llvm/include/llvm/PassSupport.h
+++ b/llvm/include/llvm/PassSupport.h
@@ -53,8 +53,6 @@ class Pass;
   static void *initialize##passName##PassOnce(PassRegistry &Registry) {
 
 #define INITIALIZE_PASS_DEPENDENCY(depName) initialize##depName##Pass(Registry);
-#define INITIALIZE_AG_DEPENDENCY(depName)                                      \
-  initialize##depName##AnalysisGroup(Registry);
 
 #define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)                \
   PassInfo *PI = new PassInfo(                                                 \
@@ -117,95 +115,6 @@ template <typename passName> struct RegisterPass : public PassInfo {
   }
 };
 
-/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_.
-/// Analysis groups are used to define an interface (which need not derive from
-/// Pass) that is required by passes to do their job.  Analysis Groups differ
-/// from normal analyses because any available implementation of the group will
-/// be used if it is available.
-///
-/// If no analysis implementing the interface is available, a default
-/// implementation is created and added.  A pass registers itself as the default
-/// implementation by specifying 'true' as the second template argument of this
-/// class.
-///
-/// In addition to registering itself as an analysis group member, a pass must
-/// register itself normally as well.  Passes may be members of multiple groups
-/// and may still be "required" specifically by name.
-///
-/// The actual interface may also be registered as well (by not specifying the
-/// second template argument).  The interface should be registered to associate
-/// a nice name with the interface.
-class RegisterAGBase : public PassInfo {
-public:
-  RegisterAGBase(StringRef Name, const void *InterfaceID,
-                 const void *PassID = nullptr, bool isDefault = false);
-};
-
-template <typename Interface, bool Default = false>
-struct RegisterAnalysisGroup : public RegisterAGBase {
-  explicit RegisterAnalysisGroup(PassInfo &RPB)
-      : RegisterAGBase(RPB.getPassName(), &Interface::ID, RPB.getTypeInfo(),
-                       Default) {}
-
-  explicit RegisterAnalysisGroup(const char *Name)
-      : RegisterAGBase(Name, &Interface::ID) {}
-};
-
-#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass)                   \
-  static void *initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \
-    initialize##defaultPass##Pass(Registry);                                   \
-    PassInfo *AI = new PassInfo(name, &agName::ID);                            \
-    Registry.registerAnalysisGroup(&agName::ID, 0, *AI, false, true);          \
-    return AI;                                                                 \
-  }                                                                            \
-  static llvm::once_flag Initialize##agName##AnalysisGroupFlag;                \
-  void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) {       \
-    llvm::call_once(Initialize##agName##AnalysisGroupFlag,                     \
-                    initialize##agName##AnalysisGroupOnce,                     \
-                    std::ref(Registry));                                       \
-  }
-
-#define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def)    \
-  static void *initialize##passName##PassOnce(PassRegistry &Registry) {        \
-    if (!def)                                                                  \
-      initialize##agName##AnalysisGroup(Registry);                             \
-    PassInfo *PI = new PassInfo(                                               \
-        name, arg, &passName::ID,                                              \
-        PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis);     \
-    Registry.registerPass(*PI, true);                                          \
-                                                                               \
-    PassInfo *AI = new PassInfo(name, &agName::ID);                            \
-    Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def,       \
-                                   true);                                      \
-    return AI;                                                                 \
-  }                                                                            \
-  static llvm::once_flag Initialize##passName##PassFlag;                       \
-  void llvm::initialize##passName##Pass(PassRegistry &Registry) {              \
-    llvm::call_once(Initialize##passName##PassFlag,                            \
-                    initialize##passName##PassOnce, std::ref(Registry));       \
-  }
-
-#define INITIALIZE_AG_PASS_BEGIN(passName, agName, arg, n, cfg, analysis, def) \
-  static void *initialize##passName##PassOnce(PassRegistry &Registry) {        \
-    if (!def)                                                                  \
-      initialize##agName##AnalysisGroup(Registry);
-
-#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def)   \
-  PassInfo *PI = new PassInfo(                                                 \
-      n, arg, &passName::ID,                                                   \
-      PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis);       \
-  Registry.registerPass(*PI, true);                                            \
-                                                                               \
-  PassInfo *AI = new PassInfo(n, &agName::ID);                                 \
-  Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, true);  \
-  return AI;                                                                   \
-  }                                                                            \
-  static llvm::once_flag Initialize##passName##PassFlag;                       \
-  void llvm::initialize##passName##Pass(PassRegistry &Registry) {              \
-    llvm::call_once(Initialize##passName##PassFlag,                            \
-                    initialize##passName##PassOnce, std::ref(Registry));       \
-  }
-
 //===---------------------------------------------------------------------------
 /// PassRegistrationListener class - This class is meant to be derived from by
 /// clients that are interested in which passes get registered and unregistered
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp
index 9c44eff7953ac..f2a83b50923e9 100644
--- a/llvm/lib/IR/LegacyPassManager.cpp
+++ b/llvm/lib/IR/LegacyPassManager.cpp
@@ -808,13 +808,6 @@ void PMTopLevelManager::addImmutablePass(ImmutablePass *P) {
   // doing lookups.
   AnalysisID AID = P->getPassID();
   ImmutablePassMap[AID] = P;
-
-  // Also add any interfaces implemented by the immutable pass to the map for
-  // fast lookup.
-  const PassInfo *PassInf = findAnalysisPassInfo(AID);
-  assert(PassInf && "Expected all immutable passes to be initialized");
-  for (const PassInfo *ImmPI : PassInf->getInterfacesImplemented())
-    ImmutablePassMap[ImmPI->getTypeInfo()] = P;
 }
 
 // Print passes managed by this top level manager.
@@ -844,8 +837,7 @@ void PMTopLevelManager::dumpArguments() const {
   for (ImmutablePass *P : ImmutablePasses)
     if (const PassInfo *PI = findAnalysisPassInfo(P->getPassID())) {
       assert(PI && "Expected all immutable passes to be initialized");
-      if (!PI->isAnalysisGroup())
-        dbgs() << " -" << PI->getPassArgument();
+      dbgs() << " -" << PI->getPassArgument();
     }
   for (PMDataManager *PM : PassManagers)
     PM->dumpPassArguments();
@@ -878,15 +870,6 @@ void PMDataManager::recordAvailableAnalysis(Pass *P) {
   AnalysisID PI = P->getPassID();
 
   AvailableAnalysis[PI] = P;
-
-  assert(!AvailableAnalysis.empty());
-
-  // This pass is the current implementation of all of the interfaces it
-  // implements as well.
-  const PassInfo *PInf = TPM->findAnalysisPassInfo(PI);
-  if (!PInf) return;
-  for (const PassInfo *PI : PInf->getInterfacesImplemented())
-    AvailableAnalysis[PI->getTypeInfo()] = P;
 }
 
 // Return true if P preserves high level analysis used by other
@@ -1004,20 +987,8 @@ void PMDataManager::freePass(Pass *P, StringRef Msg,
     P->releaseMemory();
   }
 
-  AnalysisID PI = P->getPassID();
-  if (const PassInfo *PInf = TPM->findAnalysisPassInfo(PI)) {
-    // Remove the pass itself (if it is not already removed).
-    AvailableAnalysis.erase(PI);
-
-    // Remove all interfaces this pass implements, for which it is also
-    // listed as the available implementation.
-    for (const PassInfo *PI : PInf->getInterfacesImplemented()) {
-      DenseMap<AnalysisID, Pass *>::iterator Pos =
-          AvailableAnalysis.find(PI->getTypeInfo());
-      if (Pos != AvailableAnalysis.end() && Pos->second == P)
-        AvailableAnalysis.erase(Pos);
-    }
-  }
+  // Remove the pass itself (if it is not already removed).
+  AvailableAnalysis.erase(P->getPassID());
 }
 
 /// Add pass P into the PassVector. Update
@@ -1173,11 +1144,8 @@ void PMDataManager::dumpPassArguments() const {
   for (Pass *P : PassVector) {
     if (PMDataManager *PMD = P->getAsPMDataManager())
       PMD->dumpPassArguments();
-    else
-      if (const PassInfo *PI =
-            TPM->findAnalysisPassInfo(P->getPassID()))
-        if (!PI->isAnalysisGroup())
-          dbgs() << " -" << PI->getPassArgument();
+    else if (const PassInfo *PI = TPM->findAnalysisPassInfo(P->getPassID()))
+      dbgs() << " -" << PI->getPassArgument();
   }
 }
 
diff --git a/llvm/lib/IR/Pass.cpp b/llvm/lib/IR/Pass.cpp
index d6096ebb3af70..5701bd7680830 100644
--- a/llvm/lib/IR/Pass.cpp
+++ b/llvm/lib/IR/Pass.cpp
@@ -204,1...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/101670


More information about the llvm-commits mailing list