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 eb04dcc8b6ef2..5ec94ea6f40ab 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();  }  | 
