From f5be7bdc909dae98fab6530c6ab378d6d2618443 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 21 May 2011 23:50:37 +0000 Subject: [PATCH] add an extension point mechanism that allow plugins to add stuff to the pass manager. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131814 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/PassManagerBuilder.h | 123 +++++++++++++++------- 1 file changed, 83 insertions(+), 40 deletions(-) diff --git a/include/llvm/Support/PassManagerBuilder.h b/include/llvm/Support/PassManagerBuilder.h index c684f096111..70ffddb1c60 100644 --- a/include/llvm/Support/PassManagerBuilder.h +++ b/include/llvm/Support/PassManagerBuilder.h @@ -37,53 +37,92 @@ namespace llvm { /// Builder.populateFunctionPassManager(FPM); /// Builder.populateModulePassManager(MPM); /// +/// In addition to setting up the basic passes, PassManagerBuilder allows +/// frontends to vend a plugin API, where plugins are allowed to add extensions +/// to the default pass manager. They do this by specifying where in the pass +/// pipeline they want to be added, along with a callback function that adds +/// the pass(es). For example, a plugin that wanted to add a loop optimization +/// could do something like this: +/// +/// static void addMyLoopPass(const PMBuilder &Builder, PassManagerBase &PM) { +/// if (Builder.getOptLevel() > 2 && Builder.getOptSizeLevel() == 0) +/// PM.add(createMyAwesomePass()); +/// } +/// ... +/// Builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, +/// addMyLoopPass); +/// ... class PassManagerBuilder { - unsigned OptLevel; // 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3 - unsigned SizeLevel; // 0 = none, 1 = -Os, 2 = -Oz - TargetLibraryInfo *TLI; - Pass *InlinerPass; +public: + + /// Extensions are passed the builder itself (so they can see how it is + /// configured) as well as the pass manager to add stuff to. + typedef void (*ExtensionFn)(const PassManagerBuilder &Builder, + PassManagerBase &PM); + enum ExtensionPointTy { + /// EP_EarlyAsPossible - This extension point allows adding passes before + /// any other transformations, allowing them to see the code as it is coming + /// out of the frontend. + EP_EarlyAsPossible, + + /// EP_LoopOptimizerEnd - This extension point allows adding loop passes to + /// the end of the loop optimizer. + EP_LoopOptimizerEnd + }; + + /// The Optimization Level - Specify the basic optimization level. + /// 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3 + unsigned OptLevel; + + /// SizeLevel - How much we're optimizing for size. + /// 0 = none, 1 = -Os, 2 = -Oz + unsigned SizeLevel; + + /// LibraryInfo - Specifies information about the runtime library for the + /// optimizer. If this is non-null, it is added to both the function and + /// per-module pass pipeline. + TargetLibraryInfo *LibraryInfo; + + /// Inliner - Specifies the inliner to use. If this is non-null, it is + /// added to the per-module passes. + Pass *Inliner; bool DisableSimplifyLibCalls; bool DisableUnitAtATime; bool DisableUnrollLoops; + +private: + /// ExtensionList - This is list of all of the extensions that are registered. + std::vector > Extensions; + public: PassManagerBuilder() { OptLevel = 2; SizeLevel = 0; - TLI = 0; - InlinerPass = 0; + LibraryInfo = 0; + Inliner = 0; DisableSimplifyLibCalls = false; DisableUnitAtATime = false; DisableUnrollLoops = false; } ~PassManagerBuilder() { - delete TLI; - delete InlinerPass; + delete LibraryInfo; + delete Inliner; } - /// setOptimizationLevel - Specify the basic optimization level -O0 ... -O3. - void setOptimizationLevel(unsigned L) { OptLevel = L; } - - /// setSizeLevel - Specify the size optimization level: none, -Os, -Oz. - void setSizeLevel(unsigned L) { SizeLevel = L; } - - /// setLibraryInfo - Set information about the runtime library for the - /// optimizer. If this is specified, it is added to both the function and - /// per-module pass pipeline. - void setLibraryInfo(TargetLibraryInfo *LI) { TLI = LI; } - - /// setInliner - Specify the inliner to use. If this is specified, it is - /// added to the per-module passes. - void setInliner(Pass *P) { InlinerPass = P; } - - - void disableSimplifyLibCalls() { DisableSimplifyLibCalls = true; } - void disableUnitAtATime() { DisableUnitAtATime = true; } - void disableUnrollLoops() { DisableUnrollLoops = true; } + void addExtension(ExtensionPointTy Ty, ExtensionFn Fn) { + Extensions.push_back(std::make_pair(Ty, Fn)); + } private: - void addInitialAliasAnalysisPasses(PassManagerBase &PM) { + void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const { + for (unsigned i = 0, e = Extensions.size(); i != e; ++i) + if (Extensions[i].first == ETy) + Extensions[i].second(*this, PM); + } + + void addInitialAliasAnalysisPasses(PassManagerBase &PM) const { // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. @@ -96,11 +135,13 @@ public: /// which is expected to be run on each function immediately as it is /// generated. The idea is to reduce the size of the IR in memory. void populateFunctionPassManager(FunctionPassManager &FPM) { - if (OptLevel == 0) return; - - // Add TLI if we have some. - if (TLI) FPM.add(new TargetLibraryInfo(*TLI)); + addExtensionsToPM(EP_EarlyAsPossible, FPM); + // Add LibraryInfo if we have some. + if (LibraryInfo) FPM.add(new TargetLibraryInfo(*LibraryInfo)); + + if (OptLevel == 0) return; + addInitialAliasAnalysisPasses(FPM); FPM.add(createCFGSimplificationPass()); @@ -112,15 +153,15 @@ public: void populateModulePassManager(PassManagerBase &MPM) { // If all optimizations are disabled, just run the always-inline pass. if (OptLevel == 0) { - if (InlinerPass) { - MPM.add(InlinerPass); - InlinerPass = 0; + if (Inliner) { + MPM.add(Inliner); + Inliner = 0; } return; } - // Add TLI if we have some. - if (TLI) MPM.add(new TargetLibraryInfo(*TLI)); + // Add LibraryInfo if we have some. + if (LibraryInfo) MPM.add(new TargetLibraryInfo(*LibraryInfo)); addInitialAliasAnalysisPasses(MPM); @@ -137,9 +178,9 @@ public: // Start of CallGraph SCC passes. if (!DisableUnitAtATime) MPM.add(createPruneEHPass()); // Remove dead EH info - if (InlinerPass) { - MPM.add(InlinerPass); - InlinerPass = 0; + if (Inliner) { + MPM.add(Inliner); + Inliner = 0; } if (!DisableUnitAtATime) MPM.add(createFunctionAttrsPass()); // Set readonly/readnone attrs @@ -169,6 +210,8 @@ public: MPM.add(createLoopDeletionPass()); // Delete dead loops if (!DisableUnrollLoops) MPM.add(createLoopUnrollPass()); // Unroll small loops + addExtensionsToPM(EP_LoopOptimizerEnd, MPM); + if (OptLevel > 1) MPM.add(createGVNPass()); // Remove redundancies MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset -- 2.34.1