summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Passes/PassBuilder.h38
-rw-r--r--llvm/lib/Passes/PassBuilder.cpp491
-rw-r--r--llvm/test/Other/pass-pipeline-parsing.ll34
-rw-r--r--llvm/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll2
4 files changed, 310 insertions, 255 deletions
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 9f0a9c6e138..3ed4cc4685c 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -16,9 +16,11 @@
#ifndef LLVM_PASSES_PASSBUILDER_H
#define LLVM_PASSES_PASSBUILDER_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/IR/PassManager.h"
+#include <vector>
namespace llvm {
class StringRef;
@@ -242,20 +244,36 @@ public:
bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
private:
- bool parseModulePassName(ModulePassManager &MPM, StringRef Name,
- bool DebugLogging);
- bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name);
- bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name);
- bool parseLoopPassName(LoopPassManager &LPM, StringRef Name);
+ /// A struct to capture parsed pass pipeline names.
+ struct PipelineElement {
+ StringRef Name;
+ std::vector<PipelineElement> InnerPipeline;
+ };
+
+ static Optional<std::vector<PipelineElement>>
+ parsePipelineText(StringRef Text);
+
+ bool parseModulePass(ModulePassManager &MPM, const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging);
+ bool parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging);
+ bool parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging);
+ bool parseLoopPass(LoopPassManager &LPM, const PipelineElement &E,
+ bool VerifyEachPass, bool DebugLogging);
bool parseAAPassName(AAManager &AA, StringRef Name);
- bool parseLoopPassPipeline(LoopPassManager &LPM, StringRef &PipelineText,
+
+ bool parseLoopPassPipeline(LoopPassManager &LPM,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass, bool DebugLogging);
bool parseFunctionPassPipeline(FunctionPassManager &FPM,
- StringRef &PipelineText, bool VerifyEachPass,
- bool DebugLogging);
- bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, StringRef &PipelineText,
+ ArrayRef<PipelineElement> Pipeline,
+ bool VerifyEachPass, bool DebugLogging);
+ bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass, bool DebugLogging);
- bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText,
+ bool parseModulePassPipeline(ModulePassManager &MPM,
+ ArrayRef<PipelineElement> Pipeline,
bool VerifyEachPass, bool DebugLogging);
};
}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 6b994ff5b60..3bdbb199779 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -280,6 +280,14 @@ static bool isModulePassName(StringRef Name) {
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;
@@ -293,6 +301,12 @@ static bool isModulePassName(StringRef Name) {
#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;
@@ -305,6 +319,12 @@ static bool isCGSCCPassName(StringRef Name) {
}
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;
@@ -317,6 +337,10 @@ static bool isFunctionPassName(StringRef Name) {
}
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;
@@ -328,8 +352,100 @@ static bool isLoopPassName(StringRef Name) {
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;
@@ -356,6 +472,7 @@ bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name,
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); \
@@ -377,7 +494,38 @@ bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name,
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); \
@@ -399,8 +547,37 @@ bool PassBuilder::parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
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); \
@@ -422,7 +599,27 @@ bool PassBuilder::parseFunctionPassName(FunctionPassManager &FPM,
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); \
@@ -463,148 +660,40 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
}
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,
@@ -622,71 +711,16 @@ 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.
@@ -695,58 +729,27 @@ bool PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
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) {
diff --git a/llvm/test/Other/pass-pipeline-parsing.ll b/llvm/test/Other/pass-pipeline-parsing.ll
index 54b09e511f5..a1b9ebb57ad 100644
--- a/llvm/test/Other/pass-pipeline-parsing.ll
+++ b/llvm/test/Other/pass-pipeline-parsing.ll
@@ -173,6 +173,40 @@
; CHECK-NESTED-FP-LP: Finished llvm::Function pass manager run
; CHECK-NESTED-FP-LP: Finished llvm::Module pass manager run
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='function(no-op-function)function(no-op-function)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-MISSING-COMMA1
+; CHECK-MISSING-COMMA1: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='function()' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-EMPTY-INNER-PIPELINE
+; CHECK-EMPTY-INNER-PIPELINE: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='no-op-module(no-op-module,whatever)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-MODULE-PASS
+; CHECK-PIPELINE-ON-MODULE-PASS: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='no-op-cgscc(no-op-cgscc,whatever)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-CGSCC-PASS
+; CHECK-PIPELINE-ON-CGSCC-PASS: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='no-op-function(no-op-function,whatever)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-FUNCTION-PASS
+; CHECK-PIPELINE-ON-FUNCTION-PASS: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='no-op-loop(no-op-loop,whatever)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-PIPELINE-ON-LOOP-PASS
+; CHECK-PIPELINE-ON-LOOP-PASS: unable to parse pass pipeline description
+
+; RUN: not opt -disable-output -debug-pass-manager \
+; RUN: -passes='no-op-function()' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-EMPTY-PIPELINE-ON-PASS
+; CHECK-EMPTY-PIPELINE-ON-PASS: unable to parse pass pipeline description
define void @f() {
entry:
diff --git a/llvm/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll b/llvm/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll
index 315ae8df9fa..09f0e1aa2a0 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -analyze -iv-users | FileCheck %s
-; RUN: opt -passes='function(require<scalar-evolution>),print<ivusers>' -S < %s 2>&1| FileCheck %s
+; RUN: opt -passes='function(require<scalar-evolution>,loop(print<ivusers>))' -S < %s 2>&1| FileCheck %s
; Provide legal integer types.
target datalayout = "n8:16:32:64"
OpenPOWER on IntegriCloud