diff options
Diffstat (limited to 'llvm/lib/Passes/PassBuilder.cpp')
| -rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 491 |
1 files changed, 247 insertions, 244 deletions
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) { |

