aboutsummaryrefslogtreecommitdiff
path: root/lib/Passes/PassBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Passes/PassBuilder.cpp')
-rw-r--r--lib/Passes/PassBuilder.cpp512
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();
}