// Primary pass pipeline description parsing routine. // FIXME: Should this routine accept a TargetMachine or require the caller to // pre-populate the analysis managers with target-specific stuff? bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, bool VerifyEachPass) { // Look at the first entry to figure out which layer to start parsing at. if (PipelineText.startswith("module(")) return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && PipelineText.empty(); if (PipelineText.startswith("function(")) { FunctionPassManager FPM; if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || !PipelineText.empty()) return false; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); return true; } // This isn't a direct pass manager name, look for the end of a pass name. StringRef FirstName = PipelineText.substr(0, PipelineText.find_first_of(",)")); if (isModulePassName(FirstName)) return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && PipelineText.empty(); if (isFunctionPassName(FirstName)) { FunctionPassManager FPM; if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || !PipelineText.empty()) return false; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); return true; } return false; }
// Primary pass pipeline description parsing routine. // 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) { // 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()) return false; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 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; }
static bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, bool VerifyEachPass) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("module(")) { ModulePassManager NestedMPM; // Parse the inner pipeline into the nested manager. PipelineText = PipelineText.substr(strlen("module(")); if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) || 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("function(")) { FunctionPassManager NestedFPM; // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || 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))) 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); } }
static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { if (Name == "no-op-module") { MPM.addPass(NoOpModulePass()); return true; } if (Name == "print") { MPM.addPass(PrintModulePass(dbgs())); return true; } if (Name == "print-cg") { MPM.addPass(LazyCallGraphPrinterPass(dbgs())); return true; } return false; }
void PassBuilder::addLTODefaultPipeline(ModulePassManager &MPM, OptimizationLevel Level, bool DebugLogging) { // FIXME: Finish fleshing this out to match the legacy LTO pipelines. FunctionPassManager LateFPM(DebugLogging); LateFPM.addPass(InstCombinePass()); LateFPM.addPass(SimplifyCFGPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM))); }
static void runNewCustomLtoPasses(Module &M, TargetMachine &TM) { PassBuilder PB(&TM); AAManager AA; // Parse a custom AA pipeline if asked to. if (!PB.parseAAPipeline(AA, Config->LtoAAPipeline)) { error("Unable to parse AA pipeline description: " + Config->LtoAAPipeline); return; } LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; // Register the AA manager first so that our version is the one used. FAM.registerPass([&] { return std::move(AA); }); // Register all the basic analyses with the managers. PB.registerModuleAnalyses(MAM); PB.registerCGSCCAnalyses(CGAM); PB.registerFunctionAnalyses(FAM); PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); ModulePassManager MPM; if (!Config->DisableVerify) MPM.addPass(VerifierPass()); // Now, add all the passes we've been requested to. if (!PB.parsePassPipeline(MPM, Config->LtoNewPmPasses)) { error("unable to parse pass pipeline description: " + Config->LtoNewPmPasses); return; } if (!Config->DisableVerify) MPM.addPass(VerifierPass()); MPM.run(M, MAM); }
bool 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 (VerifyEachPass) MPM.addPass(VerifierPass()); } return true; }
void PassBuilder::addPerModuleDefaultPipeline(ModulePassManager &MPM, OptimizationLevel Level, bool DebugLogging) { // FIXME: Finish fleshing this out to match the legacy pipelines. FunctionPassManager EarlyFPM(DebugLogging); EarlyFPM.addPass(SimplifyCFGPass()); EarlyFPM.addPass(SROA()); EarlyFPM.addPass(EarlyCSEPass()); EarlyFPM.addPass(LowerExpectIntrinsicPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM))); }
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, tool_output_file *Out, StringRef PassPipeline, OutputKind OK, VerifierKind VK) { FunctionAnalysisManager FAM; ModuleAnalysisManager MAM; // FIXME: Lift this registration of analysis passes into a .def file adjacent // to the one used to associate names with passes. MAM.registerPass(LazyCallGraphAnalysis()); // Cross register the analysis managers through their proxies. MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); ModulePassManager MPM; if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) { errs() << Arg0 << ": unable to parse pass pipeline description.\n"; return false; } if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); // Add any relevant output pass at the end of the pipeline. switch (OK) { case OK_NoOutput: break; // No output pass needed. case OK_OutputAssembly: MPM.addPass(PrintModulePass(Out->os())); break; case OK_OutputBitcode: MPM.addPass(BitcodeWriterPass(Out->os())); break; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. MPM.run(&M, &MAM); // Declare success. if (OK != OK_NoOutput) Out->keep(); return true; }
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; } if (auto Count = parseRepeatPassName(Name)) { ModulePassManager NestedMPM(DebugLogging); if (!parseModulePassPipeline(NestedMPM, InnerPipeline, VerifyEachPass, DebugLogging)) return false; MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM))); 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; if (!DefaultAliasRegex.match(Name, &Matches)) return false; assert(Matches.size() == 3 && "Must capture two matched strings!"); OptimizationLevel L = StringSwitch<OptimizationLevel>(Matches[2]) .Case("O0", O0) .Case("O1", O1) .Case("O2", O2) .Case("O3", O3) .Case("Os", Os) .Case("Oz", Oz); if (L == O0) // At O0 we do nothing at all! return true; if (Matches[1] == "default") { MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging)); } else if (Matches[1] == "lto-pre-link") { MPM.addPass(buildLTOPreLinkDefaultPipeline(L, DebugLogging)); } else { assert(Matches[1] == "lto" && "Not one of the matched options!"); MPM.addPass(buildLTODefaultPipeline(L, DebugLogging)); } 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 true; \ } #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ MPM.addPass( \ RequireAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type, Module>()); \ return true; \ } \ if (Name == "invalidate<" NAME ">") { \ MPM.addPass(InvalidateAnalysisPass< \ std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return true; \ } #include "PassRegistry.def" return false; }
/// A clean version of `EmitAssembly` that uses the new pass manager. /// /// Not all features are currently supported in this system, but where /// necessary it falls back to the legacy pass manager to at least provide /// basic functionality. /// /// This API is planned to have its functionality finished and then to replace /// `EmitAssembly` at some point in the future when the default switches. void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) { TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); setCommandLineOpts(); // The new pass manager always makes a target machine available to passes // during construction. CreateTargetMachine(/*MustCreateTM*/ true); if (!TM) // This will already be diagnosed, just bail. return; TheModule->setDataLayout(TM->createDataLayout()); PassBuilder PB(TM.get()); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; // Register the AA manager first so that our version is the one used. FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); // Register all the basic analyses with the managers. PB.registerModuleAnalyses(MAM); PB.registerCGSCCAnalyses(CGAM); PB.registerFunctionAnalyses(FAM); PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); ModulePassManager MPM; if (!CodeGenOpts.DisableLLVMPasses) { if (CodeGenOpts.OptimizationLevel == 0) { // Build a minimal pipeline based on the semantics required by Clang, // which is just that always inlining occurs. MPM.addPass(AlwaysInlinerPass()); } else { // Otherwise, use the default pass pipeline. We also have to map our // optimization levels into one of the distinct levels used to configure // the pipeline. PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); MPM = PB.buildPerModuleDefaultPipeline(Level); } } // FIXME: We still use the legacy pass manager to do code generation. We // create that pass manager here and use it as needed below. legacy::PassManager CodeGenPasses; bool NeedCodeGen = false; // Append any output we need to the pass manager. switch (Action) { case Backend_EmitNothing: break; case Backend_EmitBC: MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, CodeGenOpts.EmitSummaryIndex, CodeGenOpts.EmitSummaryIndex)); break; case Backend_EmitLL: MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists)); break; case Backend_EmitAssembly: case Backend_EmitMCNull: case Backend_EmitObj: NeedCodeGen = true; CodeGenPasses.add( createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); if (!AddEmitPasses(CodeGenPasses, Action, *OS)) // FIXME: Should we handle this error differently? return; break; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. { PrettyStackTraceString CrashInfo("Optimizer"); MPM.run(*TheModule, MAM); } // Now if needed, run the legacy PM for codegen. if (NeedCodeGen) { PrettyStackTraceString CrashInfo("Code generation"); CodeGenPasses.run(*TheModule); } }