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 
39 using namespace llvm;
40 using namespace opt_tool;
41 
42 static cl::opt<bool>
43     DebugPM("debug-pass-manager", cl::Hidden,
44             cl::desc("Print pass management debugging information"));
45 
46 static 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.
53 static 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
61 static 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);
66 static 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);
72 static 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);
77 static 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);
82 static 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);
87 static 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);
92 static 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);
97 static 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 
103 extern cl::opt<PGOKind> PGOKindFlag;
104 extern cl::opt<std::string> ProfileFile;
105 extern cl::opt<CSPGOKind> CSPGOKindFlag;
106 extern cl::opt<std::string> CSProfileGenFile;
107 
108 static cl::opt<std::string>
109     ProfileRemappingFile("profile-remapping-file",
110                          cl::desc("Path to the profile remapping file."),
111                          cl::Hidden);
112 static 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 
117 template <typename PassManagerT>
118 bool 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
136 static 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 
209 bool 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