xref: /freebsd/contrib/llvm-project/llvm/tools/opt/NewPMDriver.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
10b57cec5SDimitry Andric //===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file is just a split of the code that logically belongs in opt.cpp but
110b57cec5SDimitry Andric /// that includes the new pass manager headers.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "NewPMDriver.h"
165ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h"
20e8d8bef9SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
210b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriterPass.h"
220b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
230b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
240b57cec5SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
250b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
260b57cec5SDimitry Andric #include "llvm/IR/Module.h"
270b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
280b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
290b57cec5SDimitry Andric #include "llvm/Passes/PassBuilder.h"
300b57cec5SDimitry Andric #include "llvm/Passes/PassPlugin.h"
310b57cec5SDimitry Andric #include "llvm/Passes/StandardInstrumentations.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
330b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
340b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
350b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
36e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
370b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h"
38480093f4SDimitry Andric #include "llvm/Transforms/Utils/Debugify.h"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric using namespace opt_tool;
420b57cec5SDimitry Andric 
43e8d8bef9SDimitry Andric namespace llvm {
44e8d8bef9SDimitry Andric cl::opt<bool> DebugifyEach(
45e8d8bef9SDimitry Andric     "debugify-each",
46e8d8bef9SDimitry Andric     cl::desc("Start each pass with debugify and end it with check-debugify"));
47e8d8bef9SDimitry Andric 
48e8d8bef9SDimitry Andric cl::opt<std::string>
49e8d8bef9SDimitry Andric     DebugifyExport("debugify-export",
50e8d8bef9SDimitry Andric                    cl::desc("Export per-pass debugify statistics to this file"),
51e8d8bef9SDimitry Andric                    cl::value_desc("filename"));
52*753f127fSDimitry Andric 
53*753f127fSDimitry Andric cl::opt<bool> VerifyEachDebugInfoPreserve(
54*753f127fSDimitry Andric     "verify-each-debuginfo-preserve",
55*753f127fSDimitry Andric     cl::desc("Start each pass with collecting and end it with checking of "
56*753f127fSDimitry Andric              "debug info preservation."));
57*753f127fSDimitry Andric 
58*753f127fSDimitry Andric cl::opt<std::string>
59*753f127fSDimitry Andric     VerifyDIPreserveExport("verify-di-preserve-export",
60*753f127fSDimitry Andric                    cl::desc("Export debug info preservation failures into "
61*753f127fSDimitry Andric                             "specified (JSON) file (should be abs path as we use"
62*753f127fSDimitry Andric                             " append mode to insert new JSON objects)"),
63*753f127fSDimitry Andric                    cl::value_desc("filename"), cl::init(""));
64*753f127fSDimitry Andric 
65e8d8bef9SDimitry Andric } // namespace llvm
66e8d8bef9SDimitry Andric 
67fe6060f1SDimitry Andric enum class DebugLogging { None, Normal, Verbose, Quiet };
68fe6060f1SDimitry Andric 
69fe6060f1SDimitry Andric static cl::opt<DebugLogging> DebugPM(
70fe6060f1SDimitry Andric     "debug-pass-manager", cl::Hidden, cl::ValueOptional,
71fe6060f1SDimitry Andric     cl::desc("Print pass management debugging information"),
72fe6060f1SDimitry Andric     cl::init(DebugLogging::None),
73fe6060f1SDimitry Andric     cl::values(
74fe6060f1SDimitry Andric         clEnumValN(DebugLogging::Normal, "", ""),
75fe6060f1SDimitry Andric         clEnumValN(DebugLogging::Quiet, "quiet",
76fe6060f1SDimitry Andric                    "Skip printing info about analyses"),
77fe6060f1SDimitry Andric         clEnumValN(
78fe6060f1SDimitry Andric             DebugLogging::Verbose, "verbose",
79fe6060f1SDimitry Andric             "Print extra information about adaptors and pass managers")));
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric // This flag specifies a textual description of the alias analysis pipeline to
820b57cec5SDimitry Andric // use when querying for aliasing information. It only works in concert with
830b57cec5SDimitry Andric // the "passes" flag above.
840b57cec5SDimitry Andric static cl::opt<std::string>
850b57cec5SDimitry Andric     AAPipeline("aa-pipeline",
860b57cec5SDimitry Andric                cl::desc("A textual description of the alias analysis "
870b57cec5SDimitry Andric                         "pipeline for handling managed aliasing queries"),
88e8d8bef9SDimitry Andric                cl::Hidden, cl::init("default"));
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric /// {{@ These options accept textual pipeline descriptions which will be
910b57cec5SDimitry Andric /// inserted into default pipelines at the respective extension points
920b57cec5SDimitry Andric static cl::opt<std::string> PeepholeEPPipeline(
930b57cec5SDimitry Andric     "passes-ep-peephole",
940b57cec5SDimitry Andric     cl::desc("A textual description of the function pass pipeline inserted at "
950b57cec5SDimitry Andric              "the Peephole extension points into default pipelines"),
960b57cec5SDimitry Andric     cl::Hidden);
970b57cec5SDimitry Andric static cl::opt<std::string> LateLoopOptimizationsEPPipeline(
980b57cec5SDimitry Andric     "passes-ep-late-loop-optimizations",
990b57cec5SDimitry Andric     cl::desc(
1000b57cec5SDimitry Andric         "A textual description of the loop pass pipeline inserted at "
1010b57cec5SDimitry Andric         "the LateLoopOptimizations extension point into default pipelines"),
1020b57cec5SDimitry Andric     cl::Hidden);
1030b57cec5SDimitry Andric static cl::opt<std::string> LoopOptimizerEndEPPipeline(
1040b57cec5SDimitry Andric     "passes-ep-loop-optimizer-end",
1050b57cec5SDimitry Andric     cl::desc("A textual description of the loop pass pipeline inserted at "
1060b57cec5SDimitry Andric              "the LoopOptimizerEnd extension point into default pipelines"),
1070b57cec5SDimitry Andric     cl::Hidden);
1080b57cec5SDimitry Andric static cl::opt<std::string> ScalarOptimizerLateEPPipeline(
1090b57cec5SDimitry Andric     "passes-ep-scalar-optimizer-late",
1100b57cec5SDimitry Andric     cl::desc("A textual description of the function pass pipeline inserted at "
1110b57cec5SDimitry Andric              "the ScalarOptimizerLate extension point into default pipelines"),
1120b57cec5SDimitry Andric     cl::Hidden);
1130b57cec5SDimitry Andric static cl::opt<std::string> CGSCCOptimizerLateEPPipeline(
1140b57cec5SDimitry Andric     "passes-ep-cgscc-optimizer-late",
1150b57cec5SDimitry Andric     cl::desc("A textual description of the cgscc pass pipeline inserted at "
1160b57cec5SDimitry Andric              "the CGSCCOptimizerLate extension point into default pipelines"),
1170b57cec5SDimitry Andric     cl::Hidden);
1180b57cec5SDimitry Andric static cl::opt<std::string> VectorizerStartEPPipeline(
1190b57cec5SDimitry Andric     "passes-ep-vectorizer-start",
1200b57cec5SDimitry Andric     cl::desc("A textual description of the function pass pipeline inserted at "
1210b57cec5SDimitry Andric              "the VectorizerStart extension point into default pipelines"),
1220b57cec5SDimitry Andric     cl::Hidden);
1230b57cec5SDimitry Andric static cl::opt<std::string> PipelineStartEPPipeline(
1240b57cec5SDimitry Andric     "passes-ep-pipeline-start",
125e8d8bef9SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
1260b57cec5SDimitry Andric              "the PipelineStart extension point into default pipelines"),
1270b57cec5SDimitry Andric     cl::Hidden);
128e8d8bef9SDimitry Andric static cl::opt<std::string> PipelineEarlySimplificationEPPipeline(
129e8d8bef9SDimitry Andric     "passes-ep-pipeline-early-simplification",
130e8d8bef9SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
131e8d8bef9SDimitry Andric              "the EarlySimplification extension point into default pipelines"),
132e8d8bef9SDimitry Andric     cl::Hidden);
13381ad6265SDimitry Andric static cl::opt<std::string> OptimizerEarlyEPPipeline(
13481ad6265SDimitry Andric     "passes-ep-optimizer-early",
13581ad6265SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
13681ad6265SDimitry Andric              "the OptimizerEarly extension point into default pipelines"),
13781ad6265SDimitry Andric     cl::Hidden);
1380b57cec5SDimitry Andric static cl::opt<std::string> OptimizerLastEPPipeline(
1390b57cec5SDimitry Andric     "passes-ep-optimizer-last",
140e8d8bef9SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
1410b57cec5SDimitry Andric              "the OptimizerLast extension point into default pipelines"),
1420b57cec5SDimitry Andric     cl::Hidden);
14381ad6265SDimitry Andric static cl::opt<std::string> FullLinkTimeOptimizationEarlyEPPipeline(
14481ad6265SDimitry Andric     "passes-ep-full-link-time-optimization-early",
14581ad6265SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
14681ad6265SDimitry Andric              "the FullLinkTimeOptimizationEarly extension point into default "
14781ad6265SDimitry Andric              "pipelines"),
14881ad6265SDimitry Andric     cl::Hidden);
14981ad6265SDimitry Andric static cl::opt<std::string> FullLinkTimeOptimizationLastEPPipeline(
15081ad6265SDimitry Andric     "passes-ep-full-link-time-optimization-last",
15181ad6265SDimitry Andric     cl::desc("A textual description of the module pass pipeline inserted at "
15281ad6265SDimitry Andric              "the FullLinkTimeOptimizationLast extension point into default "
15381ad6265SDimitry Andric              "pipelines"),
15481ad6265SDimitry Andric     cl::Hidden);
1550b57cec5SDimitry Andric 
1565ffd83dbSDimitry Andric // Individual pipeline tuning options.
1575ffd83dbSDimitry Andric extern cl::opt<bool> DisableLoopUnrolling;
1585ffd83dbSDimitry Andric 
159fe6060f1SDimitry Andric namespace llvm {
1600b57cec5SDimitry Andric extern cl::opt<PGOKind> PGOKindFlag;
1610b57cec5SDimitry Andric extern cl::opt<std::string> ProfileFile;
1620b57cec5SDimitry Andric extern cl::opt<CSPGOKind> CSPGOKindFlag;
1630b57cec5SDimitry Andric extern cl::opt<std::string> CSProfileGenFile;
164e8d8bef9SDimitry Andric extern cl::opt<bool> DisableBasicAA;
165349cc55cSDimitry Andric extern cl::opt<bool> PrintPipelinePasses;
166fe6060f1SDimitry Andric } // namespace llvm
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric static cl::opt<std::string>
1690b57cec5SDimitry Andric     ProfileRemappingFile("profile-remapping-file",
1700b57cec5SDimitry Andric                          cl::desc("Path to the profile remapping file."),
1710b57cec5SDimitry Andric                          cl::Hidden);
1720b57cec5SDimitry Andric static cl::opt<bool> DebugInfoForProfiling(
1730b57cec5SDimitry Andric     "new-pm-debug-info-for-profiling", cl::init(false), cl::Hidden,
1740b57cec5SDimitry Andric     cl::desc("Emit special debug info to enable PGO profile generation."));
175e8d8bef9SDimitry Andric static cl::opt<bool> PseudoProbeForProfiling(
176e8d8bef9SDimitry Andric     "new-pm-pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
177e8d8bef9SDimitry Andric     cl::desc("Emit pseudo probes to enable PGO profile generation."));
1780b57cec5SDimitry Andric /// @}}
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric template <typename PassManagerT>
1810b57cec5SDimitry Andric bool tryParsePipelineText(PassBuilder &PB,
1820b57cec5SDimitry Andric                           const cl::opt<std::string> &PipelineOpt) {
1830b57cec5SDimitry Andric   if (PipelineOpt.empty())
1840b57cec5SDimitry Andric     return false;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // Verify the pipeline is parseable:
1870b57cec5SDimitry Andric   PassManagerT PM;
1880b57cec5SDimitry Andric   if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) {
1890b57cec5SDimitry Andric     errs() << "Could not parse -" << PipelineOpt.ArgStr
1900b57cec5SDimitry Andric            << " pipeline: " << toString(std::move(Err))
1910b57cec5SDimitry Andric            << "... I'm going to ignore it.\n";
1920b57cec5SDimitry Andric     return false;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric   return true;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric /// If one of the EPPipeline command line options was given, register callbacks
1980b57cec5SDimitry Andric /// for parsing and inserting the given pipeline
199e8d8bef9SDimitry Andric static void registerEPCallbacks(PassBuilder &PB) {
2000b57cec5SDimitry Andric   if (tryParsePipelineText<FunctionPassManager>(PB, PeepholeEPPipeline))
2010b57cec5SDimitry Andric     PB.registerPeepholeEPCallback(
202349cc55cSDimitry Andric         [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
2030b57cec5SDimitry Andric           ExitOnError Err("Unable to parse PeepholeEP pipeline: ");
204e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, PeepholeEPPipeline));
2050b57cec5SDimitry Andric         });
2060b57cec5SDimitry Andric   if (tryParsePipelineText<LoopPassManager>(PB,
2070b57cec5SDimitry Andric                                             LateLoopOptimizationsEPPipeline))
2080b57cec5SDimitry Andric     PB.registerLateLoopOptimizationsEPCallback(
209349cc55cSDimitry Andric         [&PB](LoopPassManager &PM, OptimizationLevel Level) {
2100b57cec5SDimitry Andric           ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: ");
211e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline));
2120b57cec5SDimitry Andric         });
2130b57cec5SDimitry Andric   if (tryParsePipelineText<LoopPassManager>(PB, LoopOptimizerEndEPPipeline))
2140b57cec5SDimitry Andric     PB.registerLoopOptimizerEndEPCallback(
215349cc55cSDimitry Andric         [&PB](LoopPassManager &PM, OptimizationLevel Level) {
2160b57cec5SDimitry Andric           ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: ");
217e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline));
2180b57cec5SDimitry Andric         });
2190b57cec5SDimitry Andric   if (tryParsePipelineText<FunctionPassManager>(PB,
2200b57cec5SDimitry Andric                                                 ScalarOptimizerLateEPPipeline))
2210b57cec5SDimitry Andric     PB.registerScalarOptimizerLateEPCallback(
222349cc55cSDimitry Andric         [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
2230b57cec5SDimitry Andric           ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: ");
224e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline));
2250b57cec5SDimitry Andric         });
2260b57cec5SDimitry Andric   if (tryParsePipelineText<CGSCCPassManager>(PB, CGSCCOptimizerLateEPPipeline))
2270b57cec5SDimitry Andric     PB.registerCGSCCOptimizerLateEPCallback(
228349cc55cSDimitry Andric         [&PB](CGSCCPassManager &PM, OptimizationLevel Level) {
2290b57cec5SDimitry Andric           ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: ");
230e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline));
2310b57cec5SDimitry Andric         });
2320b57cec5SDimitry Andric   if (tryParsePipelineText<FunctionPassManager>(PB, VectorizerStartEPPipeline))
2330b57cec5SDimitry Andric     PB.registerVectorizerStartEPCallback(
234349cc55cSDimitry Andric         [&PB](FunctionPassManager &PM, OptimizationLevel Level) {
2350b57cec5SDimitry Andric           ExitOnError Err("Unable to parse VectorizerStartEP pipeline: ");
236e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline));
2370b57cec5SDimitry Andric         });
2380b57cec5SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(PB, PipelineStartEPPipeline))
2390b57cec5SDimitry Andric     PB.registerPipelineStartEPCallback(
240349cc55cSDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
2410b57cec5SDimitry Andric           ExitOnError Err("Unable to parse PipelineStartEP pipeline: ");
242e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline));
243e8d8bef9SDimitry Andric         });
244e8d8bef9SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(
245e8d8bef9SDimitry Andric           PB, PipelineEarlySimplificationEPPipeline))
246e8d8bef9SDimitry Andric     PB.registerPipelineEarlySimplificationEPCallback(
247349cc55cSDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
248e8d8bef9SDimitry Andric           ExitOnError Err("Unable to parse EarlySimplification pipeline: ");
249e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, PipelineEarlySimplificationEPPipeline));
2500b57cec5SDimitry Andric         });
25181ad6265SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(PB, OptimizerEarlyEPPipeline))
25281ad6265SDimitry Andric     PB.registerOptimizerEarlyEPCallback(
25381ad6265SDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
25481ad6265SDimitry Andric           ExitOnError Err("Unable to parse OptimizerEarlyEP pipeline: ");
25581ad6265SDimitry Andric           Err(PB.parsePassPipeline(PM, OptimizerEarlyEPPipeline));
25681ad6265SDimitry Andric         });
25781ad6265SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(PB, OptimizerLastEPPipeline))
2580b57cec5SDimitry Andric     PB.registerOptimizerLastEPCallback(
259349cc55cSDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
2600b57cec5SDimitry Andric           ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
261e8d8bef9SDimitry Andric           Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline));
2620b57cec5SDimitry Andric         });
26381ad6265SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(
26481ad6265SDimitry Andric           PB, FullLinkTimeOptimizationEarlyEPPipeline))
26581ad6265SDimitry Andric     PB.registerFullLinkTimeOptimizationEarlyEPCallback(
26681ad6265SDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
26781ad6265SDimitry Andric           ExitOnError Err(
26881ad6265SDimitry Andric               "Unable to parse FullLinkTimeOptimizationEarlyEP pipeline: ");
26981ad6265SDimitry Andric           Err(PB.parsePassPipeline(PM,
27081ad6265SDimitry Andric                                    FullLinkTimeOptimizationEarlyEPPipeline));
27181ad6265SDimitry Andric         });
27281ad6265SDimitry Andric   if (tryParsePipelineText<ModulePassManager>(
27381ad6265SDimitry Andric           PB, FullLinkTimeOptimizationLastEPPipeline))
27481ad6265SDimitry Andric     PB.registerFullLinkTimeOptimizationLastEPCallback(
27581ad6265SDimitry Andric         [&PB](ModulePassManager &PM, OptimizationLevel) {
27681ad6265SDimitry Andric           ExitOnError Err(
27781ad6265SDimitry Andric               "Unable to parse FullLinkTimeOptimizationLastEP pipeline: ");
27881ad6265SDimitry Andric           Err(PB.parsePassPipeline(PM, FullLinkTimeOptimizationLastEPPipeline));
27981ad6265SDimitry Andric         });
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
282480093f4SDimitry Andric #define HANDLE_EXTENSION(Ext)                                                  \
283480093f4SDimitry Andric   llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
284480093f4SDimitry Andric #include "llvm/Support/Extension.def"
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
287e8d8bef9SDimitry Andric                            TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
288e8d8bef9SDimitry Andric                            ToolOutputFile *ThinLTOLinkOut,
2890b57cec5SDimitry Andric                            ToolOutputFile *OptRemarkFile,
2905ffd83dbSDimitry Andric                            StringRef PassPipeline, ArrayRef<StringRef> Passes,
29181ad6265SDimitry Andric                            ArrayRef<PassPlugin> PassPlugins,
2925ffd83dbSDimitry Andric                            OutputKind OK, VerifierKind VK,
2930b57cec5SDimitry Andric                            bool ShouldPreserveAssemblyUseListOrder,
2940b57cec5SDimitry Andric                            bool ShouldPreserveBitcodeUseListOrder,
2950b57cec5SDimitry Andric                            bool EmitSummaryIndex, bool EmitModuleHash,
296*753f127fSDimitry Andric                            bool EnableDebugify, bool VerifyDIPreserve) {
2970b57cec5SDimitry Andric   bool VerifyEachPass = VK == VK_VerifyEachPass;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   Optional<PGOOptions> P;
3000b57cec5SDimitry Andric   switch (PGOKindFlag) {
3010b57cec5SDimitry Andric   case InstrGen:
3020b57cec5SDimitry Andric     P = PGOOptions(ProfileFile, "", "", PGOOptions::IRInstr);
3030b57cec5SDimitry Andric     break;
3040b57cec5SDimitry Andric   case InstrUse:
3050b57cec5SDimitry Andric     P = PGOOptions(ProfileFile, "", ProfileRemappingFile, PGOOptions::IRUse);
3060b57cec5SDimitry Andric     break;
3070b57cec5SDimitry Andric   case SampleUse:
3080b57cec5SDimitry Andric     P = PGOOptions(ProfileFile, "", ProfileRemappingFile,
3090b57cec5SDimitry Andric                    PGOOptions::SampleUse);
3100b57cec5SDimitry Andric     break;
3110b57cec5SDimitry Andric   case NoPGO:
312349cc55cSDimitry Andric     if (DebugInfoForProfiling || PseudoProbeForProfiling)
3130b57cec5SDimitry Andric       P = PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
314349cc55cSDimitry Andric                      DebugInfoForProfiling, PseudoProbeForProfiling);
3150b57cec5SDimitry Andric     else
3160b57cec5SDimitry Andric       P = None;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric   if (CSPGOKindFlag != NoCSPGO) {
3190b57cec5SDimitry Andric     if (P && (P->Action == PGOOptions::IRInstr ||
3200b57cec5SDimitry Andric               P->Action == PGOOptions::SampleUse))
3210b57cec5SDimitry Andric       errs() << "CSPGOKind cannot be used with IRInstr or SampleUse";
3220b57cec5SDimitry Andric     if (CSPGOKindFlag == CSInstrGen) {
3230b57cec5SDimitry Andric       if (CSProfileGenFile.empty())
3240b57cec5SDimitry Andric         errs() << "CSInstrGen needs to specify CSProfileGenFile";
3250b57cec5SDimitry Andric       if (P) {
3260b57cec5SDimitry Andric         P->CSAction = PGOOptions::CSIRInstr;
3270b57cec5SDimitry Andric         P->CSProfileGenFile = CSProfileGenFile;
3280b57cec5SDimitry Andric       } else
3290b57cec5SDimitry Andric         P = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
3300b57cec5SDimitry Andric                        PGOOptions::NoAction, PGOOptions::CSIRInstr);
3310b57cec5SDimitry Andric     } else /* CSPGOKindFlag == CSInstrUse */ {
3320b57cec5SDimitry Andric       if (!P)
3330b57cec5SDimitry Andric         errs() << "CSInstrUse needs to be together with InstrUse";
3340b57cec5SDimitry Andric       P->CSAction = PGOOptions::CSIRUse;
3350b57cec5SDimitry Andric     }
3360b57cec5SDimitry Andric   }
337349cc55cSDimitry Andric   if (TM)
338349cc55cSDimitry Andric     TM->setPGOOption(P);
339349cc55cSDimitry Andric 
340fe6060f1SDimitry Andric   LoopAnalysisManager LAM;
341fe6060f1SDimitry Andric   FunctionAnalysisManager FAM;
342fe6060f1SDimitry Andric   CGSCCAnalysisManager CGAM;
343fe6060f1SDimitry Andric   ModuleAnalysisManager MAM;
344fe6060f1SDimitry Andric 
3450b57cec5SDimitry Andric   PassInstrumentationCallbacks PIC;
346fe6060f1SDimitry Andric   PrintPassOptions PrintPassOpts;
347fe6060f1SDimitry Andric   PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose;
348fe6060f1SDimitry Andric   PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet;
349fe6060f1SDimitry Andric   StandardInstrumentations SI(DebugPM != DebugLogging::None, VerifyEachPass,
350fe6060f1SDimitry Andric                               PrintPassOpts);
351fe6060f1SDimitry Andric   SI.registerCallbacks(PIC, &FAM);
352e8d8bef9SDimitry Andric   DebugifyEachInstrumentation Debugify;
353*753f127fSDimitry Andric   DebugifyStatsMap DIStatsMap;
354*753f127fSDimitry Andric   DebugInfoPerPass DebugInfoBeforePass;
355*753f127fSDimitry Andric   if (DebugifyEach) {
356*753f127fSDimitry Andric     Debugify.setDIStatsMap(DIStatsMap);
357*753f127fSDimitry Andric     Debugify.setDebugifyMode(DebugifyMode::SyntheticDebugInfo);
358e8d8bef9SDimitry Andric     Debugify.registerCallbacks(PIC);
359*753f127fSDimitry Andric   } else if (VerifyEachDebugInfoPreserve) {
360*753f127fSDimitry Andric     Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
361*753f127fSDimitry Andric     Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
362*753f127fSDimitry Andric     Debugify.setOrigDIVerifyBugsReportFilePath(
363*753f127fSDimitry Andric       VerifyDIPreserveExport);
364*753f127fSDimitry Andric     Debugify.registerCallbacks(PIC);
365*753f127fSDimitry Andric   }
3660b57cec5SDimitry Andric 
3675ffd83dbSDimitry Andric   PipelineTuningOptions PTO;
3685ffd83dbSDimitry Andric   // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized
3695ffd83dbSDimitry Andric   // to false above so we shouldn't necessarily need to check whether or not the
3705ffd83dbSDimitry Andric   // option has been enabled.
3715ffd83dbSDimitry Andric   PTO.LoopUnrolling = !DisableLoopUnrolling;
372fe6060f1SDimitry Andric   PassBuilder PB(TM, PTO, P, &PIC);
373e8d8bef9SDimitry Andric   registerEPCallbacks(PB);
3740b57cec5SDimitry Andric 
37581ad6265SDimitry Andric   // For any loaded plugins, let them register pass builder callbacks.
37681ad6265SDimitry Andric   for (auto &PassPlugin : PassPlugins)
37781ad6265SDimitry Andric     PassPlugin.registerPassBuilderCallbacks(PB);
3780b57cec5SDimitry Andric 
379e8d8bef9SDimitry Andric   PB.registerPipelineParsingCallback(
380e8d8bef9SDimitry Andric       [](StringRef Name, ModulePassManager &MPM,
381e8d8bef9SDimitry Andric          ArrayRef<PassBuilder::PipelineElement>) {
382349cc55cSDimitry Andric         AddressSanitizerOptions Opts;
383e8d8bef9SDimitry Andric         if (Name == "asan-pipeline") {
384349cc55cSDimitry Andric           MPM.addPass(ModuleAddressSanitizerPass(Opts));
385e8d8bef9SDimitry Andric           return true;
386e8d8bef9SDimitry Andric         }
387e8d8bef9SDimitry Andric         return false;
388e8d8bef9SDimitry Andric       });
3890b57cec5SDimitry Andric 
390480093f4SDimitry Andric #define HANDLE_EXTENSION(Ext)                                                  \
391480093f4SDimitry Andric   get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
392480093f4SDimitry Andric #include "llvm/Support/Extension.def"
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   // Specially handle the alias analysis manager so that we can register
3950b57cec5SDimitry Andric   // a custom pipeline of AA passes with it.
3960b57cec5SDimitry Andric   AAManager AA;
397e8d8bef9SDimitry Andric   if (Passes.empty()) {
3980b57cec5SDimitry Andric     if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
3990b57cec5SDimitry Andric       errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
4000b57cec5SDimitry Andric       return false;
4010b57cec5SDimitry Andric     }
4025ffd83dbSDimitry Andric   }
403e8d8bef9SDimitry Andric 
404e8d8bef9SDimitry Andric   // For compatibility with the legacy PM AA pipeline.
405e8d8bef9SDimitry Andric   // AAResultsWrapperPass by default provides basic-aa in the legacy PM
406e8d8bef9SDimitry Andric   // unless -disable-basic-aa is specified.
407e8d8bef9SDimitry Andric   // TODO: remove this once tests implicitly requiring basic-aa use -passes= and
408e8d8bef9SDimitry Andric   // -aa-pipeline=basic-aa.
409e8d8bef9SDimitry Andric   if (!Passes.empty() && !DisableBasicAA) {
410e8d8bef9SDimitry Andric     if (auto Err = PB.parseAAPipeline(AA, "basic-aa")) {
411e8d8bef9SDimitry Andric       errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
412e8d8bef9SDimitry Andric       return false;
413e8d8bef9SDimitry Andric     }
414e8d8bef9SDimitry Andric   }
415e8d8bef9SDimitry Andric 
4165ffd83dbSDimitry Andric   // For compatibility with legacy pass manager.
4175ffd83dbSDimitry Andric   // Alias analyses are not specially specified when using the legacy PM.
4185ffd83dbSDimitry Andric   for (auto PassName : Passes) {
4195ffd83dbSDimitry Andric     if (PB.isAAPassName(PassName)) {
4205ffd83dbSDimitry Andric       if (auto Err = PB.parseAAPipeline(AA, PassName)) {
4215ffd83dbSDimitry Andric         errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
4225ffd83dbSDimitry Andric         return false;
4235ffd83dbSDimitry Andric       }
4245ffd83dbSDimitry Andric     }
4255ffd83dbSDimitry Andric   }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // Register the AA manager first so that our version is the one used.
4280b57cec5SDimitry Andric   FAM.registerPass([&] { return std::move(AA); });
429e8d8bef9SDimitry Andric   // Register our TargetLibraryInfoImpl.
430e8d8bef9SDimitry Andric   FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   // Register all the basic analyses with the managers.
4330b57cec5SDimitry Andric   PB.registerModuleAnalyses(MAM);
4340b57cec5SDimitry Andric   PB.registerCGSCCAnalyses(CGAM);
4350b57cec5SDimitry Andric   PB.registerFunctionAnalyses(FAM);
4360b57cec5SDimitry Andric   PB.registerLoopAnalyses(LAM);
4370b57cec5SDimitry Andric   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
4380b57cec5SDimitry Andric 
439fe6060f1SDimitry Andric   ModulePassManager MPM;
4400b57cec5SDimitry Andric   if (VK > VK_NoVerifier)
4410b57cec5SDimitry Andric     MPM.addPass(VerifierPass());
4420b57cec5SDimitry Andric   if (EnableDebugify)
4430b57cec5SDimitry Andric     MPM.addPass(NewPMDebugifyPass());
444*753f127fSDimitry Andric   if (VerifyDIPreserve)
445*753f127fSDimitry Andric     MPM.addPass(NewPMDebugifyPass(DebugifyMode::OriginalDebugInfo, "",
446*753f127fSDimitry Andric                                   &DebugInfoBeforePass));
4470b57cec5SDimitry Andric 
448349cc55cSDimitry Andric   // Add passes according to the -passes options.
4495ffd83dbSDimitry Andric   if (!PassPipeline.empty()) {
4505ffd83dbSDimitry Andric     assert(Passes.empty() &&
4515ffd83dbSDimitry Andric            "PassPipeline and Passes should not both contain passes");
452e8d8bef9SDimitry Andric     if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
4530b57cec5SDimitry Andric       errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
4540b57cec5SDimitry Andric       return false;
4550b57cec5SDimitry Andric     }
4565ffd83dbSDimitry Andric   }
457349cc55cSDimitry Andric   // Add passes specified using the legacy PM syntax (i.e. not using
458349cc55cSDimitry Andric   // -passes). This should be removed later when such support has been
459349cc55cSDimitry Andric   // deprecated, i.e. when all lit tests running opt (and not using
460349cc55cSDimitry Andric   // -enable-new-pm=0) have been updated to use -passes.
461e8d8bef9SDimitry Andric   for (auto PassName : Passes) {
4625ffd83dbSDimitry Andric     std::string ModifiedPassName(PassName.begin(), PassName.end());
4635ffd83dbSDimitry Andric     if (PB.isAnalysisPassName(PassName))
4645ffd83dbSDimitry Andric       ModifiedPassName = "require<" + ModifiedPassName + ">";
465349cc55cSDimitry Andric     // FIXME: These translations are supposed to be removed when lit tests that
466349cc55cSDimitry Andric     // use these names have been updated to use the -passes syntax (and when the
467349cc55cSDimitry Andric     // support for using the old syntax to specify passes is considered as
468349cc55cSDimitry Andric     // deprecated for the new PM).
469349cc55cSDimitry Andric     if (ModifiedPassName == "early-cse-memssa")
470349cc55cSDimitry Andric       ModifiedPassName = "early-cse<memssa>";
471349cc55cSDimitry Andric     else if (ModifiedPassName == "post-inline-ee-instrument")
472349cc55cSDimitry Andric       ModifiedPassName = "ee-instrument<post-inline>";
473349cc55cSDimitry Andric     else if (ModifiedPassName == "loop-extract-single")
474349cc55cSDimitry Andric       ModifiedPassName = "loop-extract<single>";
475349cc55cSDimitry Andric     else if (ModifiedPassName == "lower-matrix-intrinsics-minimal")
476349cc55cSDimitry Andric       ModifiedPassName = "lower-matrix-intrinsics<minimal>";
477e8d8bef9SDimitry Andric     if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName)) {
4785ffd83dbSDimitry Andric       errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
4795ffd83dbSDimitry Andric       return false;
4805ffd83dbSDimitry Andric     }
4815ffd83dbSDimitry Andric   }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   if (VK > VK_NoVerifier)
4840b57cec5SDimitry Andric     MPM.addPass(VerifierPass());
4850b57cec5SDimitry Andric   if (EnableDebugify)
486*753f127fSDimitry Andric     MPM.addPass(NewPMCheckDebugifyPass(false, "", &DIStatsMap));
487*753f127fSDimitry Andric   if (VerifyDIPreserve)
488*753f127fSDimitry Andric     MPM.addPass(NewPMCheckDebugifyPass(
489*753f127fSDimitry Andric         false, "", nullptr, DebugifyMode::OriginalDebugInfo, &DebugInfoBeforePass,
490*753f127fSDimitry Andric         VerifyDIPreserveExport));
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   // Add any relevant output pass at the end of the pipeline.
4930b57cec5SDimitry Andric   switch (OK) {
4940b57cec5SDimitry Andric   case OK_NoOutput:
4950b57cec5SDimitry Andric     break; // No output pass needed.
4960b57cec5SDimitry Andric   case OK_OutputAssembly:
4970b57cec5SDimitry Andric     MPM.addPass(
4980b57cec5SDimitry Andric         PrintModulePass(Out->os(), "", ShouldPreserveAssemblyUseListOrder));
4990b57cec5SDimitry Andric     break;
5000b57cec5SDimitry Andric   case OK_OutputBitcode:
5010b57cec5SDimitry Andric     MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder,
5020b57cec5SDimitry Andric                                   EmitSummaryIndex, EmitModuleHash));
5030b57cec5SDimitry Andric     break;
5040b57cec5SDimitry Andric   case OK_OutputThinLTOBitcode:
5050b57cec5SDimitry Andric     MPM.addPass(ThinLTOBitcodeWriterPass(
5060b57cec5SDimitry Andric         Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr));
5070b57cec5SDimitry Andric     break;
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   // Before executing passes, print the final values of the LLVM options.
5110b57cec5SDimitry Andric   cl::PrintOptionValues();
5120b57cec5SDimitry Andric 
513349cc55cSDimitry Andric   // Print a textual, '-passes=' compatible, representation of pipeline if
514349cc55cSDimitry Andric   // requested.
515349cc55cSDimitry Andric   if (PrintPipelinePasses) {
516349cc55cSDimitry Andric     MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
517349cc55cSDimitry Andric       auto PassName = PIC.getPassNameForClassName(ClassName);
518349cc55cSDimitry Andric       return PassName.empty() ? ClassName : PassName;
519349cc55cSDimitry Andric     });
520349cc55cSDimitry Andric     outs() << "\n";
521349cc55cSDimitry Andric     return true;
522349cc55cSDimitry Andric   }
523349cc55cSDimitry Andric 
5240b57cec5SDimitry Andric   // Now that we have all of the passes ready, run them.
5250b57cec5SDimitry Andric   MPM.run(M, MAM);
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   // Declare success.
5280b57cec5SDimitry Andric   if (OK != OK_NoOutput) {
5290b57cec5SDimitry Andric     Out->keep();
5300b57cec5SDimitry Andric     if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut)
5310b57cec5SDimitry Andric       ThinLTOLinkOut->keep();
5320b57cec5SDimitry Andric   }
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   if (OptRemarkFile)
5350b57cec5SDimitry Andric     OptRemarkFile->keep();
5360b57cec5SDimitry Andric 
537e8d8bef9SDimitry Andric   if (DebugifyEach && !DebugifyExport.empty())
538*753f127fSDimitry Andric     exportDebugifyStats(DebugifyExport, Debugify.getDebugifyStatsMap());
539e8d8bef9SDimitry Andric 
5400b57cec5SDimitry Andric   return true;
5410b57cec5SDimitry Andric }
542fe6060f1SDimitry Andric 
543fe6060f1SDimitry Andric void llvm::printPasses(raw_ostream &OS) {
544fe6060f1SDimitry Andric   PassBuilder PB;
545fe6060f1SDimitry Andric   PB.printPassNames(OS);
546fe6060f1SDimitry Andric }
547