1//===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file is just a split of the code that logically belongs in opt.cpp but
11/// that includes the new pass manager headers.
12///
13//===----------------------------------------------------------------------===//
14
15#include "NewPMDriver.h"
16#include "PassPrinters.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/Analysis/AliasAnalysis.h"
19#include "llvm/Analysis/CGSCCPassManager.h"
20#include "llvm/Bitcode/BitcodeWriterPass.h"
21#include "llvm/Config/llvm-config.h"
22#include "llvm/IR/Dominators.h"
23#include "llvm/IR/IRPrintingPasses.h"
24#include "llvm/IR/LLVMContext.h"
25#include "llvm/IR/Module.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/IR/Verifier.h"
28#include "llvm/Passes/PassBuilder.h"
29#include "llvm/Passes/PassPlugin.h"
30#include "llvm/Passes/StandardInstrumentations.h"
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/ToolOutputFile.h"
34#include "llvm/Target/TargetMachine.h"
35#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
36#include "llvm/Transforms/Scalar/LoopPassManager.h"
37#include "llvm/Transforms/Utils/Debugify.h"
38
39using namespace llvm;
40using namespace opt_tool;
41
42static cl::opt<bool>
43    DebugPM("debug-pass-manager", cl::Hidden,
44            cl::desc("Print pass management debugging information"));
45
46static cl::list<std::string>
47    PassPlugins("load-pass-plugin",
48                cl::desc("Load passes from plugin library"));
49
50// This flag specifies a textual description of the alias analysis pipeline to
51// use when querying for aliasing information. It only works in concert with
52// the "passes" flag above.
53static cl::opt<std::string>
54    AAPipeline("aa-pipeline",
55               cl::desc("A textual description of the alias analysis "
56                        "pipeline for handling managed aliasing queries"),
57               cl::Hidden);
58
59/// {{@ These options accept textual pipeline descriptions which will be
60/// inserted into default pipelines at the respective extension points
61static cl::opt<std::string> PeepholeEPPipeline(
62    "passes-ep-peephole",
63    cl::desc("A textual description of the function pass pipeline inserted at "
64             "the Peephole extension points into default pipelines"),
65    cl::Hidden);
66static cl::opt<std::string> LateLoopOptimizationsEPPipeline(
67    "passes-ep-late-loop-optimizations",
68    cl::desc(
69        "A textual description of the loop pass pipeline inserted at "
70        "the LateLoopOptimizations extension point into default pipelines"),
71    cl::Hidden);
72static cl::opt<std::string> LoopOptimizerEndEPPipeline(
73    "passes-ep-loop-optimizer-end",
74    cl::desc("A textual description of the loop pass pipeline inserted at "
75             "the LoopOptimizerEnd extension point into default pipelines"),
76    cl::Hidden);
77static cl::opt<std::string> ScalarOptimizerLateEPPipeline(
78    "passes-ep-scalar-optimizer-late",
79    cl::desc("A textual description of the function pass pipeline inserted at "
80             "the ScalarOptimizerLate extension point into default pipelines"),
81    cl::Hidden);
82static cl::opt<std::string> CGSCCOptimizerLateEPPipeline(
83    "passes-ep-cgscc-optimizer-late",
84    cl::desc("A textual description of the cgscc pass pipeline inserted at "
85             "the CGSCCOptimizerLate extension point into default pipelines"),
86    cl::Hidden);
87static cl::opt<std::string> VectorizerStartEPPipeline(
88    "passes-ep-vectorizer-start",
89    cl::desc("A textual description of the function pass pipeline inserted at "
90             "the VectorizerStart extension point into default pipelines"),
91    cl::Hidden);
92static cl::opt<std::string> PipelineStartEPPipeline(
93    "passes-ep-pipeline-start",
94    cl::desc("A textual description of the function pass pipeline inserted at "
95             "the PipelineStart extension point into default pipelines"),
96    cl::Hidden);
97static cl::opt<std::string> OptimizerLastEPPipeline(
98    "passes-ep-optimizer-last",
99    cl::desc("A textual description of the function pass pipeline inserted at "
100             "the OptimizerLast extension point into default pipelines"),
101    cl::Hidden);
102
103extern cl::opt<PGOKind> PGOKindFlag;
104extern cl::opt<std::string> ProfileFile;
105extern cl::opt<CSPGOKind> CSPGOKindFlag;
106extern cl::opt<std::string> CSProfileGenFile;
107
108static cl::opt<std::string>
109    ProfileRemappingFile("profile-remapping-file",
110                         cl::desc("Path to the profile remapping file."),
111                         cl::Hidden);
112static cl::opt<bool> DebugInfoForProfiling(
113    "new-pm-debug-info-for-profiling", cl::init(false), cl::Hidden,
114    cl::desc("Emit special debug info to enable PGO profile generation."));
115/// @}}
116
117template <typename PassManagerT>
118bool tryParsePipelineText(PassBuilder &PB,
119                          const cl::opt<std::string> &PipelineOpt) {
120  if (PipelineOpt.empty())
121    return false;
122
123  // Verify the pipeline is parseable:
124  PassManagerT PM;
125  if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) {
126    errs() << "Could not parse -" << PipelineOpt.ArgStr
127           << " pipeline: " << toString(std::move(Err))
128           << "... I'm going to ignore it.\n";
129    return false;
130  }
131  return true;
132}
133
134/// If one of the EPPipeline command line options was given, register callbacks
135/// for parsing and inserting the given pipeline
136static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
137                                bool DebugLogging) {
138  if (tryParsePipelineText<FunctionPassManager>(PB, PeepholeEPPipeline))
139    PB.registerPeepholeEPCallback(
140        [&PB, VerifyEachPass, DebugLogging](
141            FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
142          ExitOnError Err("Unable to parse PeepholeEP pipeline: ");
143          Err(PB.parsePassPipeline(PM, PeepholeEPPipeline, VerifyEachPass,
144                                   DebugLogging));
145        });
146  if (tryParsePipelineText<LoopPassManager>(PB,
147                                            LateLoopOptimizationsEPPipeline))
148    PB.registerLateLoopOptimizationsEPCallback(
149        [&PB, VerifyEachPass, DebugLogging](
150            LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
151          ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: ");
152          Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline,
153                                   VerifyEachPass, DebugLogging));
154        });
155  if (tryParsePipelineText<LoopPassManager>(PB, LoopOptimizerEndEPPipeline))
156    PB.registerLoopOptimizerEndEPCallback(
157        [&PB, VerifyEachPass, DebugLogging](
158            LoopPassManager &PM, PassBuilder::OptimizationLevel Level) {
159          ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: ");
160          Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline,
161                                   VerifyEachPass, DebugLogging));
162        });
163  if (tryParsePipelineText<FunctionPassManager>(PB,
164                                                ScalarOptimizerLateEPPipeline))
165    PB.registerScalarOptimizerLateEPCallback(
166        [&PB, VerifyEachPass, DebugLogging](
167            FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
168          ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: ");
169          Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline,
170                                   VerifyEachPass, DebugLogging));
171        });
172  if (tryParsePipelineText<CGSCCPassManager>(PB, CGSCCOptimizerLateEPPipeline))
173    PB.registerCGSCCOptimizerLateEPCallback(
174        [&PB, VerifyEachPass, DebugLogging](
175            CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) {
176          ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: ");
177          Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline,
178                                   VerifyEachPass, DebugLogging));
179        });
180  if (tryParsePipelineText<FunctionPassManager>(PB, VectorizerStartEPPipeline))
181    PB.registerVectorizerStartEPCallback(
182        [&PB, VerifyEachPass, DebugLogging](
183            FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) {
184          ExitOnError Err("Unable to parse VectorizerStartEP pipeline: ");
185          Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline,
186                                   VerifyEachPass, DebugLogging));
187        });
188  if (tryParsePipelineText<ModulePassManager>(PB, PipelineStartEPPipeline))
189    PB.registerPipelineStartEPCallback(
190        [&PB, VerifyEachPass, DebugLogging](ModulePassManager &PM) {
191          ExitOnError Err("Unable to parse PipelineStartEP pipeline: ");
192          Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass,
193                                   DebugLogging));
194        });
195  if (tryParsePipelineText<FunctionPassManager>(PB, OptimizerLastEPPipeline))
196    PB.registerOptimizerLastEPCallback(
197        [&PB, VerifyEachPass, DebugLogging](FunctionPassManager &PM,
198                                            PassBuilder::OptimizationLevel) {
199          ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
200          Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline, VerifyEachPass,
201                                   DebugLogging));
202        });
203}
204
205#define HANDLE_EXTENSION(Ext)                                                  \
206  llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
207#include "llvm/Support/Extension.def"
208
209bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
210                           ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut,
211                           ToolOutputFile *OptRemarkFile,
212                           StringRef PassPipeline, OutputKind OK,
213                           VerifierKind VK,
214                           bool ShouldPreserveAssemblyUseListOrder,
215                           bool ShouldPreserveBitcodeUseListOrder,
216                           bool EmitSummaryIndex, bool EmitModuleHash,
217                           bool EnableDebugify) {
218  bool VerifyEachPass = VK == VK_VerifyEachPass;
219
220  Optional<PGOOptions> P;
221  switch (PGOKindFlag) {
222    case InstrGen:
223      P = PGOOptions(ProfileFile, "", "", PGOOptions::IRInstr);
224      break;
225    case InstrUse:
226      P = PGOOptions(ProfileFile, "", ProfileRemappingFile, PGOOptions::IRUse);
227      break;
228    case SampleUse:
229      P = PGOOptions(ProfileFile, "", ProfileRemappingFile,
230                     PGOOptions::SampleUse);
231      break;
232    case NoPGO:
233      if (DebugInfoForProfiling)
234        P = PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
235                       true);
236      else
237        P = None;
238    }
239    if (CSPGOKindFlag != NoCSPGO) {
240      if (P && (P->Action == PGOOptions::IRInstr ||
241                P->Action == PGOOptions::SampleUse))
242        errs() << "CSPGOKind cannot be used with IRInstr or SampleUse";
243      if (CSPGOKindFlag == CSInstrGen) {
244        if (CSProfileGenFile.empty())
245          errs() << "CSInstrGen needs to specify CSProfileGenFile";
246        if (P) {
247          P->CSAction = PGOOptions::CSIRInstr;
248          P->CSProfileGenFile = CSProfileGenFile;
249        } else
250          P = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
251                         PGOOptions::NoAction, PGOOptions::CSIRInstr);
252      } else /* CSPGOKindFlag == CSInstrUse */ {
253        if (!P)
254          errs() << "CSInstrUse needs to be together with InstrUse";
255        P->CSAction = PGOOptions::CSIRUse;
256      }
257    }
258  PassInstrumentationCallbacks PIC;
259  StandardInstrumentations SI;
260  SI.registerCallbacks(PIC);
261
262  PassBuilder PB(TM, PipelineTuningOptions(), P, &PIC);
263  registerEPCallbacks(PB, VerifyEachPass, DebugPM);
264
265  // Load requested pass plugins and let them register pass builder callbacks
266  for (auto &PluginFN : PassPlugins) {
267    auto PassPlugin = PassPlugin::Load(PluginFN);
268    if (!PassPlugin) {
269      errs() << "Failed to load passes from '" << PluginFN
270             << "'. Request ignored.\n";
271      continue;
272    }
273
274    PassPlugin->registerPassBuilderCallbacks(PB);
275  }
276
277  // Register a callback that creates the debugify passes as needed.
278  PB.registerPipelineParsingCallback(
279      [](StringRef Name, ModulePassManager &MPM,
280         ArrayRef<PassBuilder::PipelineElement>) {
281        if (Name == "debugify") {
282          MPM.addPass(NewPMDebugifyPass());
283          return true;
284        } else if (Name == "check-debugify") {
285          MPM.addPass(NewPMCheckDebugifyPass());
286          return true;
287        }
288        return false;
289      });
290
291#define HANDLE_EXTENSION(Ext)                                                  \
292  get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
293#include "llvm/Support/Extension.def"
294
295  // Specially handle the alias analysis manager so that we can register
296  // a custom pipeline of AA passes with it.
297  AAManager AA;
298  if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
299    errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
300    return false;
301  }
302
303  LoopAnalysisManager LAM(DebugPM);
304  FunctionAnalysisManager FAM(DebugPM);
305  CGSCCAnalysisManager CGAM(DebugPM);
306  ModuleAnalysisManager MAM(DebugPM);
307
308  // Register the AA manager first so that our version is the one used.
309  FAM.registerPass([&] { return std::move(AA); });
310
311  // Register all the basic analyses with the managers.
312  PB.registerModuleAnalyses(MAM);
313  PB.registerCGSCCAnalyses(CGAM);
314  PB.registerFunctionAnalyses(FAM);
315  PB.registerLoopAnalyses(LAM);
316  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
317
318  ModulePassManager MPM(DebugPM);
319  if (VK > VK_NoVerifier)
320    MPM.addPass(VerifierPass());
321  if (EnableDebugify)
322    MPM.addPass(NewPMDebugifyPass());
323
324  if (auto Err =
325          PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) {
326    errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
327    return false;
328  }
329
330  if (VK > VK_NoVerifier)
331    MPM.addPass(VerifierPass());
332  if (EnableDebugify)
333    MPM.addPass(NewPMCheckDebugifyPass());
334
335  // Add any relevant output pass at the end of the pipeline.
336  switch (OK) {
337  case OK_NoOutput:
338    break; // No output pass needed.
339  case OK_OutputAssembly:
340    MPM.addPass(
341        PrintModulePass(Out->os(), "", ShouldPreserveAssemblyUseListOrder));
342    break;
343  case OK_OutputBitcode:
344    MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder,
345                                  EmitSummaryIndex, EmitModuleHash));
346    break;
347  case OK_OutputThinLTOBitcode:
348    MPM.addPass(ThinLTOBitcodeWriterPass(
349        Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr));
350    break;
351  }
352
353  // Before executing passes, print the final values of the LLVM options.
354  cl::PrintOptionValues();
355
356  // Now that we have all of the passes ready, run them.
357  MPM.run(M, MAM);
358
359  // Declare success.
360  if (OK != OK_NoOutput) {
361    Out->keep();
362    if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut)
363      ThinLTOLinkOut->keep();
364  }
365
366  if (OptRemarkFile)
367    OptRemarkFile->keep();
368
369  return true;
370}
371