[llvm] [LegacyPM] Drop analysis groups (PR #101670)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 2 06:16:22 PDT 2024
https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/101670
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)
>From 52389714b96f931327d34f23c2c4c2b6ee57e91c Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Fri, 2 Aug 2024 12:37:18 +0000
Subject: [PATCH] [LegacyPM] Drop analysis groups
This improves the performance of recordAvailableAnalysis and freePass,
because they don't need to call getPassInfo().
---
llvm/docs/WritingAnLLVMPass.rst | 118 ------------------------------
llvm/include/llvm/Pass.h | 3 +-
llvm/include/llvm/PassInfo.h | 28 +------
llvm/include/llvm/PassRegistry.h | 7 --
llvm/include/llvm/PassSupport.h | 91 -----------------------
llvm/lib/IR/LegacyPassManager.cpp | 42 ++---------
llvm/lib/IR/Pass.cpp | 13 ----
llvm/lib/IR/PassRegistry.cpp | 39 ----------
8 files changed, 7 insertions(+), 334 deletions(-)
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,19 +204,6 @@ Pass *Pass::createPass(AnalysisID ID) {
return PI->createPass();
}
-//===----------------------------------------------------------------------===//
-// Analysis Group Implementation Code
-//===----------------------------------------------------------------------===//
-
-// RegisterAGBase implementation
-
-RegisterAGBase::RegisterAGBase(StringRef Name, const void *InterfaceID,
- const void *PassID, bool isDefault)
- : PassInfo(Name, InterfaceID) {
- PassRegistry::getPassRegistry()->registerAnalysisGroup(InterfaceID, PassID,
- *this, isDefault);
-}
-
//===----------------------------------------------------------------------===//
// PassRegistrationListener implementation
//
diff --git a/llvm/lib/IR/PassRegistry.cpp b/llvm/lib/IR/PassRegistry.cpp
index 6c22fcd347694..94afbb52d70e3 100644
--- a/llvm/lib/IR/PassRegistry.cpp
+++ b/llvm/lib/IR/PassRegistry.cpp
@@ -68,45 +68,6 @@ void PassRegistry::enumerateWith(PassRegistrationListener *L) {
L->passEnumerate(PassInfoPair.second);
}
-/// Analysis Group Mechanisms.
-void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
- const void *PassID,
- PassInfo &Registeree, bool isDefault,
- bool ShouldFree) {
- PassInfo *InterfaceInfo = const_cast<PassInfo *>(getPassInfo(InterfaceID));
- if (!InterfaceInfo) {
- // First reference to Interface, register it now.
- registerPass(Registeree);
- InterfaceInfo = &Registeree;
- }
- assert(Registeree.isAnalysisGroup() &&
- "Trying to join an analysis group that is a normal pass!");
-
- if (PassID) {
- PassInfo *ImplementationInfo = const_cast<PassInfo *>(getPassInfo(PassID));
- assert(ImplementationInfo &&
- "Must register pass before adding to AnalysisGroup!");
-
- sys::SmartScopedWriter<true> Guard(Lock);
-
- // Make sure we keep track of the fact that the implementation implements
- // the interface.
- ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
-
- if (isDefault) {
- assert(InterfaceInfo->getNormalCtor() == nullptr &&
- "Default implementation for analysis group already specified!");
- assert(
- ImplementationInfo->getNormalCtor() &&
- "Cannot specify pass as default if it does not have a default ctor");
- InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
- }
- }
-
- if (ShouldFree)
- ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree));
-}
-
void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
sys::SmartScopedWriter<true> Guard(Lock);
Listeners.push_back(L);
More information about the llvm-commits
mailing list