-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LegacyPM] Drop analysis groups #101670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LegacyPM] Drop analysis groups #101670
Conversation
This improves the performance of recordAvailableAnalysis and freePass, because they don't need to call getPassInfo().
@llvm/pr-subscribers-llvm-ir Author: Alexis Engelke (aengelke) ChangesThis 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 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:
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]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/30/builds/3346 Here is the relevant piece of the build log for the reference:
|
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