123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- //===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- ///
- /// This file is just a split of the code that logically belongs in opt.cpp but
- /// that includes the new pass manager headers.
- ///
- //===----------------------------------------------------------------------===//
- #include "NewPMDriver.h"
- #include "PassPrinters.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Analysis/AliasAnalysis.h"
- #include "llvm/Analysis/CGSCCPassManager.h"
- #include "llvm/Analysis/TargetLibraryInfo.h"
- #include "llvm/Bitcode/BitcodeWriterPass.h"
- #include "llvm/Config/llvm-config.h"
- #include "llvm/IR/Dominators.h"
- #include "llvm/IR/IRPrintingPasses.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/IR/Module.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/IR/Verifier.h"
- #include "llvm/Passes/PassBuilder.h"
- #include "llvm/Passes/PassPlugin.h"
- #include "llvm/Passes/StandardInstrumentations.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/ToolOutputFile.h"
- #include "llvm/Target/TargetMachine.h"
- #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
- #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
- #include "llvm/Transforms/Scalar/LoopPassManager.h"
- #include "llvm/Transforms/Utils/Debugify.h"
- using namespace llvm;
- using namespace opt_tool;
- namespace llvm {
- cl::opt<bool> DebugifyEach(
- "debugify-each",
- cl::desc("Start each pass with debugify and end it with check-debugify"));
- cl::opt<std::string>
- DebugifyExport("debugify-export",
- cl::desc("Export per-pass debugify statistics to this file"),
- cl::value_desc("filename"));
- } // namespace llvm
- enum class DebugLogging { None, Normal, Verbose, Quiet };
- static cl::opt<DebugLogging> DebugPM(
- "debug-pass-manager", cl::Hidden, cl::ValueOptional,
- cl::desc("Print pass management debugging information"),
- cl::init(DebugLogging::None),
- cl::values(
- clEnumValN(DebugLogging::Normal, "", ""),
- clEnumValN(DebugLogging::Quiet, "quiet",
- "Skip printing info about analyses"),
- clEnumValN(
- DebugLogging::Verbose, "verbose",
- "Print extra information about adaptors and pass managers")));
- static cl::list<std::string>
- PassPlugins("load-pass-plugin",
- cl::desc("Load passes from plugin library"));
- // This flag specifies a textual description of the alias analysis pipeline to
- // use when querying for aliasing information. It only works in concert with
- // the "passes" flag above.
- static cl::opt<std::string>
- AAPipeline("aa-pipeline",
- cl::desc("A textual description of the alias analysis "
- "pipeline for handling managed aliasing queries"),
- cl::Hidden, cl::init("default"));
- /// {{@ These options accept textual pipeline descriptions which will be
- /// inserted into default pipelines at the respective extension points
- static cl::opt<std::string> PeepholeEPPipeline(
- "passes-ep-peephole",
- cl::desc("A textual description of the function pass pipeline inserted at "
- "the Peephole extension points into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> LateLoopOptimizationsEPPipeline(
- "passes-ep-late-loop-optimizations",
- cl::desc(
- "A textual description of the loop pass pipeline inserted at "
- "the LateLoopOptimizations extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> LoopOptimizerEndEPPipeline(
- "passes-ep-loop-optimizer-end",
- cl::desc("A textual description of the loop pass pipeline inserted at "
- "the LoopOptimizerEnd extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> ScalarOptimizerLateEPPipeline(
- "passes-ep-scalar-optimizer-late",
- cl::desc("A textual description of the function pass pipeline inserted at "
- "the ScalarOptimizerLate extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> CGSCCOptimizerLateEPPipeline(
- "passes-ep-cgscc-optimizer-late",
- cl::desc("A textual description of the cgscc pass pipeline inserted at "
- "the CGSCCOptimizerLate extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> VectorizerStartEPPipeline(
- "passes-ep-vectorizer-start",
- cl::desc("A textual description of the function pass pipeline inserted at "
- "the VectorizerStart extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> PipelineStartEPPipeline(
- "passes-ep-pipeline-start",
- cl::desc("A textual description of the module pass pipeline inserted at "
- "the PipelineStart extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> PipelineEarlySimplificationEPPipeline(
- "passes-ep-pipeline-early-simplification",
- cl::desc("A textual description of the module pass pipeline inserted at "
- "the EarlySimplification extension point into default pipelines"),
- cl::Hidden);
- static cl::opt<std::string> OptimizerLastEPPipeline(
- "passes-ep-optimizer-last",
- cl::desc("A textual description of the module pass pipeline inserted at "
- "the OptimizerLast extension point into default pipelines"),
- cl::Hidden);
- // Individual pipeline tuning options.
- extern cl::opt<bool> DisableLoopUnrolling;
- namespace llvm {
- extern cl::opt<PGOKind> PGOKindFlag;
- extern cl::opt<std::string> ProfileFile;
- extern cl::opt<CSPGOKind> CSPGOKindFlag;
- extern cl::opt<std::string> CSProfileGenFile;
- extern cl::opt<bool> DisableBasicAA;
- extern cl::opt<bool> PrintPipelinePasses;
- } // namespace llvm
- static cl::opt<std::string>
- ProfileRemappingFile("profile-remapping-file",
- cl::desc("Path to the profile remapping file."),
- cl::Hidden);
- static cl::opt<bool> DebugInfoForProfiling(
- "new-pm-debug-info-for-profiling", cl::init(false), cl::Hidden,
- cl::desc("Emit special debug info to enable PGO profile generation."));
- static cl::opt<bool> PseudoProbeForProfiling(
- "new-pm-pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
- cl::desc("Emit pseudo probes to enable PGO profile generation."));
- /// @}}
- template <typename PassManagerT>
- bool tryParsePipelineText(PassBuilder &PB,
- const cl::opt<std::string> &PipelineOpt) {
- if (PipelineOpt.empty())
- return false;
- // Verify the pipeline is parseable:
- PassManagerT PM;
- if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) {
- errs() << "Could not parse -" << PipelineOpt.ArgStr
- << " pipeline: " << toString(std::move(Err))
- << "... I'm going to ignore it.\n";
- return false;
- }
- return true;
- }
- /// If one of the EPPipeline command line options was given, register callbacks
- /// for parsing and inserting the given pipeline
- static void registerEPCallbacks(PassBuilder &PB) {
- if (tryParsePipelineText<FunctionPassManager>(PB, PeepholeEPPipeline))
- PB.registerPeepholeEPCallback(
- [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse PeepholeEP pipeline: ");
- Err(PB.parsePassPipeline(PM, PeepholeEPPipeline));
- });
- if (tryParsePipelineText<LoopPassManager>(PB,
- LateLoopOptimizationsEPPipeline))
- PB.registerLateLoopOptimizationsEPCallback(
- [&PB](LoopPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: ");
- Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline));
- });
- if (tryParsePipelineText<LoopPassManager>(PB, LoopOptimizerEndEPPipeline))
- PB.registerLoopOptimizerEndEPCallback(
- [&PB](LoopPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: ");
- Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline));
- });
- if (tryParsePipelineText<FunctionPassManager>(PB,
- ScalarOptimizerLateEPPipeline))
- PB.registerScalarOptimizerLateEPCallback(
- [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: ");
- Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline));
- });
- if (tryParsePipelineText<CGSCCPassManager>(PB, CGSCCOptimizerLateEPPipeline))
- PB.registerCGSCCOptimizerLateEPCallback(
- [&PB](CGSCCPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: ");
- Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline));
- });
- if (tryParsePipelineText<FunctionPassManager>(PB, VectorizerStartEPPipeline))
- PB.registerVectorizerStartEPCallback(
- [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
- ExitOnError Err("Unable to parse VectorizerStartEP pipeline: ");
- Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline));
- });
- if (tryParsePipelineText<ModulePassManager>(PB, PipelineStartEPPipeline))
- PB.registerPipelineStartEPCallback(
- [&PB](ModulePassManager &PM, OptimizationLevel) {
- ExitOnError Err("Unable to parse PipelineStartEP pipeline: ");
- Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline));
- });
- if (tryParsePipelineText<ModulePassManager>(
- PB, PipelineEarlySimplificationEPPipeline))
- PB.registerPipelineEarlySimplificationEPCallback(
- [&PB](ModulePassManager &PM, OptimizationLevel) {
- ExitOnError Err("Unable to parse EarlySimplification pipeline: ");
- Err(PB.parsePassPipeline(PM, PipelineEarlySimplificationEPPipeline));
- });
- if (tryParsePipelineText<FunctionPassManager>(PB, OptimizerLastEPPipeline))
- PB.registerOptimizerLastEPCallback(
- [&PB](ModulePassManager &PM, OptimizationLevel) {
- ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
- Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline));
- });
- }
- #define HANDLE_EXTENSION(Ext) \
- llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
- #include "llvm/Support/Extension.def"
- bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
- TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
- ToolOutputFile *ThinLTOLinkOut,
- ToolOutputFile *OptRemarkFile,
- StringRef PassPipeline, ArrayRef<StringRef> Passes,
- OutputKind OK, VerifierKind VK,
- bool ShouldPreserveAssemblyUseListOrder,
- bool ShouldPreserveBitcodeUseListOrder,
- bool EmitSummaryIndex, bool EmitModuleHash,
- bool EnableDebugify) {
- bool VerifyEachPass = VK == VK_VerifyEachPass;
- Optional<PGOOptions> P;
- switch (PGOKindFlag) {
- case InstrGen:
- P = PGOOptions(ProfileFile, "", "", PGOOptions::IRInstr);
- break;
- case InstrUse:
- P = PGOOptions(ProfileFile, "", ProfileRemappingFile, PGOOptions::IRUse);
- break;
- case SampleUse:
- P = PGOOptions(ProfileFile, "", ProfileRemappingFile,
- PGOOptions::SampleUse);
- break;
- case NoPGO:
- if (DebugInfoForProfiling || PseudoProbeForProfiling)
- P = PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
- DebugInfoForProfiling, PseudoProbeForProfiling);
- else
- P = None;
- }
- if (CSPGOKindFlag != NoCSPGO) {
- if (P && (P->Action == PGOOptions::IRInstr ||
- P->Action == PGOOptions::SampleUse))
- errs() << "CSPGOKind cannot be used with IRInstr or SampleUse";
- if (CSPGOKindFlag == CSInstrGen) {
- if (CSProfileGenFile.empty())
- errs() << "CSInstrGen needs to specify CSProfileGenFile";
- if (P) {
- P->CSAction = PGOOptions::CSIRInstr;
- P->CSProfileGenFile = CSProfileGenFile;
- } else
- P = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
- PGOOptions::NoAction, PGOOptions::CSIRInstr);
- } else /* CSPGOKindFlag == CSInstrUse */ {
- if (!P)
- errs() << "CSInstrUse needs to be together with InstrUse";
- P->CSAction = PGOOptions::CSIRUse;
- }
- }
- if (TM)
- TM->setPGOOption(P);
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
- PassInstrumentationCallbacks PIC;
- PrintPassOptions PrintPassOpts;
- PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose;
- PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet;
- StandardInstrumentations SI(DebugPM != DebugLogging::None, VerifyEachPass,
- PrintPassOpts);
- SI.registerCallbacks(PIC, &FAM);
- DebugifyEachInstrumentation Debugify;
- if (DebugifyEach)
- Debugify.registerCallbacks(PIC);
- PipelineTuningOptions PTO;
- // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized
- // to false above so we shouldn't necessarily need to check whether or not the
- // option has been enabled.
- PTO.LoopUnrolling = !DisableLoopUnrolling;
- PassBuilder PB(TM, PTO, P, &PIC);
- registerEPCallbacks(PB);
- // Load requested pass plugins and let them register pass builder callbacks
- for (auto &PluginFN : PassPlugins) {
- auto PassPlugin = PassPlugin::Load(PluginFN);
- if (!PassPlugin) {
- errs() << "Failed to load passes from '" << PluginFN
- << "'. Request ignored.\n";
- continue;
- }
- PassPlugin->registerPassBuilderCallbacks(PB);
- }
- PB.registerPipelineParsingCallback(
- [](StringRef Name, ModulePassManager &MPM,
- ArrayRef<PassBuilder::PipelineElement>) {
- AddressSanitizerOptions Opts;
- if (Name == "asan-pipeline") {
- MPM.addPass(
- RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
- MPM.addPass(ModuleAddressSanitizerPass(Opts));
- return true;
- } else if (Name == "asan-function-pipeline") {
- MPM.addPass(
- RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
- MPM.addPass(
- createModuleToFunctionPassAdaptor(AddressSanitizerPass(Opts)));
- return true;
- }
- return false;
- });
- #define HANDLE_EXTENSION(Ext) \
- get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
- #include "llvm/Support/Extension.def"
- // Specially handle the alias analysis manager so that we can register
- // a custom pipeline of AA passes with it.
- AAManager AA;
- if (Passes.empty()) {
- if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
- errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
- return false;
- }
- }
- // For compatibility with the legacy PM AA pipeline.
- // AAResultsWrapperPass by default provides basic-aa in the legacy PM
- // unless -disable-basic-aa is specified.
- // TODO: remove this once tests implicitly requiring basic-aa use -passes= and
- // -aa-pipeline=basic-aa.
- if (!Passes.empty() && !DisableBasicAA) {
- if (auto Err = PB.parseAAPipeline(AA, "basic-aa")) {
- errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
- return false;
- }
- }
- // For compatibility with legacy pass manager.
- // Alias analyses are not specially specified when using the legacy PM.
- for (auto PassName : Passes) {
- if (PB.isAAPassName(PassName)) {
- if (auto Err = PB.parseAAPipeline(AA, PassName)) {
- errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
- return false;
- }
- }
- }
- // Register the AA manager first so that our version is the one used.
- FAM.registerPass([&] { return std::move(AA); });
- // Register our TargetLibraryInfoImpl.
- FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
- // 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 (VK > VK_NoVerifier)
- MPM.addPass(VerifierPass());
- if (EnableDebugify)
- MPM.addPass(NewPMDebugifyPass());
- // Add passes according to the -passes options.
- if (!PassPipeline.empty()) {
- assert(Passes.empty() &&
- "PassPipeline and Passes should not both contain passes");
- if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
- errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
- return false;
- }
- }
- // Add passes specified using the legacy PM syntax (i.e. not using
- // -passes). This should be removed later when such support has been
- // deprecated, i.e. when all lit tests running opt (and not using
- // -enable-new-pm=0) have been updated to use -passes.
- for (auto PassName : Passes) {
- std::string ModifiedPassName(PassName.begin(), PassName.end());
- if (PB.isAnalysisPassName(PassName))
- ModifiedPassName = "require<" + ModifiedPassName + ">";
- // FIXME: These translations are supposed to be removed when lit tests that
- // use these names have been updated to use the -passes syntax (and when the
- // support for using the old syntax to specify passes is considered as
- // deprecated for the new PM).
- if (ModifiedPassName == "early-cse-memssa")
- ModifiedPassName = "early-cse<memssa>";
- else if (ModifiedPassName == "post-inline-ee-instrument")
- ModifiedPassName = "ee-instrument<post-inline>";
- else if (ModifiedPassName == "loop-extract-single")
- ModifiedPassName = "loop-extract<single>";
- else if (ModifiedPassName == "lower-matrix-intrinsics-minimal")
- ModifiedPassName = "lower-matrix-intrinsics<minimal>";
- if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName)) {
- errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
- return false;
- }
- }
- if (VK > VK_NoVerifier)
- MPM.addPass(VerifierPass());
- if (EnableDebugify)
- MPM.addPass(NewPMCheckDebugifyPass());
- // 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(), "", ShouldPreserveAssemblyUseListOrder));
- break;
- case OK_OutputBitcode:
- MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder,
- EmitSummaryIndex, EmitModuleHash));
- break;
- case OK_OutputThinLTOBitcode:
- MPM.addPass(ThinLTOBitcodeWriterPass(
- Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr));
- break;
- }
- // Before executing passes, print the final values of the LLVM options.
- cl::PrintOptionValues();
- // Print a textual, '-passes=' compatible, representation of pipeline if
- // requested.
- if (PrintPipelinePasses) {
- MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
- auto PassName = PIC.getPassNameForClassName(ClassName);
- return PassName.empty() ? ClassName : PassName;
- });
- outs() << "\n";
- return true;
- }
- // Now that we have all of the passes ready, run them.
- MPM.run(M, MAM);
- // Declare success.
- if (OK != OK_NoOutput) {
- Out->keep();
- if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut)
- ThinLTOLinkOut->keep();
- }
- if (OptRemarkFile)
- OptRemarkFile->keep();
- if (DebugifyEach && !DebugifyExport.empty())
- exportDebugifyStats(DebugifyExport, Debugify.StatsMap);
- return true;
- }
- void llvm::printPasses(raw_ostream &OS) {
- PassBuilder PB;
- PB.printPassNames(OS);
- }
|