[llvm] r307532 - [PM] Enable registration of out-of-tree passes with PassBuilder
Galina Kistanova via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 11 19:37:31 PDT 2017
It sends emails of the fist build failure and all other errors became
difficult to catch. It's a limitation.
Thanks
Galina
On Tue, Jul 11, 2017 at 4:04 PM, Philip Pfaffe <philip.pfaffe at gmail.com>
wrote:
> Hi Galina,
>
> There is one additional thing I'm wondering about. I fixed this commit
> in r307534 first. The Darwin lld bot remained red because there was an
> another error in it. But I didn't get an email about that second error. Is
> that intentional or a limitation of Buildbot? It would be nice to get
> separate emails for different errors, because it's difficult to filter this
> out from all the build fail noise.
>
> Cheers,
> Philip
>
>
> On Jul 11, 2017 02:04, "Galina Kistanova" <gkistanova at gmail.com> wrote:
>
> Hello Philip,
>
> Looks like this commit broke one of our builders:
> http://lab.llvm.org:8011/builders/lld-x86_64-darwin13/builds/10240
>
> Please have a look?
>
> Thanks
>
> Galina
>
> On Mon, Jul 10, 2017 at 3:57 AM, Philip Pfaffe via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: pfaffe
>> Date: Mon Jul 10 03:57:55 2017
>> New Revision: 307532
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=307532&view=rev
>> Log:
>> [PM] Enable registration of out-of-tree passes with PassBuilder
>>
>> Summary:
>> This patch adds a callback registration API to the PassBuilder,
>> enabling registering out-of-tree passes with it.
>>
>> Through the Callback API, callers may register callbacks with the
>> various stages at which passes are added into pass managers, including
>> parsing of a pass pipeline as well as at extension points within the
>> default -O pipelines.
>>
>> Registering utilities like `require<>` and `invalidate<>` needs to be
>> handled manually by the caller, but a helper is provided.
>>
>> Additionally, adding passes at pipeline extension points is exposed
>> through the opt tool. This patch adds a `-passes-ep-X` commandline
>> option for every extension point X, which opt parses into pipelines
>> inserted into that extension point.
>>
>> Reviewers: chandlerc
>>
>> Reviewed By: chandlerc
>>
>> Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
>>
>> Differential Revision: https://reviews.llvm.org/D33464
>>
>> Added:
>> llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
>> Modified:
>> llvm/trunk/include/llvm/Passes/PassBuilder.h
>> llvm/trunk/lib/Passes/PassBuilder.cpp
>> llvm/trunk/test/Other/new-pm-defaults.ll
>> llvm/trunk/test/Other/new-pm-lto-defaults.ll
>> llvm/trunk/tools/opt/NewPMDriver.cpp
>> llvm/trunk/unittests/IR/CMakeLists.txt
>>
>> Modified: llvm/trunk/include/llvm/Passes/PassBuilder.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/
>> Passes/PassBuilder.h?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/include/llvm/Passes/PassBuilder.h (original)
>> +++ llvm/trunk/include/llvm/Passes/PassBuilder.h Mon Jul 10 03:57:55 2017
>> @@ -46,6 +46,19 @@ class PassBuilder {
>> Optional<PGOOptions> PGOOpt;
>>
>> public:
>> + /// \brief A struct to capture parsed pass pipeline names.
>> + ///
>> + /// A pipeline is defined as a series of names, each of which may in
>> itself
>> + /// recursively contain a nested pipeline. A name is either the name
>> of a pass
>> + /// (e.g. "instcombine") or the name of a pipeline type (e.g.
>> "cgscc"). If the
>> + /// name is the name of a pass, the InnerPipeline is empty, since
>> passes
>> + /// cannot contain inner pipelines. See parsePassPipeline() for a more
>> + /// detailed description of the textual pipeline format.
>> + struct PipelineElement {
>> + StringRef Name;
>> + std::vector<PipelineElement> InnerPipeline;
>> + };
>> +
>> /// \brief LLVM-provided high-level optimization levels.
>> ///
>> /// This enumerates the LLVM-provided high-level optimization levels.
>> Each
>> @@ -312,7 +325,8 @@ public:
>> /// registered.
>> AAManager buildDefaultAAPipeline();
>>
>> - /// \brief Parse a textual pass pipeline description into a \c
>> ModulePassManager.
>> + /// \brief Parse a textual pass pipeline description into a \c
>> + /// ModulePassManager.
>> ///
>> /// The format of the textual pass pipeline description looks
>> something like:
>> ///
>> @@ -322,8 +336,8 @@ public:
>> /// are comma separated. As a special shortcut, if the very first pass
>> is not
>> /// a module pass (as a module pass manager is), this will
>> automatically form
>> /// the shortest stack of pass managers that allow inserting that
>> first pass.
>> - /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and
>> loop passes
>> - /// 'lpassN', all of these are valid:
>> + /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and
>> loop
>> + /// passes 'lpassN', all of these are valid:
>> ///
>> /// fpass1,fpass2,fpass3
>> /// cgpass1,cgpass2,cgpass3
>> @@ -336,13 +350,28 @@ public:
>> /// module(function(loop(lpass1,lpass2,lpass3)))
>> ///
>> /// This shortcut is especially useful for debugging and testing small
>> pass
>> - /// combinations. Note that these shortcuts don't introduce any other
>> magic. If
>> - /// the sequence of passes aren't all the exact same kind of pass, it
>> will be
>> - /// an error. You cannot mix different levels implicitly, you must
>> explicitly
>> - /// form a pass manager in which to nest passes.
>> + /// combinations. Note that these shortcuts don't introduce any other
>> magic.
>> + /// If the sequence of passes aren't all the exact same kind of pass,
>> it will
>> + /// be an error. You cannot mix different levels implicitly, you must
>> + /// explicitly form a pass manager in which to nest passes.
>> bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
>> bool VerifyEachPass = true, bool DebugLogging =
>> false);
>>
>> + /// {{@ Parse a textual pass pipeline description into a specific
>> PassManager
>> + ///
>> + /// Automatic deduction of an appropriate pass manager stack is not
>> supported.
>> + /// For example, to insert a loop pass 'lpass' into a
>> FunctinoPassManager,
>> + /// this is the valid pipeline text:
>> + ///
>> + /// function(lpass)
>> + bool parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText,
>> + bool VerifyEachPass = true, bool DebugLogging =
>> false);
>> + bool parsePassPipeline(FunctionPassManager &FPM, StringRef
>> PipelineText,
>> + bool VerifyEachPass = true, bool DebugLogging =
>> false);
>> + bool parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText,
>> + bool VerifyEachPass = true, bool DebugLogging =
>> false);
>> + /// @}}
>> +
>> /// Parse a textual alias analysis pipeline into the provided AA
>> manager.
>> ///
>> /// The format of the textual AA pipeline is a comma separated list of
>> AA
>> @@ -360,13 +389,139 @@ public:
>> /// returns false.
>> bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
>>
>> -private:
>> - /// A struct to capture parsed pass pipeline names.
>> - struct PipelineElement {
>> - StringRef Name;
>> - std::vector<PipelineElement> InnerPipeline;
>> - };
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding passes that perform peephole
>> + /// optimizations similar to the instruction combiner. These passes
>> will be
>> + /// inserted after each instance of the instruction combiner pass.
>> + void registerPeepholeEPCallback(
>> + const std::function<void(FunctionPassManager &,
>> OptimizationLevel)> &C) {
>> + PeepholeEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding late loop canonicalization and
>> + /// simplification passes. This is the last point in the loop
>> optimization
>> + /// pipeline before loop deletion. Each pass added
>> + /// here must be an instance of LoopPass.
>> + /// This is the place to add passes that can remove loops, such as
>> target-
>> + /// specific loop idiom recognition.
>> + void registerLateLoopOptimizationsEPCallback(
>> + const std::function<void(LoopPassManager &, OptimizationLevel)>
>> &C) {
>> + LateLoopOptimizationsEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding loop passes to the end of the
>> loop
>> + /// optimizer.
>> + void registerLoopOptimizerEndEPCallback(
>> + const std::function<void(LoopPassManager &, OptimizationLevel)>
>> &C) {
>> + LoopOptimizerEndEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding optimization passes after most
>> of the
>> + /// main optimizations, but before the last cleanup-ish optimizations.
>> + void registerScalarOptimizerLateEPCallback(
>> + const std::function<void(FunctionPassManager &,
>> OptimizationLevel)> &C) {
>> + ScalarOptimizerLateEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding CallGraphSCC passes at the end
>> of the
>> + /// main CallGraphSCC passes and before any function simplification
>> passes run
>> + /// by CGPassManager.
>> + void registerCGSCCOptimizerLateEPCallback(
>> + const std::function<void(CGSCCPassManager &, OptimizationLevel)>
>> &C) {
>> + CGSCCOptimizerLateEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for a default optimizer pipeline
>> extension
>> + /// point
>> + ///
>> + /// This extension point allows adding optimization passes before the
>> + /// vectorizer and other highly target specific optimization passes are
>> + /// executed.
>> + void registerVectorizerStartEPCallback(
>> + const std::function<void(FunctionPassManager &,
>> OptimizationLevel)> &C) {
>> + VectorizerStartEPCallbacks.push_back(C);
>> + }
>> +
>> + /// \brief Register a callback for parsing an AliasAnalysis Name to
>> populate
>> + /// the given AAManager \p AA
>> + void registerParseAACallback(
>> + const std::function<bool(StringRef Name, AAManager &AA)> &C) {
>> + AAParsingCallbacks.push_back(C);
>> + }
>> +
>> + /// {{@ Register callbacks for analysis registration with this
>> PassBuilder
>> + /// instance.
>> + /// Callees register their analyses with the given AnalysisManager
>> objects.
>> + void registerAnalysisRegistrationCallback(
>> + const std::function<void(CGSCCAnalysisManager &)> &C) {
>> + CGSCCAnalysisRegistrationCallbacks.push_back(C);
>> + }
>> + void registerAnalysisRegistrationCallback(
>> + const std::function<void(FunctionAnalysisManager &)> &C) {
>> + FunctionAnalysisRegistrationCallbacks.push_back(C);
>> + }
>> + void registerAnalysisRegistrationCallback(
>> + const std::function<void(LoopAnalysisManager &)> &C) {
>> + LoopAnalysisRegistrationCallbacks.push_back(C);
>> + }
>> + void registerAnalysisRegistrationCallback(
>> + const std::function<void(ModuleAnalysisManager &)> &C) {
>> + ModuleAnalysisRegistrationCallbacks.push_back(C);
>> + }
>> + /// @}}
>> +
>> + /// {{@ Register pipeline parsing callbacks with this pass builder
>> instance.
>> + /// Using these callbacks, callers can parse both a single pass name,
>> as well
>> + /// as entire sub-pipelines, and populate the PassManager instance
>> + /// accordingly.
>> + void registerPipelineParsingCallback(
>> + const std::function<bool(StringRef Name, CGSCCPassManager &,
>> + ArrayRef<PipelineElement>)> &C) {
>> + CGSCCPipelineParsingCallbacks.push_back(C);
>> + }
>> + void registerPipelineParsingCallback(
>> + const std::function<bool(StringRef Name, FunctionPassManager &,
>> + ArrayRef<PipelineElement>)> &C) {
>> + FunctionPipelineParsingCallbacks.push_back(C);
>> + }
>> + void registerPipelineParsingCallback(
>> + const std::function<bool(StringRef Name, LoopPassManager &,
>> + ArrayRef<PipelineElement>)> &C) {
>> + LoopPipelineParsingCallbacks.push_back(C);
>> + }
>> + void registerPipelineParsingCallback(
>> + const std::function<bool(StringRef Name, ModulePassManager &,
>> + ArrayRef<PipelineElement>)> &C) {
>> + ModulePipelineParsingCallbacks.push_back(C);
>> + }
>> + /// @}}
>> +
>> + /// \brief Register a callback for a top-level pipeline entry.
>> + ///
>> + /// If the PassManager type is not given at the top level of the
>> pipeline
>> + /// text, this Callback should be used to determine the appropriate
>> stack of
>> + /// PassManagers and populate the passed ModulePassManager.
>> + void registerParseTopLevelPipelineCallback(
>> + const std::function<bool(ModulePassManager &,
>> ArrayRef<PipelineElement>,
>> + bool VerifyEachPass, bool DebugLogging)>
>> &C) {
>> + TopLevelPipelineParsingCallbacks.push_back(C);
>> + }
>>
>> +private:
>> static Optional<std::vector<PipelineElement>>
>> parsePipelineText(StringRef Text);
>>
>> @@ -392,7 +547,106 @@ private:
>> bool parseModulePassPipeline(ModulePassManager &MPM,
>> ArrayRef<PipelineElement> Pipeline,
>> bool VerifyEachPass, bool DebugLogging);
>> +
>> + void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
>> + OptimizationLevel Level, bool RunProfileGen,
>> + std::string ProfileGenFile,
>> + std::string ProfileUseFile);
>> +
>> + void invokePeepholeEPCallbacks(FunctionPassManager &,
>> OptimizationLevel);
>> +
>> + // Extension Point callbacks
>> + SmallVector<std::function<void(FunctionPassManager &,
>> OptimizationLevel)>, 2>
>> + PeepholeEPCallbacks;
>> + SmallVector<std::function<void(LoopPassManager &,
>> OptimizationLevel)>, 2>
>> + LateLoopOptimizationsEPCallbacks;
>> + SmallVector<std::function<void(LoopPassManager &,
>> OptimizationLevel)>, 2>
>> + LoopOptimizerEndEPCallbacks;
>> + SmallVector<std::function<void(FunctionPassManager &,
>> OptimizationLevel)>, 2>
>> + ScalarOptimizerLateEPCallbacks;
>> + SmallVector<std::function<void(CGSCCPassManager &,
>> OptimizationLevel)>, 2>
>> + CGSCCOptimizerLateEPCallbacks;
>> + SmallVector<std::function<void(FunctionPassManager &,
>> OptimizationLevel)>, 2>
>> + VectorizerStartEPCallbacks;
>> + // Module callbacks
>> + SmallVector<std::function<void(ModuleAnalysisManager &)>, 2>
>> + ModuleAnalysisRegistrationCallbacks;
>> + SmallVector<std::function<bool(StringRef, ModulePassManager &,
>> + ArrayRef<PipelineElement>)>,
>> + 2>
>> + ModulePipelineParsingCallbacks;
>> + SmallVector<std::function<bool(ModulePassManager &,
>> ArrayRef<PipelineElement>,
>> + bool VerifyEachPass, bool
>> DebugLogging)>,
>> + 2>
>> + TopLevelPipelineParsingCallbacks;
>> + // CGSCC callbacks
>> + SmallVector<std::function<void(CGSCCAnalysisManager &)>, 2>
>> + CGSCCAnalysisRegistrationCallbacks;
>> + SmallVector<std::function<bool(StringRef, CGSCCPassManager &,
>> + ArrayRef<PipelineElement>)>,
>> + 2>
>> + CGSCCPipelineParsingCallbacks;
>> + // Function callbacks
>> + SmallVector<std::function<void(FunctionAnalysisManager &)>, 2>
>> + FunctionAnalysisRegistrationCallbacks;
>> + SmallVector<std::function<bool(StringRef, FunctionPassManager &,
>> + ArrayRef<PipelineElement>)>,
>> + 2>
>> + FunctionPipelineParsingCallbacks;
>> + // Loop callbacks
>> + SmallVector<std::function<void(LoopAnalysisManager &)>, 2>
>> + LoopAnalysisRegistrationCallbacks;
>> + SmallVector<std::function<bool(StringRef, LoopPassManager &,
>> + ArrayRef<PipelineElement>)>,
>> + 2>
>> + LoopPipelineParsingCallbacks;
>> + // AA callbacks
>> + SmallVector<std::function<bool(StringRef Name, AAManager &AA)>, 2>
>> + AAParsingCallbacks;
>> };
>> +
>> +/// This utility template takes care of adding require<> and invalidate<>
>> +/// passes for an analysis to a given \c PassManager. It is intended to
>> be used
>> +/// during parsing of a pass pipeline when parsing a single PipelineName.
>> +/// When registering a new function analysis FancyAnalysis with the pass
>> +/// pipeline name "fancy-analysis", a matching ParsePipelineCallback
>> could look
>> +/// like this:
>> +///
>> +/// static bool parseFunctionPipeline(StringRef Name,
>> FunctionPassManager &FPM,
>> +/// ArrayRef<PipelineElement> P) {
>> +/// if (parseAnalysisUtilityPasses<FancyAnalysis>("fancy-analysis",
>> Name,
>> +/// FPM))
>> +/// return true;
>> +/// return false;
>> +/// }
>> +template <typename AnalysisT, typename IRUnitT, typename
>> AnalysisManagerT,
>> + typename... ExtraArgTs>
>> +bool parseAnalysisUtilityPasses(
>> + StringRef AnalysisName, StringRef PipelineName,
>> + PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...> &PM) {
>> + if (!PipelineName.endswith(">"))
>> + return false;
>> + // See if this is an invalidate<> pass name
>> + if (PipelineName.startswith("invalidate<")) {
>> + PipelineName = PipelineName.substr(11, PipelineName.size() - 12);
>> + if (PipelineName != AnalysisName)
>> + return false;
>> + PM.addPass(InvalidateAnalysisPass<AnalysisT>());
>> + return true;
>> + }
>> +
>> + // See if this is a require<> pass name
>> + if (PipelineName.startswith("require<")) {
>> + PipelineName = PipelineName.substr(8, PipelineName.size() - 9);
>> + if (PipelineName != AnalysisName)
>> + return false;
>> + PM.addPass(RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT,
>> + ExtraArgTs...>());
>> + return true;
>> + }
>> +
>> + return false;
>> +}
>> }
>>
>> #endif
>>
>> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/Pa
>> ssBuilder.cpp?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
>> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Mon Jul 10 03:57:55 2017
>> @@ -281,28 +281,46 @@ AnalysisKey NoOpLoopAnalysis::Key;
>>
>> } // End anonymous namespace.
>>
>> +void PassBuilder::invokePeepholeEPCallbacks(
>> + FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
>> + for (auto &C : PeepholeEPCallbacks)
>> + C(FPM, Level);
>> +}
>> +
>> void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
>> #define MODULE_ANALYSIS(NAME, CREATE_PASS)
>> \
>> MAM.registerPass([&] { return CREATE_PASS; });
>> #include "PassRegistry.def"
>> +
>> + for (auto &C : ModuleAnalysisRegistrationCallbacks)
>> + C(MAM);
>> }
>>
>> void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
>> #define CGSCC_ANALYSIS(NAME, CREATE_PASS)
>> \
>> CGAM.registerPass([&] { return CREATE_PASS; });
>> #include "PassRegistry.def"
>> +
>> + for (auto &C : CGSCCAnalysisRegistrationCallbacks)
>> + C(CGAM);
>> }
>>
>> void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager
>> &FAM) {
>> #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)
>> \
>> FAM.registerPass([&] { return CREATE_PASS; });
>> #include "PassRegistry.def"
>> +
>> + for (auto &C : FunctionAnalysisRegistrationCallbacks)
>> + C(FAM);
>> }
>>
>> void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
>> #define LOOP_ANALYSIS(NAME, CREATE_PASS)
>> \
>> LAM.registerPass([&] { return CREATE_PASS; });
>> #include "PassRegistry.def"
>> +
>> + for (auto &C : LoopAnalysisRegistrationCallbacks)
>> + C(LAM);
>> }
>>
>> FunctionPassManager
>> @@ -341,6 +359,8 @@ PassBuilder::buildFunctionSimplification
>> if (!isOptimizingForSize(Level))
>> FPM.addPass(LibCallsShrinkWrapPass());
>>
>> + invokePeepholeEPCallbacks(FPM, Level);
>> +
>> FPM.addPass(TailCallElimPass());
>> FPM.addPass(SimplifyCFGPass());
>>
>> @@ -364,6 +384,10 @@ PassBuilder::buildFunctionSimplification
>> LPM1.addPass(SimpleLoopUnswitchPass());
>> LPM2.addPass(IndVarSimplifyPass());
>> LPM2.addPass(LoopIdiomRecognizePass());
>> +
>> + for (auto &C : LateLoopOptimizationsEPCallbacks)
>> + C(LPM2, Level);
>> +
>> LPM2.addPass(LoopDeletionPass());
>> // Do not enable unrolling in PrepareForThinLTO phase during sample PGO
>> // because it changes IR to makes profile annotation in back compile
>> @@ -371,6 +395,9 @@ PassBuilder::buildFunctionSimplification
>> if (!PrepareForThinLTO || !PGOOpt || PGOOpt->SampleProfileFile.empt
>> y())
>> LPM2.addPass(LoopUnrollPass::createFull(Level));
>>
>> + for (auto &C : LoopOptimizerEndEPCallbacks)
>> + C(LPM2, Level);
>> +
>> // We provide the opt remark emitter pass for LICM to use. We only
>> need to do
>> // this once as it is immutable.
>> FPM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis,
>> Function>());
>> @@ -405,6 +432,7 @@ PassBuilder::buildFunctionSimplification
>> // Run instcombine after redundancy and dead bit elimination to exploit
>> // opportunities opened up by them.
>> FPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(FPM, Level);
>>
>> // Re-consider control flow based optimizations after redundancy
>> elimination,
>> // redo DCE, etc.
>> @@ -413,19 +441,24 @@ PassBuilder::buildFunctionSimplification
>> FPM.addPass(DSEPass());
>> FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass()));
>>
>> + for (auto &C : ScalarOptimizerLateEPCallbacks)
>> + C(FPM, Level);
>> +
>> // Finally, do an expensive DCE pass to catch all the dead code
>> exposed by
>> // the simplifications and basic cleanup after all the simplifications.
>> FPM.addPass(ADCEPass());
>> FPM.addPass(SimplifyCFGPass());
>> FPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(FPM, Level);
>>
>> return FPM;
>> }
>>
>> -static void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
>> - PassBuilder::OptimizationLevel Level,
>> - bool RunProfileGen, std::string
>> ProfileGenFile,
>> - std::string ProfileUseFile) {
>> +void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool
>> DebugLogging,
>> + PassBuilder::OptimizationLevel Level,
>> + bool RunProfileGen,
>> + std::string ProfileGenFile,
>> + std::string ProfileUseFile) {
>> // Generally running simplification passes and the inliner with an high
>> // threshold results in smaller executables, but there may be cases
>> where
>> // the size grows, so let's be conservative here and skip this
>> simplification
>> @@ -450,9 +483,8 @@ static void addPGOInstrPasses(ModulePass
>> FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies.
>> FPM.addPass(SimplifyCFGPass()); // Merge & remove basic blocks.
>> FPM.addPass(InstCombinePass()); // Combine silly sequences.
>> + invokePeepholeEPCallbacks(FPM, Level);
>>
>> - // FIXME: Here the old pass manager inserts peephole extensions.
>> - // Add them when they're supported.
>> CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::mo
>> ve(FPM)));
>>
>> MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::mo
>> ve(CGPipeline)));
>> @@ -533,6 +565,8 @@ PassBuilder::buildModuleSimplificationPi
>> // optimizations.
>> FunctionPassManager GlobalCleanupPM(DebugLogging);
>> GlobalCleanupPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(GlobalCleanupPM, Level);
>> +
>> GlobalCleanupPM.addPass(SimplifyCFGPass());
>> MPM.addPass(createModuleToFunctionPassAdaptor(std::move(Glo
>> balCleanupPM)));
>>
>> @@ -597,6 +631,9 @@ PassBuilder::buildModuleSimplificationPi
>> buildFunctionSimplificationPipeline(Level, DebugLogging,
>> PrepareForThinLTO)));
>>
>> + for (auto &C : CGSCCOptimizerLateEPCallbacks)
>> + C(MainCGPipeline, Level);
>> +
>> // We wrap the CGSCC pipeline in a devirtualization repeater. This
>> will try
>> // to detect when we devirtualize indirect calls and iterate the SCC
>> passes
>> // in that case to try and catch knock-on inlining or function attrs
>> @@ -655,6 +692,9 @@ PassBuilder::buildModuleOptimizationPipe
>> // rather than on each loop in an inside-out manner, and so they are
>> actually
>> // function passes.
>>
>> + for (auto &C : VectorizerStartEPCallbacks)
>> + C(OptimizePM, Level);
>> +
>> // First rotate loops that may have been un-rotated by prior passes.
>> OptimizePM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
>>
>> @@ -883,8 +923,11 @@ ModulePassManager PassBuilder::buildLTOD
>> // simplification opportunities, and both can propagate functions
>> through
>> // function pointers. When this happens, we often have to resolve
>> varargs
>> // calls, etc, so let instcombine do this.
>> - // FIXME: add peephole extensions here as the legacy PM does.
>> - MPM.addPass(createModuleToFunctionPassAdaptor(InstCombinePass()));
>> + FunctionPassManager PeepholeFPM(DebugLogging);
>> + PeepholeFPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(PeepholeFPM, Level);
>> +
>> + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(Peep
>> holeFPM)));
>>
>> // Note: historically, the PruneEH pass was run first to deduce
>> nounwind and
>> // generally clean up exception handling overhead. It isn't clear this
>> is
>> @@ -902,10 +945,10 @@ ModulePassManager PassBuilder::buildLTOD
>> MPM.addPass(GlobalDCEPass());
>>
>> FunctionPassManager FPM(DebugLogging);
>> -
>> // The IPO Passes may leave cruft around. Clean up after them.
>> - // FIXME: add peephole extensions here as the legacy PM does.
>> FPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(FPM, Level);
>> +
>> FPM.addPass(JumpThreadingPass());
>>
>> // Break up allocas
>> @@ -952,8 +995,11 @@ ModulePassManager PassBuilder::buildLTOD
>> MainFPM.add(AlignmentFromAssumptionsPass());
>> #endif
>>
>> - // FIXME: add peephole extensions to the PM here.
>> + // FIXME: Conditionally run LoadCombine here, after it's ported
>> + // (in case we still have this pass, given its questionable
>> usefulness).
>> +
>> MainFPM.addPass(InstCombinePass());
>> + invokePeepholeEPCallbacks(MainFPM, Level);
>> MainFPM.addPass(JumpThreadingPass());
>> MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM)));
>>
>> @@ -1036,7 +1082,27 @@ static bool startsWithDefaultPipelineAli
>> Name.startswith("lto");
>> }
>>
>> -static bool isModulePassName(StringRef Name) {
>> +/// Tests whether registered callbacks will accept a given pass name.
>> +///
>> +/// When parsing a pipeline text, the type of the outermost pipeline may
>> be
>> +/// omitted, in which case the type is automatically determined from the
>> first
>> +/// pass name in the text. This may be a name that is handled through
>> one of the
>> +/// callbacks. We check this through the oridinary parsing callbacks by
>> setting
>> +/// up a dummy PassManager in order to not force the client to also
>> handle this
>> +/// type of query.
>> +template <typename PassManagerT, typename CallbacksT>
>> +static bool callbacksAcceptPassName(StringRef Name, CallbacksT
>> &Callbacks) {
>> + if (!Callbacks.empty()) {
>> + PassManagerT DummyPM;
>> + for (auto &CB : Callbacks)
>> + if (CB(Name, DummyPM, {}))
>> + return true;
>> + }
>> + return false;
>> +}
>> +
>> +template <typename CallbacksT>
>> +static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
>> // Manually handle aliases for pre-configured pipeline fragments.
>> if (startsWithDefaultPipelineAliasPrefix(Name))
>> return DefaultAliasRegex.match(Name);
>> @@ -1061,10 +1127,11 @@ static bool isModulePassName(StringRef N
>> return true;
>> #include "PassRegistry.def"
>>
>> - return false;
>> + return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);
>> }
>>
>> -static bool isCGSCCPassName(StringRef Name) {
>> +template <typename CallbacksT>
>> +static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {
>> // Explicitly handle pass manager names.
>> if (Name == "cgscc")
>> return true;
>> @@ -1085,10 +1152,11 @@ static bool isCGSCCPassName(StringRef Na
>> return true;
>> #include "PassRegistry.def"
>>
>> - return false;
>> + return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);
>> }
>>
>> -static bool isFunctionPassName(StringRef Name) {
>> +template <typename CallbacksT>
>> +static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
>> // Explicitly handle pass manager names.
>> if (Name == "function")
>> return true;
>> @@ -1107,10 +1175,11 @@ static bool isFunctionPassName(StringRef
>> return true;
>> #include "PassRegistry.def"
>>
>> - return false;
>> + return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);
>> }
>>
>> -static bool isLoopPassName(StringRef Name) {
>> +template <typename CallbacksT>
>> +static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks) {
>> // Explicitly handle pass manager names.
>> if (Name == "loop")
>> return true;
>> @@ -1127,7 +1196,7 @@ static bool isLoopPassName(StringRef Nam
>> return true;
>> #include "PassRegistry.def"
>>
>> - return false;
>> + return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
>> }
>>
>> Optional<std::vector<PassBuilder::PipelineElement>>
>> @@ -1228,6 +1297,11 @@ bool PassBuilder::parseModulePass(Module
>> MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM)));
>> return true;
>> }
>> +
>> + for (auto &C : ModulePipelineParsingCallbacks)
>> + if (C(Name, MPM, InnerPipeline))
>> + return true;
>> +
>> // Normal passes can't have pipelines.
>> return false;
>> }
>> @@ -1240,12 +1314,12 @@ bool PassBuilder::parseModulePass(Module
>> assert(Matches.size() == 3 && "Must capture two matched strings!");
>>
>> OptimizationLevel L = StringSwitch<OptimizationLevel>(Matches[2])
>> - .Case("O0", O0)
>> - .Case("O1", O1)
>> - .Case("O2", O2)
>> - .Case("O3", O3)
>> - .Case("Os", Os)
>> - .Case("Oz", Oz);
>> + .Case("O0", O0)
>> + .Case("O1", O1)
>> + .Case("O2", O2)
>> + .Case("O3", O3)
>> + .Case("Os", Os)
>> + .Case("Oz", Oz);
>> if (L == O0)
>> // At O0 we do nothing at all!
>> return true;
>> @@ -1285,6 +1359,9 @@ bool PassBuilder::parseModulePass(Module
>> }
>> #include "PassRegistry.def"
>>
>> + for (auto &C : ModulePipelineParsingCallbacks)
>> + if (C(Name, MPM, InnerPipeline))
>> + return true;
>> return false;
>> }
>>
>> @@ -1332,11 +1409,16 @@ bool PassBuilder::parseCGSCCPass(CGSCCPa
>> *MaxRepetitions,
>> DebugLogging));
>> return true;
>> }
>> +
>> + for (auto &C : CGSCCPipelineParsingCallbacks)
>> + if (C(Name, CGPM, InnerPipeline))
>> + return true;
>> +
>> // Normal passes can't have pipelines.
>> return false;
>> }
>>
>> - // Now expand the basic registered passes from the .inc file.
>> +// Now expand the basic registered passes from the .inc file.
>> #define CGSCC_PASS(NAME, CREATE_PASS)
>> \
>> if (Name == NAME) {
>> \
>> CGPM.addPass(CREATE_PASS);
>> \
>> @@ -1357,6 +1439,9 @@ bool PassBuilder::parseCGSCCPass(CGSCCPa
>> }
>> #include "PassRegistry.def"
>>
>> + for (auto &C : CGSCCPipelineParsingCallbacks)
>> + if (C(Name, CGPM, InnerPipeline))
>> + return true;
>> return false;
>> }
>>
>> @@ -1394,11 +1479,16 @@ bool PassBuilder::parseFunctionPass(Func
>> FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM)));
>> return true;
>> }
>> +
>> + for (auto &C : FunctionPipelineParsingCallbacks)
>> + if (C(Name, FPM, InnerPipeline))
>> + return true;
>> +
>> // Normal passes can't have pipelines.
>> return false;
>> }
>>
>> - // Now expand the basic registered passes from the .inc file.
>> +// Now expand the basic registered passes from the .inc file.
>> #define FUNCTION_PASS(NAME, CREATE_PASS)
>> \
>> if (Name == NAME) {
>> \
>> FPM.addPass(CREATE_PASS);
>> \
>> @@ -1418,6 +1508,9 @@ bool PassBuilder::parseFunctionPass(Func
>> }
>> #include "PassRegistry.def"
>>
>> + for (auto &C : FunctionPipelineParsingCallbacks)
>> + if (C(Name, FPM, InnerPipeline))
>> + return true;
>> return false;
>> }
>>
>> @@ -1445,11 +1538,16 @@ bool PassBuilder::parseLoopPass(LoopPass
>> LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM)));
>> return true;
>> }
>> +
>> + for (auto &C : LoopPipelineParsingCallbacks)
>> + if (C(Name, LPM, InnerPipeline))
>> + return true;
>> +
>> // Normal passes can't have pipelines.
>> return false;
>> }
>>
>> - // Now expand the basic registered passes from the .inc file.
>> +// Now expand the basic registered passes from the .inc file.
>> #define LOOP_PASS(NAME, CREATE_PASS)
>> \
>> if (Name == NAME) {
>> \
>> LPM.addPass(CREATE_PASS);
>> \
>> @@ -1470,6 +1568,9 @@ bool PassBuilder::parseLoopPass(LoopPass
>> }
>> #include "PassRegistry.def"
>>
>> + for (auto &C : LoopPipelineParsingCallbacks)
>> + if (C(Name, LPM, InnerPipeline))
>> + return true;
>> return false;
>> }
>>
>> @@ -1488,6 +1589,9 @@ bool PassBuilder::parseAAPassName(AAMana
>> }
>> #include "PassRegistry.def"
>>
>> + for (auto &C : AAParsingCallbacks)
>> + if (C(Name, AA))
>> + return true;
>> return false;
>> }
>>
>> @@ -1554,7 +1658,7 @@ bool PassBuilder::parseModulePassPipelin
>> return true;
>> }
>>
>> -// Primary pass pipeline description parsing routine.
>> +// Primary pass pipeline description parsing routine for a \c
>> ModulePassManager
>> // FIXME: Should this routine accept a TargetMachine or require the
>> caller to
>> // pre-populate the analysis managers with target-specific stuff?
>> bool PassBuilder::parsePassPipeline(ModulePassManager &MPM,
>> @@ -1568,21 +1672,70 @@ bool PassBuilder::parsePassPipeline(Modu
>> // automatically.
>> StringRef FirstName = Pipeline->front().Name;
>>
>> - if (!isModulePassName(FirstName)) {
>> - if (isCGSCCPassName(FirstName))
>> + if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {
>> + if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {
>> Pipeline = {{"cgscc", std::move(*Pipeline)}};
>> - else if (isFunctionPassName(FirstName))
>> + } else if (isFunctionPassName(FirstName,
>> + FunctionPipelineParsingCallbacks)) {
>> Pipeline = {{"function", std::move(*Pipeline)}};
>> - else if (isLoopPassName(FirstName))
>> + } else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks)) {
>> Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}};
>> - else
>> + } else {
>> + for (auto &C : TopLevelPipelineParsingCallbacks)
>> + if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging))
>> + return true;
>> +
>> // Unknown pass name!
>> return false;
>> + }
>> }
>>
>> return parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass,
>> DebugLogging);
>> }
>>
>> +// Primary pass pipeline description parsing routine for a \c
>> CGSCCPassManager
>> +bool PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,
>> + StringRef PipelineText, bool
>> VerifyEachPass,
>> + bool DebugLogging) {
>> + auto Pipeline = parsePipelineText(PipelineText);
>> + if (!Pipeline || Pipeline->empty())
>> + return false;
>> +
>> + StringRef FirstName = Pipeline->front().Name;
>> + if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))
>> + return false;
>> +
>> + return parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass,
>> DebugLogging);
>> +}
>> +
>> +// Primary pass pipeline description parsing routine for a \c
>> +// FunctionPassManager
>> +bool PassBuilder::parsePassPipeline(FunctionPassManager &FPM,
>> + StringRef PipelineText, bool
>> VerifyEachPass,
>> + bool DebugLogging) {
>> + auto Pipeline = parsePipelineText(PipelineText);
>> + if (!Pipeline || Pipeline->empty())
>> + return false;
>> +
>> + StringRef FirstName = Pipeline->front().Name;
>> + if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))
>> + return false;
>> +
>> + return parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass,
>> + DebugLogging);
>> +}
>> +
>> +// Primary pass pipeline description parsing routine for a \c
>> LoopPassManager
>> +bool PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
>> + StringRef PipelineText, bool
>> VerifyEachPass,
>> + bool DebugLogging) {
>> + auto Pipeline = parsePipelineText(PipelineText);
>> + if (!Pipeline || Pipeline->empty())
>> + return false;
>> +
>> + return parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass,
>> DebugLogging);
>> +}
>> +
>> bool PassBuilder::parseAAPipeline(AAManager &AA, StringRef
>> PipelineText) {
>> // If the pipeline just consists of the word 'default' just replace
>> the AA
>> // manager with our default one.
>>
>> Modified: llvm/trunk/test/Other/new-pm-defaults.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/ne
>> w-pm-defaults.ll?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/test/Other/new-pm-defaults.ll (original)
>> +++ llvm/trunk/test/Other/new-pm-defaults.ll Mon Jul 10 03:57:55 2017
>> @@ -26,6 +26,37 @@
>> ; RUN: -passes='lto-pre-link<O2>' -S %s 2>&1 \
>> ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2
>>
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-peephole='no-op-function' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-PEEPHOLE
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-late-loop-optimizations='no-op-loop' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-LOOP-LATE
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-loop-optimizer-end='no-op-loop' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-LOOP-END
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-scalar-optimizer-late='no-op-function' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-SCALAR-LATE
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-cgscc-optimizer-late='no-op-cgscc' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-CGSCC-LATE
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes-ep-vectorizer-start='no-op-function' \
>> +; RUN: -passes='default<O3>' -S %s 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3
>> \
>> +; RUN: --check-prefix=CHECK-EP-VECTORIZER-START
>> +
>> ; CHECK-O: Starting llvm::Module pass manager run.
>> ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}>
>> ; CHECK-O-NEXT: Starting llvm::Module pass manager run.
>> @@ -53,6 +84,7 @@
>> ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{
>> .*}}PassManager{{.*}}>
>> ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
>> ; CHECK-O-NEXT: Running pass: InstCombinePass
>> +; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
>> ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
>> ; CHECK-O-NEXT: Running pass: RequireAnalysisPass<{{.*}}GlobalsAA
>> @@ -84,6 +116,7 @@
>> ; CHECK-O1-NEXT: Running pass: LibCallsShrinkWrapPass
>> ; CHECK-O2-NEXT: Running pass: LibCallsShrinkWrapPass
>> ; CHECK-O3-NEXT: Running pass: LibCallsShrinkWrapPass
>> +; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Running pass: TailCallElimPass
>> ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
>> ; CHECK-O-NEXT: Running pass: ReassociatePass
>> @@ -105,8 +138,10 @@
>> ; CHECK-O-NEXT: Starting Loop pass manager run.
>> ; CHECK-O-NEXT: Running pass: IndVarSimplifyPass
>> ; CHECK-O-NEXT: Running pass: LoopIdiomRecognizePass
>> +; CHECK-EP-LOOP-LATE-NEXT: Running pass: NoOpLoopPass
>> ; CHECK-O-NEXT: Running pass: LoopDeletionPass
>> ; CHECK-O-NEXT: Running pass: LoopUnrollPass
>> +; CHECK-EP-LOOP-END-NEXT: Running pass: NoOpLoopPass
>> ; CHECK-O-NEXT: Finished Loop pass manager run.
>> ; CHECK-Os-NEXT: Running pass: MergedLoadStoreMotionPass
>> ; CHECK-Os-NEXT: Running pass: GVN
>> @@ -126,15 +161,19 @@
>> ; CHECK-O-NEXT: Running pass: BDCEPass
>> ; CHECK-O-NEXT: Running analysis: DemandedBitsAnalysis
>> ; CHECK-O-NEXT: Running pass: InstCombinePass
>> +; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Running pass: JumpThreadingPass
>> ; CHECK-O-NEXT: Running pass: CorrelatedValuePropagationPass
>> ; CHECK-O-NEXT: Running pass: DSEPass
>> ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*
>> }}LICMPass{{.*}}>
>> +; CHECK-EP-SCALAR-LATE-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Running pass: ADCEPass
>> ; CHECK-O-NEXT: Running analysis: PostDominatorTreeAnalysis
>> ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
>> ; CHECK-O-NEXT: Running pass: InstCombinePass
>> +; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Finished llvm::Function pass manager run.
>> +; CHECK-EP-CGSCC-LATE-NEXT: Running pass: NoOpCGSCCPass
>> ; CHECK-O-NEXT: Finished CGSCC pass manager run.
>> ; CHECK-O-NEXT: Finished llvm::Module pass manager run.
>> ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}>
>> @@ -146,6 +185,7 @@
>> ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{
>> .*}}PassManager{{.*}}>
>> ; CHECK-O-NEXT: Starting llvm::Function pass manager run.
>> ; CHECK-O-NEXT: Running pass: Float2IntPass
>> +; CHECK-EP-VECTORIZER-START-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*
>> }}LoopRotatePass
>> ; CHECK-O-NEXT: Running pass: LoopDistributePass
>> ; CHECK-O-NEXT: Running pass: LoopVectorizePass
>>
>> Modified: llvm/trunk/test/Other/new-pm-lto-defaults.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/ne
>> w-pm-lto-defaults.ll?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/test/Other/new-pm-lto-defaults.ll (original)
>> +++ llvm/trunk/test/Other/new-pm-lto-defaults.ll Mon Jul 10 03:57:55 2017
>> @@ -17,6 +17,10 @@
>> ; RUN: opt -disable-verify -debug-pass-manager \
>> ; RUN: -passes='lto<Oz>' -S %s 2>&1 \
>> ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2
>> +; RUN: opt -disable-verify -debug-pass-manager \
>> +; RUN: -passes='lto<O3>' -S %s -passes-ep-peephole='no-op-function'
>> 2>&1 \
>> +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2
>> \
>> +; RUN: --check-prefix=CHECK-EP-Peephole
>>
>> ; CHECK-O: Starting llvm::Module pass manager run.
>> ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module
>> @@ -45,13 +49,18 @@
>> ; CHECK-O2-NEXT: Running analysis: AssumptionAnalysis
>> ; CHECK-O2-NEXT: Running pass: ConstantMergePass
>> ; CHECK-O2-NEXT: Running pass: DeadArgumentEliminationPass
>> -; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{
>> .*}}InstCombinePass>
>> +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{
>> .*}}PassManager{{.*}}>
>> +; CHECK-O2-NEXT: Starting llvm::Function pass manager run.
>> +; CHECK-O2-NEXT: Running pass: InstCombinePass
>> +; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass
>> +; CHECK-O2-NEXT: Finished llvm::Function pass manager run.
>> ; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdap
>> tor<{{.*}}InlinerPass>
>> ; CHECK-O2-NEXT: Running pass: GlobalOptPass
>> ; CHECK-O2-NEXT: Running pass: GlobalDCEPass
>> ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{
>> .*}}PassManager{{.*}}>
>> ; CHECK-O2-NEXT: Starting llvm::Function pass manager run.
>> ; CHECK-O2-NEXT: Running pass: InstCombinePass
>> +; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass
>> ; CHECK-O2-NEXT: Running pass: JumpThreadingPass
>> ; CHECK-O2-NEXT: Running analysis: LazyValueAnalysis
>> ; CHECK-O2-NEXT: Running pass: SROA on foo
>>
>> Modified: llvm/trunk/tools/opt/NewPMDriver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/New
>> PMDriver.cpp?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/tools/opt/NewPMDriver.cpp (original)
>> +++ llvm/trunk/tools/opt/NewPMDriver.cpp Mon Jul 10 03:57:55 2017
>> @@ -48,6 +48,83 @@ static cl::opt<std::string>
>> "pipeline for handling managed aliasing
>> queries"),
>> cl::Hidden);
>>
>> +/// {{@ These options accept textual pipeline descriptions which will be
>> +/// inserted into default pipelines at the respective extension points
>> +static cl::opt<std::string> PeepholeEPPipeline(
>> + "passes-ep-peephole",
>> + cl::desc("A textual description of the function pass pipeline
>> inserted at "
>> + "the Peephole extension points into default pipelines"),
>> + cl::Hidden);
>> +static cl::opt<std::string> LateLoopOptimizationsEPPipeline(
>> + "passes-ep-late-loop-optimizations",
>> + cl::desc(
>> + "A textual description of the loop pass pipeline inserted at "
>> + "the LateLoopOptimizations extension point into default
>> pipelines"),
>> + cl::Hidden);
>> +static cl::opt<std::string> LoopOptimizerEndEPPipeline(
>> + "passes-ep-loop-optimizer-end",
>> + cl::desc("A textual description of the loop pass pipeline inserted
>> at "
>> + "the LoopOptimizerEnd extension point into default
>> pipelines"),
>> + cl::Hidden);
>> +static cl::opt<std::string> ScalarOptimizerLateEPPipeline(
>> + "passes-ep-scalar-optimizer-late",
>> + cl::desc("A textual description of the function pass pipeline
>> inserted at "
>> + "the ScalarOptimizerLate extension point into default
>> pipelines"),
>> + cl::Hidden);
>> +static cl::opt<std::string> CGSCCOptimizerLateEPPipeline(
>> + "passes-ep-cgscc-optimizer-late",
>> + cl::desc("A textual description of the cgscc pass pipeline inserted
>> at "
>> + "the CGSCCOptimizerLate extension point into default
>> pipelines"),
>> + cl::Hidden);
>> +static cl::opt<std::string> VectorizerStartEPPipeline(
>> + "passes-ep-vectorizer-start",
>> + cl::desc("A textual description of the function pass pipeline
>> inserted at "
>> + "the VectorizerStart extension point into default
>> pipelines"),
>> + cl::Hidden);
>> +/// @}}
>> +
>> +/// If one of the EPPipeline command line options was given, register
>> callbacks
>> +/// for parsing and inserting the given pipeline
>> +static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
>> + bool DebugLogging) {
>> + if (!PeepholeEPPipeline.empty())
>> + PB.registerPeepholeEPCallback(
>> + [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel
>> Level) {
>> + return PB.parsePassPipeline(PM, PeepholeEPPipeline,
>> VerifyEachPass,
>> + DebugPM);
>> + });
>> + if (!LateLoopOptimizationsEPPipeline.empty())
>> + PB.registerLateLoopOptimizationsEPCallback(
>> + [&](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
>> + return PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipelin
>> e,
>> + VerifyEachPass, DebugPM);
>> + });
>> + if (!LoopOptimizerEndEPPipeline.empty())
>> + PB.registerLoopOptimizerEndEPCallback(
>> + [&](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
>> + return PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline,
>> + VerifyEachPass, DebugPM);
>> + });
>> + if (!ScalarOptimizerLateEPPipeline.empty())
>> + PB.registerScalarOptimizerLateEPCallback(
>> + [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel
>> Level) {
>> + return PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline,
>> + VerifyEachPass, DebugPM);
>> + });
>> + if (!CGSCCOptimizerLateEPPipeline.empty())
>> + PB.registerCGSCCOptimizerLateEPCallback(
>> + [&](CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) {
>> + return PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline,
>> + VerifyEachPass, DebugPM);
>> + });
>> + if (!VectorizerStartEPPipeline.empty())
>> + PB.registerVectorizerStartEPCallback(
>> + [&](FunctionPassManager &PM, PassBuilder::OptimizationLevel
>> Level) {
>> + return PB.parsePassPipeline(PM, VectorizerStartEPPipeline,
>> + VerifyEachPass, DebugPM);
>> + });
>> +}
>> +
>> bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
>> tool_output_file *Out,
>> tool_output_file *ThinLTOLinkOut,
>> @@ -56,7 +133,9 @@ bool llvm::runPassPipeline(StringRef Arg
>> bool ShouldPreserveAssemblyUseListOrder,
>> bool ShouldPreserveBitcodeUseListOrder,
>> bool EmitSummaryIndex, bool EmitModuleHash) {
>> + bool VerifyEachPass = VK == VK_VerifyEachPass;
>> PassBuilder PB(TM);
>> + registerEPCallbacks(PB, VerifyEachPass, DebugPM);
>>
>> // Specially handle the alias analysis manager so that we can register
>> // a custom pipeline of AA passes with it.
>> @@ -85,8 +164,7 @@ bool llvm::runPassPipeline(StringRef Arg
>> if (VK > VK_NoVerifier)
>> MPM.addPass(VerifierPass());
>>
>> - if (!PB.parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass,
>> - DebugPM)) {
>> + if (!PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM))
>> {
>> errs() << Arg0 << ": unable to parse pass pipeline description.\n";
>> return false;
>> }
>>
>> Modified: llvm/trunk/unittests/IR/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/
>> CMakeLists.txt?rev=307532&r1=307531&r2=307532&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/unittests/IR/CMakeLists.txt (original)
>> +++ llvm/trunk/unittests/IR/CMakeLists.txt Mon Jul 10 03:57:55 2017
>> @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
>> AsmParser
>> Core
>> Support
>> + Passes
>> )
>>
>> set(IRSources
>> @@ -15,6 +16,7 @@ set(IRSources
>> DebugTypeODRUniquingTest.cpp
>> DominatorTreeTest.cpp
>> FunctionTest.cpp
>> + PassBuilderCallbacksTest.cpp
>> IRBuilderTest.cpp
>> InstructionsTest.cpp
>> IntrinsicsTest.cpp
>>
>> Added: llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/
>> PassBuilderCallbacksTest.cpp?rev=307532&view=auto
>> ============================================================
>> ==================
>> --- llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp (added)
>> +++ llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp Mon Jul 10
>> 03:57:55 2017
>> @@ -0,0 +1,520 @@
>> +//===- unittests/IR/PassBuilderCallbacksTest.cpp - PB Callback Tests
>> --===//
>> +//
>> +// The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===------------------------------------------------------
>> ----------------===//
>> +
>> +#include <gmock/gmock.h>
>> +#include <gtest/gtest.h>
>> +#include <llvm/Analysis/CGSCCPassManager.h>
>> +#include <llvm/Analysis/LoopAnalysisManager.h>
>> +#include <llvm/AsmParser/Parser.h>
>> +#include <llvm/IR/LLVMContext.h>
>> +#include <llvm/IR/PassManager.h>
>> +#include <llvm/Passes/PassBuilder.h>
>> +#include <llvm/Support/SourceMgr.h>
>> +#include <llvm/Transforms/Scalar/LoopPassManager.h>
>> +
>> +using namespace llvm;
>> +
>> +namespace llvm {
>> +/// Provide an ostream operator for StringRef.
>> +///
>> +/// For convenience we provide a custom matcher below for IRUnit's and
>> analysis
>> +/// result's getName functions, which most of the time returns a
>> StringRef. The
>> +/// matcher makes use of this operator.
>> +static std::ostream &operator<<(std::ostream &O, StringRef S) {
>> + return O << S.str();
>> +}
>> +}
>> +
>> +namespace {
>> +using testing::DoDefault;
>> +using testing::Return;
>> +using testing::Expectation;
>> +using testing::Invoke;
>> +using testing::WithArgs;
>> +using testing::_;
>> +
>> +/// \brief A CRTP base for analysis mock handles
>> +///
>> +/// This class reconciles mocking with the value semantics
>> implementation of the
>> +/// AnalysisManager. Analysis mock handles should derive from this class
>> and
>> +/// call \c setDefault() in their constroctur for wiring up the defaults
>> defined
>> +/// by this base with their mock run() and invalidate() implementations.
>> +template <typename DerivedT, typename IRUnitT,
>> + typename AnalysisManagerT = AnalysisManager<IRUnitT>,
>> + typename... ExtraArgTs>
>> +class MockAnalysisHandleBase {
>> +public:
>> + class Analysis : public AnalysisInfoMixin<Analysis> {
>> + friend AnalysisInfoMixin<Analysis>;
>> + friend MockAnalysisHandleBase;
>> + static AnalysisKey Key;
>> +
>> + DerivedT *Handle;
>> +
>> + Analysis(DerivedT &Handle) : Handle(&Handle) {
>> + static_assert(std::is_base_of<MockAnalysisHandleBase,
>> DerivedT>::value,
>> + "Must pass the derived type to this template!");
>> + }
>> +
>> + public:
>> + class Result {
>> + friend MockAnalysisHandleBase;
>> +
>> + DerivedT *Handle;
>> +
>> + Result(DerivedT &Handle) : Handle(&Handle) {}
>> +
>> + public:
>> + // Forward invalidation events to the mock handle.
>> + bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
>> + typename AnalysisManagerT::Invalidator &Inv) {
>> + return Handle->invalidate(IR, PA, Inv);
>> + }
>> + };
>> +
>> + Result run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs...
>> ExtraArgs) {
>> + return Handle->run(IR, AM, ExtraArgs...);
>> + }
>> + };
>> +
>> + Analysis getAnalysis() { return Analysis(static_cast<DerivedT
>> &>(*this)); }
>> + typename Analysis::Result getResult() {
>> + return typename Analysis::Result(static_cast<DerivedT &>(*this));
>> + }
>> +
>> +protected:
>> + // FIXME: MSVC seems unable to handle a lambda argument to Invoke from
>> within
>> + // the template, so we use a boring static function.
>> + static bool invalidateCallback(IRUnitT &IR, const PreservedAnalyses
>> &PA,
>> + typename AnalysisManagerT::Invalidator
>> &Inv) {
>> + auto PAC = PA.template getChecker<Analysis>();
>> + return !PAC.preserved() &&
>> + !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
>> + }
>> +
>> + /// Derived classes should call this in their constructor to set up
>> default
>> + /// mock actions. (We can't do this in our constructor because this
>> has to
>> + /// run after the DerivedT is constructed.)
>> + void setDefaults() {
>> + ON_CALL(static_cast<DerivedT &>(*this),
>> + run(_, _, testing::Matcher<ExtraArgTs>(_)...))
>> + .WillByDefault(Return(this->getResult()));
>> + ON_CALL(static_cast<DerivedT &>(*this), invalidate(_, _, _))
>> + .WillByDefault(Invoke(&invalidateCallback));
>> + }
>> +};
>> +
>> +/// \brief A CRTP base for pass mock handles
>> +///
>> +/// This class reconciles mocking with the value semantics
>> implementation of the
>> +/// PassManager. Pass mock handles should derive from this class and
>> +/// call \c setDefault() in their constroctur for wiring up the defaults
>> defined
>> +/// by this base with their mock run() and invalidate() implementations.
>> +template <typename DerivedT, typename IRUnitT, typename AnalysisManagerT,
>> + typename... ExtraArgTs>
>> +AnalysisKey MockAnalysisHandleBase<DerivedT, IRUnitT, AnalysisManagerT,
>> + ExtraArgTs...>::Analysis::Key;
>> +
>> +template <typename DerivedT, typename IRUnitT,
>> + typename AnalysisManagerT = AnalysisManager<IRUnitT>,
>> + typename... ExtraArgTs>
>> +class MockPassHandleBase {
>> +public:
>> + class Pass : public PassInfoMixin<Pass> {
>> + friend MockPassHandleBase;
>> +
>> + DerivedT *Handle;
>> +
>> + Pass(DerivedT &Handle) : Handle(&Handle) {
>> + static_assert(std::is_base_of<MockPassHandleBase,
>> DerivedT>::value,
>> + "Must pass the derived type to this template!");
>> + }
>> +
>> + public:
>> + PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
>> + ExtraArgTs... ExtraArgs) {
>> + return Handle->run(IR, AM, ExtraArgs...);
>> + }
>> + };
>> +
>> + Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); }
>> +
>> +protected:
>> + /// Derived classes should call this in their constructor to set up
>> default
>> + /// mock actions. (We can't do this in our constructor because this
>> has to
>> + /// run after the DerivedT is constructed.)
>> + void setDefaults() {
>> + ON_CALL(static_cast<DerivedT &>(*this),
>> + run(_, _, testing::Matcher<ExtraArgTs>(_)...))
>> + .WillByDefault(Return(PreservedAnalyses::all()));
>> + }
>> +};
>> +
>> +/// Mock handles for passes for the IRUnits Module, CGSCC, Function,
>> Loop.
>> +/// These handles define the appropriate run() mock interface for the
>> respective
>> +/// IRUnit type.
>> +template <typename IRUnitT> struct MockPassHandle;
>> +template <>
>> +struct MockPassHandle<Loop>
>> + : MockPassHandleBase<MockPassHandle<Loop>, Loop,
>> LoopAnalysisManager,
>> + LoopStandardAnalysisResults &, LPMUpdater &> {
>> + MOCK_METHOD4(run,
>> + PreservedAnalyses(Loop &, LoopAnalysisManager &,
>> + LoopStandardAnalysisResults &,
>> LPMUpdater &));
>> + MockPassHandle() { setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockPassHandle<Function>
>> + : MockPassHandleBase<MockPassHandle<Function>, Function> {
>> + MOCK_METHOD2(run, PreservedAnalyses(Function &,
>> FunctionAnalysisManager &));
>> +
>> + MockPassHandle() { setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockPassHandle<LazyCallGraph::SCC>
>> + : MockPassHandleBase<MockPassHandle<LazyCallGraph::SCC>,
>> LazyCallGraph::SCC,
>> + CGSCCAnalysisManager, LazyCallGraph &,
>> + CGSCCUpdateResult &> {
>> + MOCK_METHOD4(run,
>> + PreservedAnalyses(LazyCallGraph::SCC &,
>> CGSCCAnalysisManager &,
>> + LazyCallGraph &G, CGSCCUpdateResult
>> &UR));
>> +
>> + MockPassHandle() { setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockPassHandle<Module>
>> + : MockPassHandleBase<MockPassHandle<Module>, Module> {
>> + MOCK_METHOD2(run, PreservedAnalyses(Module &, ModuleAnalysisManager
>> &));
>> +
>> + MockPassHandle() { setDefaults(); }
>> +};
>> +
>> +/// Mock handles for analyses for the IRUnits Module, CGSCC, Function,
>> Loop.
>> +/// These handles define the appropriate run() and invalidate() mock
>> interfaces
>> +/// for the respective IRUnit type.
>> +template <typename IRUnitT> struct MockAnalysisHandle;
>> +template <>
>> +struct MockAnalysisHandle<Loop>
>> + : MockAnalysisHandleBase<MockAnalysisHandle<Loop>, Loop,
>> + LoopAnalysisManager,
>> + LoopStandardAnalysisResults &> {
>> +
>> + MOCK_METHOD3_T(run, typename Analysis::Result(Loop &,
>> LoopAnalysisManager &,
>> +
>> LoopStandardAnalysisResults &));
>> +
>> + MOCK_METHOD3_T(invalidate, bool(Loop &, const PreservedAnalyses &,
>> + LoopAnalysisManager::Invalidator &));
>> +
>> + MockAnalysisHandle<Loop>() { this->setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockAnalysisHandle<Function>
>> + : MockAnalysisHandleBase<MockAnalysisHandle<Function>, Function> {
>> + MOCK_METHOD2(run, Analysis::Result(Function &, FunctionAnalysisManager
>> &));
>> +
>> + MOCK_METHOD3(invalidate, bool(Function &, const PreservedAnalyses &,
>> + FunctionAnalysisManager::Invalidator
>> &));
>> +
>> + MockAnalysisHandle<Function>() { setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockAnalysisHandle<LazyCallGraph::SCC>
>> + : MockAnalysisHandleBase<MockAnalysisHandle<LazyCallGraph::SCC>,
>> + LazyCallGraph::SCC, CGSCCAnalysisManager,
>> + LazyCallGraph &> {
>> + MOCK_METHOD3(run, Analysis::Result(LazyCallGraph::SCC &,
>> + CGSCCAnalysisManager &,
>> LazyCallGraph &));
>> +
>> + MOCK_METHOD3(invalidate, bool(LazyCallGraph::SCC &, const
>> PreservedAnalyses &,
>> + CGSCCAnalysisManager::Invalidator &));
>> +
>> + MockAnalysisHandle<LazyCallGraph::SCC>() { setDefaults(); }
>> +};
>> +
>> +template <>
>> +struct MockAnalysisHandle<Module>
>> + : MockAnalysisHandleBase<MockAnalysisHandle<Module>, Module> {
>> + MOCK_METHOD2(run, Analysis::Result(Module &, ModuleAnalysisManager &));
>> +
>> + MOCK_METHOD3(invalidate, bool(Module &, const PreservedAnalyses &,
>> + ModuleAnalysisManager::Invalidator &));
>> +
>> + MockAnalysisHandle<Module>() { setDefaults(); }
>> +};
>> +
>> +static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
>> + SMDiagnostic Err;
>> + return parseAssemblyString(IR, Err, C);
>> +}
>> +
>> +template <typename PassManagerT> class PassBuilderCallbacksTest;
>> +
>> +/// This test fixture is shared between all the actual tests below and
>> +/// takes care of setting up appropriate defaults.
>> +///
>> +/// The template specialization serves to extract the IRUnit and AM
>> types from
>> +/// the given PassManagerT.
>> +template <typename TestIRUnitT, typename... ExtraPassArgTs,
>> + typename... ExtraAnalysisArgTs>
>> +class PassBuilderCallbacksTest<PassManager<
>> + TestIRUnitT, AnalysisManager<TestIRUnitT, ExtraAnalysisArgTs...>,
>> + ExtraPassArgTs...>> : public testing::Test {
>> +protected:
>> + using IRUnitT = TestIRUnitT;
>> + using AnalysisManagerT = AnalysisManager<TestIRUnitT,
>> ExtraAnalysisArgTs...>;
>> + using PassManagerT =
>> + PassManager<TestIRUnitT, AnalysisManagerT, ExtraPassArgTs...>;
>> + using AnalysisT = typename MockAnalysisHandle<IRUnitT>::Analysis;
>> +
>> + LLVMContext Context;
>> + std::unique_ptr<Module> M;
>> +
>> + PassBuilder PB;
>> + ModulePassManager PM;
>> + LoopAnalysisManager LAM;
>> + FunctionAnalysisManager FAM;
>> + CGSCCAnalysisManager CGAM;
>> + ModuleAnalysisManager AM;
>> +
>> + MockPassHandle<IRUnitT> PassHandle;
>> + MockAnalysisHandle<IRUnitT> AnalysisHandle;
>> +
>> + static PreservedAnalyses getAnalysisResult(IRUnitT &U,
>> AnalysisManagerT &AM,
>> + ExtraAnalysisArgTs &&...
>> Args) {
>> + (void)AM.template getResult<AnalysisT>(
>> + U, std::forward<ExtraAnalysisArgTs>(Args)...);
>> + return PreservedAnalyses::all();
>> + }
>> +
>> + PassBuilderCallbacksTest()
>> + : M(parseIR(Context,
>> + "declare void @bar()\n"
>> + "define void @foo(i32 %n) {\n"
>> + "entry:\n"
>> + " br label %loop\n"
>> + "loop:\n"
>> + " %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]\n"
>> + " %iv.next = add i32 %iv, 1\n"
>> + " tail call void @bar()\n"
>> + " %cmp = icmp eq i32 %iv, %n\n"
>> + " br i1 %cmp, label %exit, label %loop\n"
>> + "exit:\n"
>> + " ret void\n"
>> + "}\n")),
>> + PM(true), LAM(true), FAM(true), CGAM(true), AM(true) {
>> +
>> + /// Register a callback for analysis registration.
>> + ///
>> + /// The callback is a function taking a reference to an
>> AnalyisManager
>> + /// object. When called, the callee gets to register its own
>> analyses with
>> + /// this PassBuilder instance.
>> + PB.registerAnalysisRegistrationCallback([this](AnalysisManagerT
>> &AM) {
>> + // Register our mock analysis
>> + AM.registerPass([this] { return AnalysisHandle.getAnalysis(); });
>> + });
>> +
>> + /// Register a callback for pipeline parsing.
>> + ///
>> + /// During parsing of a textual pipeline, the PassBuilder will call
>> these
>> + /// callbacks for each encountered pass name that it does not know.
>> This
>> + /// includes both simple pass names as well as names of
>> sub-pipelines. In
>> + /// the latter case, the InnerPipeline is not empty.
>> + PB.registerPipelineParsingCallback(
>> + [this](StringRef Name, PassManagerT &PM,
>> + ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
>> + /// Handle parsing of the names of analysis utilities such as
>> + /// require<test-analysis> and invalidate<test-analysis> for
>> our
>> + /// analysis mock handle
>> + if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis",
>> Name, PM))
>> + return true;
>> +
>> + /// Parse the name of our pass mock handle
>> + if (Name == "test-transform") {
>> + PM.addPass(PassHandle.getPass());
>> + return true;
>> + }
>> + return false;
>> + });
>> +
>> + /// Register builtin analyses and cross-register the analysis proxies
>> + PB.registerModuleAnalyses(AM);
>> + PB.registerCGSCCAnalyses(CGAM);
>> + PB.registerFunctionAnalyses(FAM);
>> + PB.registerLoopAnalyses(LAM);
>> + PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
>> + }
>> +};
>> +
>> +/// Define a custom matcher for objects which support a 'getName' method.
>> +///
>> +/// LLVM often has IR objects or analysis objects which expose a name
>> +/// and in tests it is convenient to match these by name for readability.
>> +/// Usually, this name is either a StringRef or a plain std::string. This
>> +/// matcher supports any type exposing a getName() method of this form
>> whose
>> +/// return value is compatible with an std::ostream. For StringRef, this
>> uses
>> +/// the shift operator defined above.
>> +///
>> +/// It should be used as:
>> +///
>> +/// HasName("my_function")
>> +///
>> +/// No namespace or other qualification is required.
>> +MATCHER_P(HasName, Name, "") {
>> + *result_listener << "has name '" << arg.getName() << "'";
>> + return Name == arg.getName();
>> +}
>> +
>> +using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>;
>> +using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>;
>> +using FunctionCallbacksTest = PassBuilderCallbacksTest<Funct
>> ionPassManager>;
>> +using LoopCallbacksTest = PassBuilderCallbacksTest<LoopPassManager>;
>> +
>> +/// Test parsing of the name of our mock pass for all IRUnits.
>> +///
>> +/// The pass should by default run our mock analysis and then preserve
>> it.
>> +TEST_F(ModuleCallbacksTest, Passes) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
>> + EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
>> + .WillOnce(Invoke(getAnalysisResult));
>> +
>> + StringRef PipelineText = "test-transform";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(FunctionCallbacksTest, Passes) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
>> + EXPECT_CALL(PassHandle, run(HasName("foo"), _))
>> + .WillOnce(Invoke(getAnalysisResult));
>> +
>> + StringRef PipelineText = "test-transform";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(LoopCallbacksTest, Passes) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
>> + EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
>> + .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
>> +
>> + StringRef PipelineText = "test-transform";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(CGSCCCallbacksTest, Passes) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
>> + EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
>> + .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult)));
>> +
>> + StringRef PipelineText = "test-transform";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +/// Test parsing of the names of analysis utilities for our mock analysis
>> +/// for all IRUnits.
>> +///
>> +/// We first require<>, then invalidate<> it, expecting the analysis to
>> be run
>> +/// once and subsequently invalidated.
>> +TEST_F(ModuleCallbacksTest, AnalysisUtilities) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
>> + EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
>> +
>> + StringRef PipelineText = "require<test-analysis>,invali
>> date<test-analysis>";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(CGSCCCallbacksTest, PassUtilities) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
>> + EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _));
>> +
>> + StringRef PipelineText = "require<test-analysis>,invali
>> date<test-analysis>";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(FunctionCallbacksTest, AnalysisUtilities) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _));
>> + EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _));
>> +
>> + StringRef PipelineText = "require<test-analysis>,invali
>> date<test-analysis>";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +TEST_F(LoopCallbacksTest, PassUtilities) {
>> + EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
>> + EXPECT_CALL(AnalysisHandle, invalidate(HasName("loop"), _, _));
>> +
>> + StringRef PipelineText = "require<test-analysis>,invali
>> date<test-analysis>";
>> +
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +}
>> +
>> +/// Test parsing of the top-level pipeline.
>> +///
>> +/// The ParseTopLevelPipeline callback takes over parsing of the entire
>> pipeline
>> +/// from PassBuilder if it encounters an unknown pipeline entry at the
>> top level
>> +/// (i.e., the first entry on the pipeline).
>> +/// This test parses a pipeline named 'another-pipeline', whose only
>> elements
>> +/// may be the test-transform pass or the analysis utilities
>> +TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) {
>> + PB.registerParseTopLevelPipelineCallback([this](
>> + ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement>
>> Pipeline,
>> + bool VerifyEachPass, bool DebugLogging) {
>> + auto &FirstName = Pipeline.front().Name;
>> + auto &InnerPipeline = Pipeline.front().InnerPipeline;
>> + if (FirstName == "another-pipeline") {
>> + for (auto &E : InnerPipeline) {
>> + if (parseAnalysisUtilityPasses<AnalysisT>("test-analysis",
>> E.Name, PM))
>> + continue;
>> +
>> + if (E.Name == "test-transform") {
>> + PM.addPass(PassHandle.getPass());
>> + continue;
>> + }
>> + return false;
>> + }
>> + }
>> + return true;
>> + });
>> +
>> + EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _));
>> + EXPECT_CALL(PassHandle, run(HasName("<string>"), _))
>> + .WillOnce(Invoke(getAnalysisResult));
>> + EXPECT_CALL(AnalysisHandle, invalidate(HasName("<string>"), _, _));
>> +
>> + StringRef PipelineText =
>> + "another-pipeline(test-transform,invalidate<test-analysis>)";
>> + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> + PM.run(*M, AM);
>> +
>> + /// Test the negative case
>> + PipelineText = "another-pipeline(instcombine)";
>> + ASSERT_FALSE(PB.parsePassPipeline(PM, PipelineText, true))
>> + << "Pipeline was: " << PipelineText;
>> +}
>> +} // end anonymous namespace
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170711/54b297f0/attachment-0001.html>
More information about the llvm-commits
mailing list