Skip to content

Commit 293df8a

Browse files
authored
[LegacyPM] Drop analysis groups (#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.
1 parent 07aaab8 commit 293df8a

File tree

8 files changed

+7
-334
lines changed

8 files changed

+7
-334
lines changed

llvm/docs/WritingAnLLVMPass.rst

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -580,124 +580,6 @@ it is active. For example:
580580
// A DominatorSet is active. This code will update it.
581581
}
582582
583-
Implementing Analysis Groups
584-
----------------------------
585-
586-
Now that we understand the basics of how passes are defined, how they are used,
587-
and how they are required from other passes, it's time to get a little bit
588-
fancier. All of the pass relationships that we have seen so far are very
589-
simple: one pass depends on one other specific pass to be run before it can
590-
run. For many applications, this is great, for others, more flexibility is
591-
required.
592-
593-
In particular, some analyses are defined such that there is a single simple
594-
interface to the analysis results, but multiple ways of calculating them.
595-
Consider alias analysis for example. The most trivial alias analysis returns
596-
"may alias" for any alias query. The most sophisticated analysis a
597-
flow-sensitive, context-sensitive interprocedural analysis that can take a
598-
significant amount of time to execute (and obviously, there is a lot of room
599-
between these two extremes for other implementations). To cleanly support
600-
situations like this, the LLVM Pass Infrastructure supports the notion of
601-
Analysis Groups.
602-
603-
Analysis Group Concepts
604-
^^^^^^^^^^^^^^^^^^^^^^^
605-
606-
An Analysis Group is a single simple interface that may be implemented by
607-
multiple different passes. Analysis Groups can be given human readable names
608-
just like passes, but unlike passes, they need not derive from the ``Pass``
609-
class. An analysis group may have one or more implementations, one of which is
610-
the "default" implementation.
611-
612-
Analysis groups are used by client passes just like other passes are: the
613-
``AnalysisUsage::addRequired()`` and ``Pass::getAnalysis()`` methods. In order
614-
to resolve this requirement, the :ref:`PassManager
615-
<writing-an-llvm-pass-passmanager>` scans the available passes to see if any
616-
implementations of the analysis group are available. If none is available, the
617-
default implementation is created for the pass to use. All standard rules for
618-
:ref:`interaction between passes <writing-an-llvm-pass-interaction>` still
619-
apply.
620-
621-
Although :ref:`Pass Registration <writing-an-llvm-pass-registration>` is
622-
optional for normal passes, all analysis group implementations must be
623-
registered, and must use the :ref:`INITIALIZE_AG_PASS
624-
<writing-an-llvm-pass-RegisterAnalysisGroup>` template to join the
625-
implementation pool. Also, a default implementation of the interface **must**
626-
be registered with :ref:`RegisterAnalysisGroup
627-
<writing-an-llvm-pass-RegisterAnalysisGroup>`.
628-
629-
As a concrete example of an Analysis Group in action, consider the
630-
`AliasAnalysis <https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_
631-
analysis group. The default implementation of the alias analysis interface
632-
(the `basic-aa <https://llvm.org/doxygen/structBasicAliasAnalysis.html>`_ pass)
633-
just does a few simple checks that don't require significant analysis to
634-
compute (such as: two different globals can never alias each other, etc).
635-
Passes that use the `AliasAnalysis
636-
<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_ interface (for
637-
example the `gvn <https://llvm.org/doxygen/classllvm_1_1GVN.html>`_ pass), do not
638-
care which implementation of alias analysis is actually provided, they just use
639-
the designated interface.
640-
641-
From the user's perspective, commands work just like normal. Issuing the
642-
command ``opt -gvn ...`` will cause the ``basic-aa`` class to be instantiated
643-
and added to the pass sequence. Issuing the command ``opt -somefancyaa -gvn
644-
...`` will cause the ``gvn`` pass to use the ``somefancyaa`` alias analysis
645-
(which doesn't actually exist, it's just a hypothetical example) instead.
646-
647-
.. _writing-an-llvm-pass-RegisterAnalysisGroup:
648-
649-
Using ``RegisterAnalysisGroup``
650-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
651-
652-
The ``RegisterAnalysisGroup`` template is used to register the analysis group
653-
itself, while the ``INITIALIZE_AG_PASS`` is used to add pass implementations to
654-
the analysis group. First, an analysis group should be registered, with a
655-
human readable name provided for it. Unlike registration of passes, there is
656-
no command line argument to be specified for the Analysis Group Interface
657-
itself, because it is "abstract":
658-
659-
.. code-block:: c++
660-
661-
static RegisterAnalysisGroup<AliasAnalysis> A("Alias Analysis");
662-
663-
Once the analysis is registered, passes can declare that they are valid
664-
implementations of the interface by using the following code:
665-
666-
.. code-block:: c++
667-
668-
namespace {
669-
// Declare that we implement the AliasAnalysis interface
670-
INITIALIZE_AG_PASS(FancyAA, AliasAnalysis , "somefancyaa",
671-
"A more complex alias analysis implementation",
672-
false, // Is CFG Only?
673-
true, // Is Analysis?
674-
false); // Is default Analysis Group implementation?
675-
}
676-
677-
This just shows a class ``FancyAA`` that uses the ``INITIALIZE_AG_PASS`` macro
678-
both to register and to "join" the `AliasAnalysis
679-
<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`_ analysis group.
680-
Every implementation of an analysis group should join using this macro.
681-
682-
.. code-block:: c++
683-
684-
namespace {
685-
// Declare that we implement the AliasAnalysis interface
686-
INITIALIZE_AG_PASS(BasicAA, AliasAnalysis, "basic-aa",
687-
"Basic Alias Analysis (default AA impl)",
688-
false, // Is CFG Only?
689-
true, // Is Analysis?
690-
true); // Is default Analysis Group implementation?
691-
}
692-
693-
Here we show how the default implementation is specified (using the final
694-
argument to the ``INITIALIZE_AG_PASS`` template). There must be exactly one
695-
default implementation available at all times for an Analysis Group to be used.
696-
Only default implementation can derive from ``ImmutablePass``. Here we declare
697-
that the `BasicAliasAnalysis
698-
<https://llvm.org/doxygen/structBasicAliasAnalysis.html>`_ pass is the default
699-
implementation for the interface.
700-
701583
Pass Statistics
702584
===============
703585

llvm/include/llvm/Pass.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ class ModulePass : public Pass {
276276

277277
//===----------------------------------------------------------------------===//
278278
/// ImmutablePass class - This class is used to provide information that does
279-
/// not need to be run. This is useful for things like target information and
280-
/// "basic" versions of AnalysisGroups.
279+
/// not need to be run. This is useful for things like target information.
281280
///
282281
class ImmutablePass : public ModulePass {
283282
public:

llvm/include/llvm/PassInfo.h

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ class PassInfo {
3737
const void *PassID;
3838
const bool IsCFGOnlyPass = false; // Pass only looks at the CFG.
3939
const bool IsAnalysis; // True if an analysis pass.
40-
const bool IsAnalysisGroup; // True if an analysis group.
41-
std::vector<const PassInfo *> ItfImpl; // Interfaces implemented by this pass
4240
NormalCtor_t NormalCtor = nullptr;
4341

4442
public:
@@ -47,13 +45,7 @@ class PassInfo {
4745
PassInfo(StringRef name, StringRef arg, const void *pi, NormalCtor_t normal,
4846
bool isCFGOnly, bool is_analysis)
4947
: PassName(name), PassArgument(arg), PassID(pi), IsCFGOnlyPass(isCFGOnly),
50-
IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) {}
51-
52-
/// PassInfo ctor - Do not call this directly, this should only be invoked
53-
/// through RegisterPass. This version is for use by analysis groups; it
54-
/// does not auto-register the pass.
55-
PassInfo(StringRef name, const void *pi)
56-
: PassName(name), PassID(pi), IsAnalysis(false), IsAnalysisGroup(true) {}
48+
IsAnalysis(is_analysis), NormalCtor(normal) {}
5749

5850
PassInfo(const PassInfo &) = delete;
5951
PassInfo &operator=(const PassInfo &) = delete;
@@ -73,9 +65,6 @@ class PassInfo {
7365
/// Return true if this PassID implements the specified ID pointer.
7466
bool isPassID(const void *IDPtr) const { return PassID == IDPtr; }
7567

76-
/// isAnalysisGroup - Return true if this is an analysis group, not a normal
77-
/// pass.
78-
bool isAnalysisGroup() const { return IsAnalysisGroup; }
7968
bool isAnalysis() const { return IsAnalysis; }
8069

8170
/// isCFGOnlyPass - return true if this pass only looks at the CFG for the
@@ -94,25 +83,10 @@ class PassInfo {
9483

9584
/// createPass() - Use this method to create an instance of this pass.
9685
Pass *createPass() const {
97-
assert((!isAnalysisGroup() || NormalCtor) &&
98-
"No default implementation found for analysis group!");
9986
assert(NormalCtor &&
10087
"Cannot call createPass on PassInfo without default ctor!");
10188
return NormalCtor();
10289
}
103-
104-
/// addInterfaceImplemented - This method is called when this pass is
105-
/// registered as a member of an analysis group with the RegisterAnalysisGroup
106-
/// template.
107-
void addInterfaceImplemented(const PassInfo *ItfPI) {
108-
ItfImpl.push_back(ItfPI);
109-
}
110-
111-
/// getInterfacesImplemented - Return a list of all of the analysis group
112-
/// interfaces implemented by this pass.
113-
const std::vector<const PassInfo*> &getInterfacesImplemented() const {
114-
return ItfImpl;
115-
}
11690
};
11791

11892
} // end namespace llvm

llvm/include/llvm/PassRegistry.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,6 @@ class PassRegistry {
6868
/// registry. Required in order to use the pass with a PassManager.
6969
void registerPass(const PassInfo &PI, bool ShouldFree = false);
7070

71-
/// registerAnalysisGroup - Register an analysis group (or a pass implementing
72-
// an analysis group) with the registry. Like registerPass, this is required
73-
// in order for a PassManager to be able to use this group/pass.
74-
void registerAnalysisGroup(const void *InterfaceID, const void *PassID,
75-
PassInfo &Registeree, bool isDefault,
76-
bool ShouldFree = false);
77-
7871
/// enumerateWith - Enumerate the registered passes, calling the provided
7972
/// PassRegistrationListener's passEnumerate() callback on each of them.
8073
void enumerateWith(PassRegistrationListener *L);

llvm/include/llvm/PassSupport.h

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ class Pass;
5353
static void *initialize##passName##PassOnce(PassRegistry &Registry) {
5454

5555
#define INITIALIZE_PASS_DEPENDENCY(depName) initialize##depName##Pass(Registry);
56-
#define INITIALIZE_AG_DEPENDENCY(depName) \
57-
initialize##depName##AnalysisGroup(Registry);
5856

5957
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) \
6058
PassInfo *PI = new PassInfo( \
@@ -117,95 +115,6 @@ template <typename passName> struct RegisterPass : public PassInfo {
117115
}
118116
};
119117

120-
/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_.
121-
/// Analysis groups are used to define an interface (which need not derive from
122-
/// Pass) that is required by passes to do their job. Analysis Groups differ
123-
/// from normal analyses because any available implementation of the group will
124-
/// be used if it is available.
125-
///
126-
/// If no analysis implementing the interface is available, a default
127-
/// implementation is created and added. A pass registers itself as the default
128-
/// implementation by specifying 'true' as the second template argument of this
129-
/// class.
130-
///
131-
/// In addition to registering itself as an analysis group member, a pass must
132-
/// register itself normally as well. Passes may be members of multiple groups
133-
/// and may still be "required" specifically by name.
134-
///
135-
/// The actual interface may also be registered as well (by not specifying the
136-
/// second template argument). The interface should be registered to associate
137-
/// a nice name with the interface.
138-
class RegisterAGBase : public PassInfo {
139-
public:
140-
RegisterAGBase(StringRef Name, const void *InterfaceID,
141-
const void *PassID = nullptr, bool isDefault = false);
142-
};
143-
144-
template <typename Interface, bool Default = false>
145-
struct RegisterAnalysisGroup : public RegisterAGBase {
146-
explicit RegisterAnalysisGroup(PassInfo &RPB)
147-
: RegisterAGBase(RPB.getPassName(), &Interface::ID, RPB.getTypeInfo(),
148-
Default) {}
149-
150-
explicit RegisterAnalysisGroup(const char *Name)
151-
: RegisterAGBase(Name, &Interface::ID) {}
152-
};
153-
154-
#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass) \
155-
static void *initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \
156-
initialize##defaultPass##Pass(Registry); \
157-
PassInfo *AI = new PassInfo(name, &agName::ID); \
158-
Registry.registerAnalysisGroup(&agName::ID, 0, *AI, false, true); \
159-
return AI; \
160-
} \
161-
static llvm::once_flag Initialize##agName##AnalysisGroupFlag; \
162-
void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \
163-
llvm::call_once(Initialize##agName##AnalysisGroupFlag, \
164-
initialize##agName##AnalysisGroupOnce, \
165-
std::ref(Registry)); \
166-
}
167-
168-
#define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def) \
169-
static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
170-
if (!def) \
171-
initialize##agName##AnalysisGroup(Registry); \
172-
PassInfo *PI = new PassInfo( \
173-
name, arg, &passName::ID, \
174-
PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
175-
Registry.registerPass(*PI, true); \
176-
\
177-
PassInfo *AI = new PassInfo(name, &agName::ID); \
178-
Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, \
179-
true); \
180-
return AI; \
181-
} \
182-
static llvm::once_flag Initialize##passName##PassFlag; \
183-
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
184-
llvm::call_once(Initialize##passName##PassFlag, \
185-
initialize##passName##PassOnce, std::ref(Registry)); \
186-
}
187-
188-
#define INITIALIZE_AG_PASS_BEGIN(passName, agName, arg, n, cfg, analysis, def) \
189-
static void *initialize##passName##PassOnce(PassRegistry &Registry) { \
190-
if (!def) \
191-
initialize##agName##AnalysisGroup(Registry);
192-
193-
#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def) \
194-
PassInfo *PI = new PassInfo( \
195-
n, arg, &passName::ID, \
196-
PassInfo::NormalCtor_t(callDefaultCtor<passName>), cfg, analysis); \
197-
Registry.registerPass(*PI, true); \
198-
\
199-
PassInfo *AI = new PassInfo(n, &agName::ID); \
200-
Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, true); \
201-
return AI; \
202-
} \
203-
static llvm::once_flag Initialize##passName##PassFlag; \
204-
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
205-
llvm::call_once(Initialize##passName##PassFlag, \
206-
initialize##passName##PassOnce, std::ref(Registry)); \
207-
}
208-
209118
//===---------------------------------------------------------------------------
210119
/// PassRegistrationListener class - This class is meant to be derived from by
211120
/// clients that are interested in which passes get registered and unregistered

llvm/lib/IR/LegacyPassManager.cpp

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -808,13 +808,6 @@ void PMTopLevelManager::addImmutablePass(ImmutablePass *P) {
808808
// doing lookups.
809809
AnalysisID AID = P->getPassID();
810810
ImmutablePassMap[AID] = P;
811-
812-
// Also add any interfaces implemented by the immutable pass to the map for
813-
// fast lookup.
814-
const PassInfo *PassInf = findAnalysisPassInfo(AID);
815-
assert(PassInf && "Expected all immutable passes to be initialized");
816-
for (const PassInfo *ImmPI : PassInf->getInterfacesImplemented())
817-
ImmutablePassMap[ImmPI->getTypeInfo()] = P;
818811
}
819812

820813
// Print passes managed by this top level manager.
@@ -844,8 +837,7 @@ void PMTopLevelManager::dumpArguments() const {
844837
for (ImmutablePass *P : ImmutablePasses)
845838
if (const PassInfo *PI = findAnalysisPassInfo(P->getPassID())) {
846839
assert(PI && "Expected all immutable passes to be initialized");
847-
if (!PI->isAnalysisGroup())
848-
dbgs() << " -" << PI->getPassArgument();
840+
dbgs() << " -" << PI->getPassArgument();
849841
}
850842
for (PMDataManager *PM : PassManagers)
851843
PM->dumpPassArguments();
@@ -878,15 +870,6 @@ void PMDataManager::recordAvailableAnalysis(Pass *P) {
878870
AnalysisID PI = P->getPassID();
879871

880872
AvailableAnalysis[PI] = P;
881-
882-
assert(!AvailableAnalysis.empty());
883-
884-
// This pass is the current implementation of all of the interfaces it
885-
// implements as well.
886-
const PassInfo *PInf = TPM->findAnalysisPassInfo(PI);
887-
if (!PInf) return;
888-
for (const PassInfo *PI : PInf->getInterfacesImplemented())
889-
AvailableAnalysis[PI->getTypeInfo()] = P;
890873
}
891874

892875
// Return true if P preserves high level analysis used by other
@@ -1004,20 +987,8 @@ void PMDataManager::freePass(Pass *P, StringRef Msg,
1004987
P->releaseMemory();
1005988
}
1006989

1007-
AnalysisID PI = P->getPassID();
1008-
if (const PassInfo *PInf = TPM->findAnalysisPassInfo(PI)) {
1009-
// Remove the pass itself (if it is not already removed).
1010-
AvailableAnalysis.erase(PI);
1011-
1012-
// Remove all interfaces this pass implements, for which it is also
1013-
// listed as the available implementation.
1014-
for (const PassInfo *PI : PInf->getInterfacesImplemented()) {
1015-
DenseMap<AnalysisID, Pass *>::iterator Pos =
1016-
AvailableAnalysis.find(PI->getTypeInfo());
1017-
if (Pos != AvailableAnalysis.end() && Pos->second == P)
1018-
AvailableAnalysis.erase(Pos);
1019-
}
1020-
}
990+
// Remove the pass itself (if it is not already removed).
991+
AvailableAnalysis.erase(P->getPassID());
1021992
}
1022993

1023994
/// Add pass P into the PassVector. Update
@@ -1173,11 +1144,8 @@ void PMDataManager::dumpPassArguments() const {
11731144
for (Pass *P : PassVector) {
11741145
if (PMDataManager *PMD = P->getAsPMDataManager())
11751146
PMD->dumpPassArguments();
1176-
else
1177-
if (const PassInfo *PI =
1178-
TPM->findAnalysisPassInfo(P->getPassID()))
1179-
if (!PI->isAnalysisGroup())
1180-
dbgs() << " -" << PI->getPassArgument();
1147+
else if (const PassInfo *PI = TPM->findAnalysisPassInfo(P->getPassID()))
1148+
dbgs() << " -" << PI->getPassArgument();
11811149
}
11821150
}
11831151

0 commit comments

Comments
 (0)