if (Name.startswith("default") || Name.startswith("lto"))
return DefaultAliasRegex.match(Name);
+ // Explicitly handle pass manager names.
+ if (Name == "module")
+ return true;
+ if (Name == "cgscc")
+ return true;
+ if (Name == "function")
+ return true;
+
#define MODULE_PASS(NAME, CREATE_PASS) \
if (Name == NAME) \
return true;
#endif
static bool isCGSCCPassName(StringRef Name) {
+ // Explicitly handle pass manager names.
+ if (Name == "cgscc")
+ return true;
+ if (Name == "function")
+ return true;
+
#define CGSCC_PASS(NAME, CREATE_PASS) \
if (Name == NAME) \
return true;
}
static bool isFunctionPassName(StringRef Name) {
+ // Explicitly handle pass manager names.
+ if (Name == "function")
+ return true;
+ if (Name == "loop")
+ return true;
+
#define FUNCTION_PASS(NAME, CREATE_PASS) \
if (Name == NAME) \
return true;
}
static bool isLoopPassName(StringRef Name) {
+ // Explicitly handle pass manager names.
+ if (Name == "loop")
+ return true;
+
#define LOOP_PASS(NAME, CREATE_PASS) \
if (Name == NAME) \
return true;
return false;
}
-bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name,
- bool DebugLogging) {
+Optional<std::vector<PassBuilder::PipelineElement>>
+PassBuilder::parsePipelineText(StringRef Text) {
+ std::vector<PipelineElement> ResultPipeline;
+
+ SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {
+ &ResultPipeline};
+ for (;;) {
+ std::vector<PipelineElement> &Pipeline = *PipelineStack.back();
+ size_t Pos = Text.find_first_of(",()");
+ Pipeline.push_back({Text.substr(0, Pos), {}});
+
+ // If we have a single terminating name, we're done.
+ if (Pos == Text.npos)
+ break;
+
+ char Sep = Text[Pos];
+ Text = Text.substr(Pos + 1);
+ if (Sep == ',')
+ // Just a name ending in a comma, continue.
+ continue;
+
+ if (Sep == '(') {
+ // Push the inner pipeline onto the stack to continue processing.
+ PipelineStack.push_back(&Pipeline.back().InnerPipeline);
+ continue;
+ }
+
+ assert(Sep == ')' && "Bogus separator!");
+ // When handling the close parenthesis, we greedily consume them to avoid
+ // empty strings in the pipeline.
+ do {
+ // If we try to pop the outer pipeline we have unbalanced parentheses.
+ if (PipelineStack.size() == 1)
+ return None;
+
+ PipelineStack.pop_back();
+ } while (Text.consume_front(")"));
+
+ // Check if we've finished parsing.
+ if (Text.empty())
+ break;
+
+ // Otherwise, the end of an inner pipeline always has to be followed by
+ // a comma, and then we can continue.
+ if (!Text.consume_front(","))
+ return None;
+ }
+
+ if (PipelineStack.size() > 1)
+ // Unbalanced paretheses.
+ return None;
+
+ assert(PipelineStack.back() == &ResultPipeline &&
+ "Wrong pipeline at the bottom of the stack!");
+ return {std::move(ResultPipeline)};
+}
+
+bool PassBuilder::parseModulePass(ModulePassManager &MPM,
+ const PipelineElement &E, bool VerifyEachPass,
+ bool DebugLogging) {
+ auto &Name = E.Name;
+ auto &InnerPipeline = E.InnerPipeline;
+
+ // First handle complex passes like the pass managers which carry pipelines.
+ if (!InnerPipeline.empty()) {
+ if (Name == "module") {
+ ModulePassManager NestedMPM(DebugLogging);
+ if (!parseModulePassPipeline(NestedMPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ MPM.addPass(std::move(NestedMPM));
+ return true;
+ }
+ if (Name == "cgscc") {
+ CGSCCPassManager CGPM(DebugLogging);
+ if (!parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM),
+ DebugLogging));
+ return true;
+ }
+ if (Name == "function") {
+ FunctionPassManager FPM(DebugLogging);
+ if (!parseFunctionPassPipeline(FPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ return true;
+ }
+ // Normal passes can't have pipelines.
+ return false;
+ }
+
// Manually handle aliases for pre-configured pipeline fragments.
if (Name.startswith("default") || Name.startswith("lto")) {
SmallVector<StringRef, 3> Matches;
return true;
}
+ // Finally expand the basic registered passes from the .inc file.
#define MODULE_PASS(NAME, CREATE_PASS) \
if (Name == NAME) { \
MPM.addPass(CREATE_PASS); \
return false;
}
-bool PassBuilder::parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
+bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,
+ const PipelineElement &E, bool VerifyEachPass,
+ bool DebugLogging) {
+ auto &Name = E.Name;
+ auto &InnerPipeline = E.InnerPipeline;
+
+ // First handle complex passes like the pass managers which carry pipelines.
+ if (!InnerPipeline.empty()) {
+ if (Name == "cgscc") {
+ CGSCCPassManager NestedCGPM(DebugLogging);
+ if (!parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ // Add the nested pass manager with the appropriate adaptor.
+ CGPM.addPass(std::move(NestedCGPM));
+ return true;
+ }
+ if (Name == "function") {
+ FunctionPassManager FPM(DebugLogging);
+ if (!parseFunctionPassPipeline(FPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ // Add the nested pass manager with the appropriate adaptor.
+ CGPM.addPass(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM), DebugLogging));
+ return true;
+ }
+ // Normal passes can't have pipelines.
+ return false;
+ }
+
+ // Now expand the basic registered passes from the .inc file.
#define CGSCC_PASS(NAME, CREATE_PASS) \
if (Name == NAME) { \
CGPM.addPass(CREATE_PASS); \
return false;
}
-bool PassBuilder::parseFunctionPassName(FunctionPassManager &FPM,
- StringRef Name) {
+bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
+ const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging) {
+ auto &Name = E.Name;
+ auto &InnerPipeline = E.InnerPipeline;
+
+ // First handle complex passes like the pass managers which carry pipelines.
+ if (!InnerPipeline.empty()) {
+ if (Name == "function") {
+ FunctionPassManager NestedFPM(DebugLogging);
+ if (!parseFunctionPassPipeline(NestedFPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ // Add the nested pass manager with the appropriate adaptor.
+ FPM.addPass(std::move(NestedFPM));
+ return true;
+ }
+ if (Name == "loop") {
+ LoopPassManager LPM(DebugLogging);
+ if (!parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ // Add the nested pass manager with the appropriate adaptor.
+ FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM)));
+ return true;
+ }
+ // Normal passes can't have pipelines.
+ return false;
+ }
+
+ // Now expand the basic registered passes from the .inc file.
#define FUNCTION_PASS(NAME, CREATE_PASS) \
if (Name == NAME) { \
FPM.addPass(CREATE_PASS); \
return false;
}
-bool PassBuilder::parseLoopPassName(LoopPassManager &FPM, StringRef Name) {
+bool PassBuilder::parseLoopPass(LoopPassManager &FPM, const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging) {
+ auto &Name = E.Name;
+ auto &InnerPipeline = E.InnerPipeline;
+
+ // First handle complex passes like the pass managers which carry pipelines.
+ if (!InnerPipeline.empty()) {
+ if (Name == "loop") {
+ LoopPassManager NestedLPM(DebugLogging);
+ if (!parseLoopPassPipeline(NestedLPM, InnerPipeline, VerifyEachPass,
+ DebugLogging))
+ return false;
+ // Add the nested pass manager with the appropriate adaptor.
+ FPM.addPass(std::move(NestedLPM));
+ return true;
+ }
+ // Normal passes can't have pipelines.
+ return false;
+ }
+
+ // Now expand the basic registered passes from the .inc file.
#define LOOP_PASS(NAME, CREATE_PASS) \
if (Name == NAME) { \
FPM.addPass(CREATE_PASS); \
}
bool PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
- StringRef &PipelineText,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass,
bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("loop(")) {
- LoopPassManager NestedLPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("loop("));
- if (!parseLoopPassPipeline(NestedLPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- LPM.addPass(std::move(NestedLPM));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseLoopPassName(LPM, PipelineText.substr(0, End)))
- return false;
- // TODO: Ideally, we would run a LoopVerifierPass() here in the
- // VerifyEachPass case, but we don't have such a verifier yet.
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
+ for (const auto &Element : Pipeline) {
+ if (!parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging))
+ return false;
+ // FIXME: No verifier support for Loop passes!
}
+ return true;
}
bool PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM,
- StringRef &PipelineText,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass,
bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- FPM.addPass(std::move(NestedFPM));
- } else if (PipelineText.startswith("loop(")) {
- LoopPassManager NestedLPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("loop("));
- if (!parseLoopPassPipeline(NestedLPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- FPM.addPass(createFunctionToLoopPassAdaptor(std::move(NestedLPM)));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
- return false;
- if (VerifyEachPass)
- FPM.addPass(VerifierPass());
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
+ for (const auto &Element : Pipeline) {
+ if (!parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging))
+ return false;
+ if (VerifyEachPass)
+ FPM.addPass(VerifierPass());
}
+ return true;
}
bool PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
- StringRef &PipelineText,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass,
bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM(DebugLogging);
-
- // Parse the inner pipeline into the nested manager.
- PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- CGPM.addPass(std::move(NestedCGPM));
- } else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- CGPM.addPass(
- createCGSCCToFunctionPassAdaptor(std::move(NestedFPM), DebugLogging));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End)))
- return false;
- // FIXME: No verifier support for CGSCC passes!
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
+ for (const auto &Element : Pipeline) {
+ if (!parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging))
+ return false;
+ // FIXME: No verifier support for CGSCC passes!
}
+ return true;
}
void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
}
bool PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
- StringRef &PipelineText,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass,
bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("module(")) {
- ModulePassManager NestedMPM(DebugLogging);
-
- // Parse the inner pipeline into the nested manager.
- PipelineText = PipelineText.substr(strlen("module("));
- if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Now add the nested manager as a module pass.
- MPM.addPass(std::move(NestedMPM));
- } else if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM),
- DebugLogging));
- } else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseModulePassName(MPM, PipelineText.substr(0, End), DebugLogging))
- return false;
- if (VerifyEachPass)
- MPM.addPass(VerifierPass());
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
+ for (const auto &Element : Pipeline) {
+ if (!parseModulePass(MPM, Element, VerifyEachPass, DebugLogging))
+ return false;
+ if (VerifyEachPass)
+ MPM.addPass(VerifierPass());
}
+ return true;
}
// Primary pass pipeline description parsing routine.
bool PassBuilder::parsePassPipeline(ModulePassManager &MPM,
StringRef PipelineText, bool VerifyEachPass,
bool DebugLogging) {
- // By default, try to parse the pipeline as-if it were within an implicit
- // 'module(...)' pass pipeline. If this will parse at all, it needs to
- // consume the entire string.
- if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging))
- return PipelineText.empty();
-
- // This isn't parsable as a module pipeline, look for the end of a pass name
- // and directly drop down to that layer.
- StringRef FirstName =
- PipelineText.substr(0, PipelineText.find_first_of(",)"));
- assert(!isModulePassName(FirstName) &&
- "Already handled all module pipeline options.");
-
- // If this looks like a CGSCC pass, parse the whole thing as a CGSCC
- // pipeline.
- if (PipelineText.startswith("cgscc(") || isCGSCCPassName(FirstName)) {
- CGSCCPassManager CGPM(DebugLogging);
- if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- !PipelineText.empty())
+ auto Pipeline = parsePipelineText(PipelineText);
+ if (!Pipeline || Pipeline->empty())
+ return false;
+
+ // If the first name isn't at the module layer, wrap the pipeline up
+ // automatically.
+ StringRef FirstName = Pipeline->front().Name;
+
+ if (!isModulePassName(FirstName)) {
+ if (isCGSCCPassName(FirstName))
+ Pipeline = {{"cgscc", std::move(*Pipeline)}};
+ else if (isFunctionPassName(FirstName))
+ Pipeline = {{"function", std::move(*Pipeline)}};
+ else if (isLoopPassName(FirstName))
+ Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}};
+ else
+ // Unknown pass name!
return false;
- MPM.addPass(
- createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM), DebugLogging));
- return true;
- }
-
- // Similarly, if this looks like a Function pass, parse the whole thing as
- // a Function pipelien.
- if (PipelineText.startswith("function(") || isFunctionPassName(FirstName)) {
- FunctionPassManager FPM(DebugLogging);
- if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- !PipelineText.empty())
- return false;
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- return true;
}
- // If this looks like a Loop pass, parse the whole thing as a Loop pipeline.
- if (PipelineText.startswith("loop(") || isLoopPassName(FirstName)) {
- LoopPassManager LPM(DebugLogging);
- if (!parseLoopPassPipeline(LPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- !PipelineText.empty())
- return false;
- FunctionPassManager FPM(DebugLogging);
- FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM)));
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- return true;
- }
-
- return false;
+ return parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging);
}
bool PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {