diff options
Diffstat (limited to 'lib/Passes/PassBuilder.cpp')
| -rw-r--r-- | lib/Passes/PassBuilder.cpp | 512 |
1 files changed, 352 insertions, 160 deletions
diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index eb04dcc8b6ef..5ec94ea6f40a 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -48,6 +48,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" @@ -58,10 +59,10 @@ #include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" -#include "llvm/Transforms/Instrumentation/CGProfile.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/ArgumentPromotion.h" #include "llvm/Transforms/IPO/CalledValuePropagation.h" @@ -75,6 +76,7 @@ #include "llvm/Transforms/IPO/GlobalDCE.h" #include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/IPO/GlobalSplit.h" +#include "llvm/Transforms/IPO/HotColdSplitting.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/Inliner.h" #include "llvm/Transforms/IPO/Internalize.h" @@ -86,9 +88,14 @@ #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h" #include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/BoundsChecking.h" +#include "llvm/Transforms/Instrumentation/CGProfile.h" +#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h" #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" +#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" @@ -127,6 +134,7 @@ #include "llvm/Transforms/Scalar/LowerAtomic.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h" +#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" #include "llvm/Transforms/Scalar/NaryReassociate.h" @@ -136,14 +144,17 @@ #include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h" #include "llvm/Transforms/Scalar/SCCP.h" #include "llvm/Transforms/Scalar/SROA.h" +#include "llvm/Transforms/Scalar/Scalarizer.h" #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Scalar/Sink.h" #include "llvm/Transforms/Scalar/SpeculateAroundPHIs.h" #include "llvm/Transforms/Scalar/SpeculativeExecution.h" #include "llvm/Transforms/Scalar/TailRecursionElimination.h" +#include "llvm/Transforms/Scalar/WarnMissedTransforms.h" #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/BreakCriticalEdges.h" +#include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" #include "llvm/Transforms/Utils/LCSSA.h" #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h" @@ -152,6 +163,7 @@ #include "llvm/Transforms/Utils/Mem2Reg.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h" #include "llvm/Transforms/Vectorize/LoopVectorize.h" #include "llvm/Transforms/Vectorize/SLPVectorizer.h" @@ -193,6 +205,12 @@ static cl::opt<bool> EnableSyntheticCounts( static Regex DefaultAliasRegex( "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$"); +static cl::opt<bool> + EnableCHR("enable-chr-npm", cl::init(true), cl::Hidden, + cl::desc("Enable control height reduction optimization (CHR)")); + +extern cl::opt<bool> EnableHotColdSplit; + static bool isOptimizingForSize(PassBuilder::OptimizationLevel Level) { switch (Level) { case PassBuilder::O0: @@ -486,6 +504,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, FPM.addPass(InstCombinePass()); invokePeepholeEPCallbacks(FPM, Level); + if (EnableCHR && Level == O3 && PGOOpt && + (!PGOOpt->ProfileUseFile.empty() || !PGOOpt->SampleProfileFile.empty())) + FPM.addPass(ControlHeightReductionPass()); + return FPM; } @@ -493,7 +515,8 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, PassBuilder::OptimizationLevel Level, bool RunProfileGen, std::string ProfileGenFile, - std::string ProfileUseFile) { + std::string ProfileUseFile, + std::string ProfileRemappingFile) { // 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 @@ -547,7 +570,7 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, } if (!ProfileUseFile.empty()) - MPM.addPass(PGOInstrumentationUse(ProfileUseFile)); + MPM.addPass(PGOInstrumentationUse(ProfileUseFile, ProfileRemappingFile)); } static InlineParams @@ -593,6 +616,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // Annotate sample profile right after early FPM to ensure freshness of // the debug info. MPM.addPass(SampleProfileLoaderPass(PGOOpt->SampleProfileFile, + PGOOpt->ProfileRemappingFile, Phase == ThinLTOPhase::PreLink)); // Do not invoke ICP in the ThinLTOPrelink phase as it makes it hard // for the profile annotation to be accurate in the ThinLTO backend. @@ -642,7 +666,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, if (PGOOpt && Phase != ThinLTOPhase::PostLink && (!PGOOpt->ProfileGenFile.empty() || !PGOOpt->ProfileUseFile.empty())) { addPGOInstrPasses(MPM, DebugLogging, Level, PGOOpt->RunProfileGen, - PGOOpt->ProfileGenFile, PGOOpt->ProfileUseFile); + PGOOpt->ProfileGenFile, PGOOpt->ProfileUseFile, + PGOOpt->ProfileRemappingFile); MPM.addPass(PGOIndirectCallPromotion(false, false)); } @@ -693,6 +718,11 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( buildFunctionSimplificationPipeline(Level, Phase, DebugLogging))); + // We only want to do hot cold splitting once for ThinLTO, during the + // post-link ThinLTO. + if (EnableHotColdSplit && Phase != ThinLTOPhase::PreLink) + MPM.addPass(HotColdSplittingPass()); + for (auto &C : CGSCCOptimizerLateEPCallbacks) C(MainCGPipeline, Level); @@ -809,7 +839,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, OptimizePM.addPass( createFunctionToLoopPassAdaptor(LoopUnrollAndJamPass(Level))); } - OptimizePM.addPass(LoopUnrollPass(Level)); + OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level))); + OptimizePM.addPass(WarnMissedTransformationsPass()); OptimizePM.addPass(InstCombinePass()); OptimizePM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); OptimizePM.addPass(createFunctionToLoopPassAdaptor(LICMPass(), DebugLogging)); @@ -841,6 +872,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, // inserting redudnancies into the progrem. This even includes SimplifyCFG. OptimizePM.addPass(SpeculateAroundPHIsPass()); + for (auto &C : OptimizerLastEPCallbacks) + C(OptimizePM, Level); + // Add the core optimizing pipeline. MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM))); @@ -980,6 +1014,13 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, assert(Level != O0 && "Must request optimizations for the default pipeline!"); ModulePassManager MPM(DebugLogging); + if (PGOOpt && !PGOOpt->SampleProfileFile.empty()) { + // Load sample profile before running the LTO optimization pipeline. + MPM.addPass(SampleProfileLoaderPass(PGOOpt->SampleProfileFile, + PGOOpt->ProfileRemappingFile, + false /* ThinLTOPhase::PreLink */)); + } + // Remove unused virtual tables to improve the quality of code generated by // whole-program devirtualization and bitset lowering. MPM.addPass(GlobalDCEPass()); @@ -1202,6 +1243,91 @@ static Optional<int> parseDevirtPassName(StringRef Name) { return Count; } +static bool checkParametrizedPassName(StringRef Name, StringRef PassName) { + if (!Name.consume_front(PassName)) + return false; + // normal pass name w/o parameters == default parameters + if (Name.empty()) + return true; + return Name.startswith("<") && Name.endswith(">"); +} + +namespace { + +/// This performs customized parsing of pass name with parameters. +/// +/// We do not need parametrization of passes in textual pipeline very often, +/// yet on a rare occasion ability to specify parameters right there can be +/// useful. +/// +/// \p Name - parameterized specification of a pass from a textual pipeline +/// is a string in a form of : +/// PassName '<' parameter-list '>' +/// +/// Parameter list is being parsed by the parser callable argument, \p Parser, +/// It takes a string-ref of parameters and returns either StringError or a +/// parameter list in a form of a custom parameters type, all wrapped into +/// Expected<> template class. +/// +template <typename ParametersParseCallableT> +auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name, + StringRef PassName) -> decltype(Parser(StringRef{})) { + using ParametersT = typename decltype(Parser(StringRef{}))::value_type; + + StringRef Params = Name; + if (!Params.consume_front(PassName)) { + assert(false && + "unable to strip pass name from parametrized pass specification"); + } + if (Params.empty()) + return ParametersT{}; + if (!Params.consume_front("<") || !Params.consume_back(">")) { + assert(false && "invalid format for parametrized pass name"); + } + + Expected<ParametersT> Result = Parser(Params); + assert((Result || Result.template errorIsA<StringError>()) && + "Pass parameter parser can only return StringErrors."); + return std::move(Result); +} + +/// Parser of parameters for LoopUnroll pass. +Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) { + LoopUnrollOptions UnrollOpts; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + int OptLevel = StringSwitch<int>(ParamName) + .Case("O0", 0) + .Case("O1", 1) + .Case("O2", 2) + .Case("O3", 3) + .Default(-1); + if (OptLevel >= 0) { + UnrollOpts.setOptLevel(OptLevel); + continue; + } + + bool Enable = !ParamName.consume_front("no-"); + if (ParamName == "partial") { + UnrollOpts.setPartial(Enable); + } else if (ParamName == "peeling") { + UnrollOpts.setPeeling(Enable); + } else if (ParamName == "runtime") { + UnrollOpts.setRuntime(Enable); + } else if (ParamName == "upperbound") { + UnrollOpts.setUpperBound(Enable); + } else { + return make_error<StringError>( + formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(), + inconvertibleErrorCode()); + } + } + return UnrollOpts; +} + +} // namespace + /// Tests whether a pass name starts with a valid prefix for a default pipeline /// alias. static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) { @@ -1297,6 +1423,9 @@ static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) { #define FUNCTION_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) \ + return true; #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; @@ -1383,9 +1512,9 @@ PassBuilder::parsePipelineText(StringRef Text) { return {std::move(ResultPipeline)}; } -bool PassBuilder::parseModulePass(ModulePassManager &MPM, - const PipelineElement &E, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseModulePass(ModulePassManager &MPM, + const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1393,50 +1522,56 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM, if (!InnerPipeline.empty()) { if (Name == "module") { ModulePassManager NestedMPM(DebugLogging); - if (!parseModulePassPipeline(NestedMPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; MPM.addPass(std::move(NestedMPM)); - return true; + return Error::success(); } if (Name == "cgscc") { CGSCCPassManager CGPM(DebugLogging); - if (!parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return Err; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); - return true; + return Error::success(); } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (!parseFunctionPassPipeline(FPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - return true; + return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { ModulePassManager NestedMPM(DebugLogging); - if (!parseModulePassPipeline(NestedMPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM))); - return true; + return Error::success(); } for (auto &C : ModulePipelineParsingCallbacks) if (C(Name, MPM, InnerPipeline)) - return true; + return Error::success(); // Normal passes can't have pipelines. - return false; + return make_error<StringError>( + formatv("invalid use of '{0}' pass as module pipeline", Name).str(), + inconvertibleErrorCode()); + ; } // Manually handle aliases for pre-configured pipeline fragments. if (startsWithDefaultPipelineAliasPrefix(Name)) { SmallVector<StringRef, 3> Matches; if (!DefaultAliasRegex.match(Name, &Matches)) - return false; + return make_error<StringError>( + formatv("unknown default pipeline alias '{0}'", Name).str(), + inconvertibleErrorCode()); + assert(Matches.size() == 3 && "Must capture two matched strings!"); OptimizationLevel L = StringSwitch<OptimizationLevel>(Matches[2]) @@ -1448,7 +1583,7 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM, .Case("Oz", Oz); if (L == O0) // At O0 we do nothing at all! - return true; + return Error::success(); if (Matches[1] == "default") { MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging)); @@ -1462,38 +1597,40 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM, assert(Matches[1] == "lto" && "Not one of the matched options!"); MPM.addPass(buildLTODefaultPipeline(L, DebugLogging, nullptr)); } - return true; + return Error::success(); } // Finally expand the basic registered passes from the .inc file. #define MODULE_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ MPM.addPass(CREATE_PASS); \ - return true; \ + return Error::success(); \ } #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ MPM.addPass( \ RequireAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type, Module>()); \ - return true; \ + return Error::success(); \ } \ if (Name == "invalidate<" NAME ">") { \ MPM.addPass(InvalidateAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type>()); \ - return true; \ + return Error::success(); \ } #include "PassRegistry.def" for (auto &C : ModulePipelineParsingCallbacks) if (C(Name, MPM, InnerPipeline)) - return true; - return false; + return Error::success(); + return make_error<StringError>( + formatv("unknown module pass '{0}'", Name).str(), + inconvertibleErrorCode()); } -bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, - const PipelineElement &E, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, + const PipelineElement &E, bool VerifyEachPass, + bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1501,53 +1638,55 @@ bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, if (!InnerPipeline.empty()) { if (Name == "cgscc") { CGSCCPassManager NestedCGPM(DebugLogging); - if (!parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(std::move(NestedCGPM)); - return true; + return Error::success(); } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (!parseFunctionPassPipeline(FPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); - return true; + return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (!parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; CGPM.addPass(createRepeatedPass(*Count, std::move(NestedCGPM))); - return true; + return Error::success(); } if (auto MaxRepetitions = parseDevirtPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (!parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; CGPM.addPass( createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions)); - return true; + return Error::success(); } for (auto &C : CGSCCPipelineParsingCallbacks) if (C(Name, CGPM, InnerPipeline)) - return true; + return Error::success(); // Normal passes can't have pipelines. - return false; + return make_error<StringError>( + formatv("invalid use of '{0}' pass as cgscc pipeline", Name).str(), + inconvertibleErrorCode()); } // Now expand the basic registered passes from the .inc file. #define CGSCC_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ CGPM.addPass(CREATE_PASS); \ - return true; \ + return Error::success(); \ } #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ @@ -1555,24 +1694,26 @@ bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, std::remove_reference<decltype(CREATE_PASS)>::type, \ LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \ CGSCCUpdateResult &>()); \ - return true; \ + return Error::success(); \ } \ if (Name == "invalidate<" NAME ">") { \ CGPM.addPass(InvalidateAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type>()); \ - return true; \ + return Error::success(); \ } #include "PassRegistry.def" for (auto &C : CGSCCPipelineParsingCallbacks) if (C(Name, CGPM, InnerPipeline)) - return true; - return false; + return Error::success(); + return make_error<StringError>( + formatv("unknown cgscc pass '{0}'", Name).str(), + inconvertibleErrorCode()); } -bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM, - const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, + const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1580,68 +1721,80 @@ bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM, if (!InnerPipeline.empty()) { if (Name == "function") { FunctionPassManager NestedFPM(DebugLogging); - if (!parseFunctionPassPipeline(NestedFPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; // Add the nested pass manager with the appropriate adaptor. FPM.addPass(std::move(NestedFPM)); - return true; + return Error::success(); } if (Name == "loop") { LoopPassManager LPM(DebugLogging); - if (!parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass, + DebugLogging)) + return Err; // Add the nested pass manager with the appropriate adaptor. FPM.addPass( createFunctionToLoopPassAdaptor(std::move(LPM), DebugLogging)); - return true; + return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { FunctionPassManager NestedFPM(DebugLogging); - if (!parseFunctionPassPipeline(NestedFPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM))); - return true; + return Error::success(); } for (auto &C : FunctionPipelineParsingCallbacks) if (C(Name, FPM, InnerPipeline)) - return true; + return Error::success(); // Normal passes can't have pipelines. - return false; + return make_error<StringError>( + formatv("invalid use of '{0}' pass as function pipeline", Name).str(), + inconvertibleErrorCode()); } // Now expand the basic registered passes from the .inc file. #define FUNCTION_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ FPM.addPass(CREATE_PASS); \ - return true; \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + FPM.addPass(CREATE_PASS(Params.get())); \ + return Error::success(); \ } #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ FPM.addPass( \ RequireAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type, Function>()); \ - return true; \ + return Error::success(); \ } \ if (Name == "invalidate<" NAME ">") { \ FPM.addPass(InvalidateAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type>()); \ - return true; \ + return Error::success(); \ } #include "PassRegistry.def" for (auto &C : FunctionPipelineParsingCallbacks) if (C(Name, FPM, InnerPipeline)) - return true; - return false; + return Error::success(); + return make_error<StringError>( + formatv("unknown function pass '{0}'", Name).str(), + inconvertibleErrorCode()); } -bool PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) { StringRef Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1649,35 +1802,37 @@ bool PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, if (!InnerPipeline.empty()) { if (Name == "loop") { LoopPassManager NestedLPM(DebugLogging); - if (!parseLoopPassPipeline(NestedLPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; // Add the nested pass manager with the appropriate adaptor. LPM.addPass(std::move(NestedLPM)); - return true; + return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { LoopPassManager NestedLPM(DebugLogging); - if (!parseLoopPassPipeline(NestedLPM, InnerPipeline, VerifyEachPass, - DebugLogging)) - return false; + if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, + VerifyEachPass, DebugLogging)) + return Err; LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM))); - return true; + return Error::success(); } for (auto &C : LoopPipelineParsingCallbacks) if (C(Name, LPM, InnerPipeline)) - return true; + return Error::success(); // Normal passes can't have pipelines. - return false; + return make_error<StringError>( + formatv("invalid use of '{0}' pass as loop pipeline", Name).str(), + inconvertibleErrorCode()); } // Now expand the basic registered passes from the .inc file. #define LOOP_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ LPM.addPass(CREATE_PASS); \ - return true; \ + return Error::success(); \ } #define LOOP_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ @@ -1685,19 +1840,20 @@ bool PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, std::remove_reference<decltype(CREATE_PASS)>::type, Loop, \ LoopAnalysisManager, LoopStandardAnalysisResults &, \ LPMUpdater &>()); \ - return true; \ + return Error::success(); \ } \ if (Name == "invalidate<" NAME ">") { \ LPM.addPass(InvalidateAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type>()); \ - return true; \ + return Error::success(); \ } #include "PassRegistry.def" for (auto &C : LoopPipelineParsingCallbacks) if (C(Name, LPM, InnerPipeline)) - return true; - return false; + return Error::success(); + return make_error<StringError>(formatv("unknown loop pass '{0}'", Name).str(), + inconvertibleErrorCode()); } bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) { @@ -1721,41 +1877,42 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) { return false; } -bool PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM, + ArrayRef<PipelineElement> Pipeline, + bool VerifyEachPass, + bool DebugLogging) { for (const auto &Element : Pipeline) { - if (!parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging)) - return false; + if (auto Err = parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging)) + return Err; // FIXME: No verifier support for Loop passes! } - return true; + return Error::success(); } -bool PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, + ArrayRef<PipelineElement> Pipeline, + bool VerifyEachPass, + bool DebugLogging) { for (const auto &Element : Pipeline) { - if (!parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging)) - return false; + if (auto Err = + parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging)) + return Err; if (VerifyEachPass) FPM.addPass(VerifierPass()); } - return true; + return Error::success(); } -bool PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, + ArrayRef<PipelineElement> Pipeline, + bool VerifyEachPass, + bool DebugLogging) { for (const auto &Element : Pipeline) { - if (!parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging)) - return false; + if (auto Err = parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging)) + return Err; // FIXME: No verifier support for CGSCC passes! } - return true; + return Error::success(); } void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, @@ -1771,28 +1928,30 @@ void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); }); } -bool PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, + ArrayRef<PipelineElement> Pipeline, + bool VerifyEachPass, + bool DebugLogging) { for (const auto &Element : Pipeline) { - if (!parseModulePass(MPM, Element, VerifyEachPass, DebugLogging)) - return false; + if (auto Err = parseModulePass(MPM, Element, VerifyEachPass, DebugLogging)) + return Err; if (VerifyEachPass) MPM.addPass(VerifierPass()); } - return true; + return Error::success(); } // 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, - StringRef PipelineText, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, + StringRef PipelineText, + bool VerifyEachPass, bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) - return false; + return make_error<StringError>( + formatv("invalid pipeline '{0}'", PipelineText).str(), + inconvertibleErrorCode()); // If the first name isn't at the module layer, wrap the pipeline up // automatically. @@ -1809,73 +1968,106 @@ bool PassBuilder::parsePassPipeline(ModulePassManager &MPM, } else { for (auto &C : TopLevelPipelineParsingCallbacks) if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging)) - return true; - - // Unknown pass name! - return false; + return Error::success(); + + // Unknown pass or pipeline name! + auto &InnerPipeline = Pipeline->front().InnerPipeline; + return make_error<StringError>( + formatv("unknown {0} name '{1}'", + (InnerPipeline.empty() ? "pass" : "pipeline"), FirstName) + .str(), + inconvertibleErrorCode()); } } - return parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging); + if (auto Err = + parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + return Err; + return Error::success(); } // Primary pass pipeline description parsing routine for a \c CGSCCPassManager -bool PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, - StringRef PipelineText, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, + StringRef PipelineText, + bool VerifyEachPass, bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) - return false; + return make_error<StringError>( + formatv("invalid pipeline '{0}'", PipelineText).str(), + inconvertibleErrorCode()); StringRef FirstName = Pipeline->front().Name; if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) - return false; - - return parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging); + return make_error<StringError>( + formatv("unknown cgscc pass '{0}' in pipeline '{1}'", FirstName, + PipelineText) + .str(), + inconvertibleErrorCode()); + + if (auto Err = + parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + return Err; + return Error::success(); } // Primary pass pipeline description parsing routine for a \c // FunctionPassManager -bool PassBuilder::parsePassPipeline(FunctionPassManager &FPM, - StringRef PipelineText, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, + StringRef PipelineText, + bool VerifyEachPass, bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) - return false; + return make_error<StringError>( + formatv("invalid pipeline '{0}'", PipelineText).str(), + inconvertibleErrorCode()); StringRef FirstName = Pipeline->front().Name; if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks)) - return false; - - return parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass, - DebugLogging); + return make_error<StringError>( + formatv("unknown function pass '{0}' in pipeline '{1}'", FirstName, + PipelineText) + .str(), + inconvertibleErrorCode()); + + if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass, + DebugLogging)) + return Err; + return Error::success(); } // Primary pass pipeline description parsing routine for a \c LoopPassManager -bool PassBuilder::parsePassPipeline(LoopPassManager &CGPM, - StringRef PipelineText, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM, + StringRef PipelineText, + bool VerifyEachPass, bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) - return false; + return make_error<StringError>( + formatv("invalid pipeline '{0}'", PipelineText).str(), + inconvertibleErrorCode()); + + if (auto Err = + parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + return Err; - return parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging); + return Error::success(); } -bool PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { +Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { // If the pipeline just consists of the word 'default' just replace the AA // manager with our default one. if (PipelineText == "default") { AA = buildDefaultAAPipeline(); - return true; + return Error::success(); } while (!PipelineText.empty()) { StringRef Name; std::tie(Name, PipelineText) = PipelineText.split(','); if (!parseAAPassName(AA, Name)) - return false; + return make_error<StringError>( + formatv("unknown alias analysis name '{0}'", Name).str(), + inconvertibleErrorCode()); } - return true; + return Error::success(); } |
