Skip to content

Commit 5404fe3

Browse files
committed
Revert "[LegacyPM] Remove pipeline extension mechanism"
This reverts commit 4ea6ffb. Breaks various backends.
1 parent c7ca01b commit 5404fe3

File tree

4 files changed

+212
-0
lines changed

4 files changed

+212
-0
lines changed

llvm/docs/WritingAnLLVMPass.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ without modifying it then the third argument is set to ``true``; if a pass is
185185
an analysis pass, for example dominator tree pass, then ``true`` is supplied as
186186
the fourth argument.
187187

188+
If we want to register the pass as a step of an existing pipeline, some extension
189+
points are provided, e.g. ``PassManagerBuilder::EP_EarlyAsPossible`` to apply our
190+
pass before any optimization, or ``PassManagerBuilder::EP_FullLinkTimeOptimizationLast``
191+
to apply it after Link Time Optimizations.
192+
193+
.. code-block:: c++
194+
195+
static llvm::RegisterStandardPasses Y(
196+
llvm::PassManagerBuilder::EP_EarlyAsPossible,
197+
[](const llvm::PassManagerBuilder &Builder,
198+
llvm::legacy::PassManagerBase &PM) { PM.add(new Hello()); });
199+
188200
As a whole, the ``.cpp`` file looks like:
189201

190202
.. code-block:: c++
@@ -216,6 +228,11 @@ As a whole, the ``.cpp`` file looks like:
216228
false /* Only looks at CFG */,
217229
false /* Analysis Pass */);
218230
231+
static RegisterStandardPasses Y(
232+
PassManagerBuilder::EP_EarlyAsPossible,
233+
[](const PassManagerBuilder &Builder,
234+
legacy::PassManagerBase &PM) { PM.add(new Hello()); });
235+
219236
Now that it's all together, compile the file with a simple "``gmake``" command
220237
from the top level of your build directory and you should get a new file
221238
"``lib/LLVMHello.so``". Note that everything in this file is

llvm/examples/Bye/Bye.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ static RegisterPass<LegacyBye> X("goodbye", "Good Bye World Pass",
4444
false /* Only looks at CFG */,
4545
false /* Analysis Pass */);
4646

47+
/* Legacy PM Registration */
48+
static llvm::RegisterStandardPasses RegisterBye(
49+
llvm::PassManagerBuilder::EP_VectorizerStart,
50+
[](const llvm::PassManagerBuilder &Builder,
51+
llvm::legacy::PassManagerBase &PM) { PM.add(new LegacyBye()); });
52+
53+
static llvm::RegisterStandardPasses RegisterByeLTO(
54+
llvm::PassManagerBuilder::EP_ModuleOptimizerEarly,
55+
[](const llvm::PassManagerBuilder &Builder,
56+
llvm::legacy::PassManagerBase &PM) { PM.add(new LegacyBye()); });
57+
4758
/* New PM Registration */
4859
llvm::PassPluginLibraryInfo getByePluginInfo() {
4960
return {LLVM_PLUGIN_API_VERSION, "Bye", LLVM_VERSION_STRING,

llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,68 @@ class PassManagerBuilder {
6363
ExtensionFn;
6464
typedef int GlobalExtensionID;
6565

66+
enum ExtensionPointTy {
67+
/// EP_EarlyAsPossible - This extension point allows adding passes before
68+
/// any other transformations, allowing them to see the code as it is coming
69+
/// out of the frontend.
70+
EP_EarlyAsPossible,
71+
72+
/// EP_ModuleOptimizerEarly - This extension point allows adding passes
73+
/// just before the main module-level optimization passes.
74+
EP_ModuleOptimizerEarly,
75+
76+
/// EP_LoopOptimizerEnd - This extension point allows adding loop passes to
77+
/// the end of the loop optimizer.
78+
EP_LoopOptimizerEnd,
79+
80+
/// EP_ScalarOptimizerLate - This extension point allows adding optimization
81+
/// passes after most of the main optimizations, but before the last
82+
/// cleanup-ish optimizations.
83+
EP_ScalarOptimizerLate,
84+
85+
/// EP_OptimizerLast -- This extension point allows adding passes that
86+
/// run after everything else.
87+
EP_OptimizerLast,
88+
89+
/// EP_VectorizerStart - This extension point allows adding optimization
90+
/// passes before the vectorizer and other highly target specific
91+
/// optimization passes are executed.
92+
EP_VectorizerStart,
93+
94+
/// EP_EnabledOnOptLevel0 - This extension point allows adding passes that
95+
/// should not be disabled by O0 optimization level. The passes will be
96+
/// inserted after the inlining pass.
97+
EP_EnabledOnOptLevel0,
98+
99+
/// EP_Peephole - This extension point allows adding passes that perform
100+
/// peephole optimizations similar to the instruction combiner. These passes
101+
/// will be inserted after each instance of the instruction combiner pass.
102+
EP_Peephole,
103+
104+
/// EP_LateLoopOptimizations - This extension point allows adding late loop
105+
/// canonicalization and simplification passes. This is the last point in
106+
/// the loop optimization pipeline before loop deletion. Each pass added
107+
/// here must be an instance of LoopPass.
108+
/// This is the place to add passes that can remove loops, such as target-
109+
/// specific loop idiom recognition.
110+
EP_LateLoopOptimizations,
111+
112+
/// EP_CGSCCOptimizerLate - This extension point allows adding CallGraphSCC
113+
/// passes at the end of the main CallGraphSCC passes and before any
114+
/// function simplification passes run by CGPassManager.
115+
EP_CGSCCOptimizerLate,
116+
117+
/// EP_FullLinkTimeOptimizationEarly - This extensions point allow adding
118+
/// passes that
119+
/// run at Link Time, before Full Link Time Optimization.
120+
EP_FullLinkTimeOptimizationEarly,
121+
122+
/// EP_FullLinkTimeOptimizationLast - This extensions point allow adding
123+
/// passes that
124+
/// run at Link Time, after Full Link Time Optimization.
125+
EP_FullLinkTimeOptimizationLast,
126+
};
127+
66128
/// The Optimization Level - Specify the basic optimization level.
67129
/// 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3
68130
unsigned OptLevel;
@@ -106,11 +168,32 @@ class PassManagerBuilder {
106168
unsigned LicmMssaOptCap;
107169
unsigned LicmMssaNoAccForPromotionCap;
108170

171+
private:
172+
/// ExtensionList - This is list of all of the extensions that are registered.
173+
std::vector<std::pair<ExtensionPointTy, ExtensionFn>> Extensions;
174+
109175
public:
110176
PassManagerBuilder();
111177
~PassManagerBuilder();
178+
/// Adds an extension that will be used by all PassManagerBuilder instances.
179+
/// This is intended to be used by plugins, to register a set of
180+
/// optimisations to run automatically.
181+
///
182+
/// \returns A global extension identifier that can be used to remove the
183+
/// extension.
184+
static GlobalExtensionID addGlobalExtension(ExtensionPointTy Ty,
185+
ExtensionFn Fn);
186+
/// Removes an extension that was previously added using addGlobalExtension.
187+
/// This is also intended to be used by plugins, to remove any extension that
188+
/// was previously registered before being unloaded.
189+
///
190+
/// \param ExtensionID Identifier of the extension to be removed.
191+
static void removeGlobalExtension(GlobalExtensionID ExtensionID);
192+
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn);
112193

113194
private:
195+
void addExtensionsToPM(ExtensionPointTy ETy,
196+
legacy::PassManagerBase &PM) const;
114197
void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const;
115198
void addFunctionSimplificationPasses(legacy::PassManagerBase &MPM);
116199
void addVectorPasses(legacy::PassManagerBase &PM, bool IsFullLTO);
@@ -125,6 +208,27 @@ class PassManagerBuilder {
125208
void populateModulePassManager(legacy::PassManagerBase &MPM);
126209
};
127210

211+
/// Registers a function for adding a standard set of passes. This should be
212+
/// used by optimizer plugins to allow all front ends to transparently use
213+
/// them. Create a static instance of this class in your plugin, providing a
214+
/// private function that the PassManagerBuilder can use to add your passes.
215+
class RegisterStandardPasses {
216+
PassManagerBuilder::GlobalExtensionID ExtensionID;
217+
218+
public:
219+
RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty,
220+
PassManagerBuilder::ExtensionFn Fn) {
221+
ExtensionID = PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
222+
}
223+
224+
~RegisterStandardPasses() {
225+
// If the collection holding the global extensions is destroyed after the
226+
// plugin is unloaded, the extension has to be removed here. Indeed, the
227+
// destructor of the ExtensionFn may reference code in the plugin.
228+
PassManagerBuilder::removeGlobalExtension(ExtensionID);
229+
}
230+
};
231+
128232
inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) {
129233
return reinterpret_cast<PassManagerBuilder*>(P);
130234
}

llvm/lib/Transforms/IPO/PassManagerBuilder.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,64 @@ PassManagerBuilder::~PassManagerBuilder() {
193193
delete Inliner;
194194
}
195195

196+
/// Set of global extensions, automatically added as part of the standard set.
197+
static ManagedStatic<
198+
SmallVector<std::tuple<PassManagerBuilder::ExtensionPointTy,
199+
PassManagerBuilder::ExtensionFn,
200+
PassManagerBuilder::GlobalExtensionID>,
201+
8>>
202+
GlobalExtensions;
203+
static PassManagerBuilder::GlobalExtensionID GlobalExtensionsCounter;
204+
205+
/// Check if GlobalExtensions is constructed and not empty.
206+
/// Since GlobalExtensions is a managed static, calling 'empty()' will trigger
207+
/// the construction of the object.
208+
static bool GlobalExtensionsNotEmpty() {
209+
return GlobalExtensions.isConstructed() && !GlobalExtensions->empty();
210+
}
211+
212+
PassManagerBuilder::GlobalExtensionID
213+
PassManagerBuilder::addGlobalExtension(PassManagerBuilder::ExtensionPointTy Ty,
214+
PassManagerBuilder::ExtensionFn Fn) {
215+
auto ExtensionID = GlobalExtensionsCounter++;
216+
GlobalExtensions->push_back(std::make_tuple(Ty, std::move(Fn), ExtensionID));
217+
return ExtensionID;
218+
}
219+
220+
void PassManagerBuilder::removeGlobalExtension(
221+
PassManagerBuilder::GlobalExtensionID ExtensionID) {
222+
// RegisterStandardPasses may try to call this function after GlobalExtensions
223+
// has already been destroyed; doing so should not generate an error.
224+
if (!GlobalExtensions.isConstructed())
225+
return;
226+
227+
auto GlobalExtension =
228+
llvm::find_if(*GlobalExtensions, [ExtensionID](const auto &elem) {
229+
return std::get<2>(elem) == ExtensionID;
230+
});
231+
assert(GlobalExtension != GlobalExtensions->end() &&
232+
"The extension ID to be removed should always be valid.");
233+
234+
GlobalExtensions->erase(GlobalExtension);
235+
}
236+
237+
void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
238+
Extensions.push_back(std::make_pair(Ty, std::move(Fn)));
239+
}
240+
241+
void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy,
242+
legacy::PassManagerBase &PM) const {
243+
if (GlobalExtensionsNotEmpty()) {
244+
for (auto &Ext : *GlobalExtensions) {
245+
if (std::get<0>(Ext) == ETy)
246+
std::get<1>(Ext)(*this, PM);
247+
}
248+
}
249+
for (const auto &[PT, Fn] : Extensions)
250+
if (PT == ETy)
251+
Fn(*this, PM);
252+
}
253+
196254
void PassManagerBuilder::addInitialAliasAnalysisPasses(
197255
legacy::PassManagerBase &PM) const {
198256
switch (UseCFLAA) {
@@ -219,6 +277,8 @@ void PassManagerBuilder::addInitialAliasAnalysisPasses(
219277

220278
void PassManagerBuilder::populateFunctionPassManager(
221279
legacy::FunctionPassManager &FPM) {
280+
addExtensionsToPM(EP_EarlyAsPossible, FPM);
281+
222282
// Add LibraryInfo if we have some.
223283
if (LibraryInfo)
224284
FPM.add(new TargetLibraryInfoWrapperPass(*LibraryInfo));
@@ -281,6 +341,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
281341
MPM.add(createInstructionCombiningPass());
282342
if (SizeLevel == 0 && !DisableLibCallsShrinkWrap)
283343
MPM.add(createLibCallsShrinkWrapPass());
344+
addExtensionsToPM(EP_Peephole, MPM);
284345

285346
// TODO: Investigate the cost/benefit of tail call elimination on debugging.
286347
if (OptLevel > 1)
@@ -330,6 +391,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
330391
}
331392
MPM.add(createLoopIdiomPass()); // Recognize idioms like memset.
332393
MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars
394+
addExtensionsToPM(EP_LateLoopOptimizations, MPM);
333395
MPM.add(createLoopDeletionPass()); // Delete dead loops
334396

335397
if (EnableLoopInterchange)
@@ -338,6 +400,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
338400
// Unroll small loops and perform peeling.
339401
MPM.add(createSimpleLoopUnrollPass(OptLevel, DisableUnrollLoops,
340402
ForgetAllSCEVInLoopUnroll));
403+
addExtensionsToPM(EP_LoopOptimizerEnd, MPM);
341404
// This ends the loop pass pipelines.
342405

343406
// Break up allocas that may now be splittable after loop unrolling.
@@ -361,6 +424,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
361424
// Run instcombine after redundancy elimination to exploit opportunities
362425
// opened up by them.
363426
MPM.add(createInstructionCombiningPass());
427+
addExtensionsToPM(EP_Peephole, MPM);
364428
if (OptLevel > 1) {
365429
if (EnableDFAJumpThreading && SizeLevel == 0)
366430
MPM.add(createDFAJumpThreadingPass());
@@ -378,6 +442,8 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
378442
/*AllowSpeculation=*/true));
379443
}
380444

445+
addExtensionsToPM(EP_ScalarOptimizerLate, MPM);
446+
381447
if (RerollLoops)
382448
MPM.add(createLoopRerollPass());
383449

@@ -386,6 +452,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
386452
SimplifyCFGOptions().hoistCommonInsts(true).sinkCommonInsts(true)));
387453
// Clean up after everything.
388454
MPM.add(createInstructionCombiningPass());
455+
addExtensionsToPM(EP_Peephole, MPM);
389456
}
390457

391458
/// FIXME: Should LTO cause any differences to this set of passes?
@@ -469,6 +536,7 @@ void PassManagerBuilder::addVectorPasses(legacy::PassManagerBase &PM,
469536
PM.add(createVectorCombinePass());
470537

471538
if (!IsFullLTO) {
539+
addExtensionsToPM(EP_Peephole, PM);
472540
PM.add(createInstructionCombiningPass());
473541

474542
if (EnableUnrollAndJam && !DisableUnrollLoops) {
@@ -527,6 +595,10 @@ void PassManagerBuilder::populateModulePassManager(
527595
// builds. The function merging pass is
528596
if (MergeFunctions)
529597
MPM.add(createMergeFunctionsPass());
598+
else if (GlobalExtensionsNotEmpty() || !Extensions.empty())
599+
MPM.add(createBarrierNoopPass());
600+
601+
addExtensionsToPM(EP_EnabledOnOptLevel0, MPM);
530602

531603
MPM.add(createAnnotationRemarksLegacyPass());
532604
return;
@@ -545,6 +617,8 @@ void PassManagerBuilder::populateModulePassManager(
545617
if (AttributorRun & AttributorRunOption::MODULE)
546618
MPM.add(createAttributorLegacyPass());
547619

620+
addExtensionsToPM(EP_ModuleOptimizerEarly, MPM);
621+
548622
if (OptLevel > 2)
549623
MPM.add(createCallSiteSplittingPass());
550624

@@ -562,6 +636,7 @@ void PassManagerBuilder::populateModulePassManager(
562636
MPM.add(createDeadArgEliminationPass()); // Dead argument elimination
563637

564638
MPM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
639+
addExtensionsToPM(EP_Peephole, MPM);
565640
MPM.add(
566641
createCFGSimplificationPass(SimplifyCFGOptions().convertSwitchRangeToICmp(
567642
true))); // Clean up after IPCP & DAE
@@ -590,6 +665,7 @@ void PassManagerBuilder::populateModulePassManager(
590665

591666
MPM.add(createPostOrderFunctionAttrsLegacyPass());
592667

668+
addExtensionsToPM(EP_CGSCCOptimizerLate, MPM);
593669
addFunctionSimplificationPasses(MPM);
594670

595671
// FIXME: This is a HACK! The inliner pass above implicitly creates a CGSCC
@@ -664,6 +740,8 @@ void PassManagerBuilder::populateModulePassManager(
664740
MPM.add(createEarlyCSEPass(false));
665741
}
666742

743+
addExtensionsToPM(EP_VectorizerStart, MPM);
744+
667745
// Re-rotate loops in all our loop nests. These may have fallout out of
668746
// rotated form due to GVN or other transformations, and the vectorizer relies
669747
// on the rotated form. Disable header duplication at -Oz.
@@ -716,6 +794,8 @@ void PassManagerBuilder::populateModulePassManager(
716794
MPM.add(createCFGSimplificationPass(
717795
SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
718796

797+
addExtensionsToPM(EP_OptimizerLast, MPM);
798+
719799
MPM.add(createAnnotationRemarksLegacyPass());
720800
}
721801

0 commit comments

Comments
 (0)