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 "llvm/ADT/SmallVector.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/Analysis/AliasAnalysis.h" |
19 | #include "llvm/Analysis/CGSCCPassManager.h" |
20 | #include "llvm/Analysis/TargetLibraryInfo.h" |
21 | #include "llvm/Bitcode/BitcodeWriterPass.h" |
22 | #include "llvm/Config/llvm-config.h" |
23 | #include "llvm/IR/Dominators.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/IRPrinter/IRPrintingPasses.h" |
29 | #include "llvm/Passes/PassBuilder.h" |
30 | #include "llvm/Passes/PassPlugin.h" |
31 | #include "llvm/Passes/StandardInstrumentations.h" |
32 | #include "llvm/Support/ErrorHandling.h" |
33 | #include "llvm/Support/ToolOutputFile.h" |
34 | #include "llvm/Support/VirtualFileSystem.h" |
35 | #include "llvm/Support/raw_ostream.h" |
36 | #include "llvm/Target/TargetMachine.h" |
37 | #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" |
38 | #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" |
39 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
40 | #include "llvm/Transforms/Utils/Debugify.h" |
41 | |
42 | using namespace llvm; |
43 | using namespace opt_tool; |
44 | |
45 | namespace llvm { |
46 | cl::opt<bool> DebugifyEach( |
47 | "debugify-each" , |
48 | cl::desc("Start each pass with debugify and end it with check-debugify" )); |
49 | |
50 | cl::opt<std::string> |
51 | DebugifyExport("debugify-export" , |
52 | cl::desc("Export per-pass debugify statistics to this file" ), |
53 | cl::value_desc("filename" )); |
54 | |
55 | cl::opt<bool> VerifyEachDebugInfoPreserve( |
56 | "verify-each-debuginfo-preserve" , |
57 | cl::desc("Start each pass with collecting and end it with checking of " |
58 | "debug info preservation." )); |
59 | |
60 | cl::opt<std::string> |
61 | VerifyDIPreserveExport("verify-di-preserve-export" , |
62 | cl::desc("Export debug info preservation failures into " |
63 | "specified (JSON) file (should be abs path as we use" |
64 | " append mode to insert new JSON objects)" ), |
65 | cl::value_desc("filename" ), cl::init(Val: "" )); |
66 | |
67 | } // namespace llvm |
68 | |
69 | enum class DebugLogging { None, Normal, Verbose, Quiet }; |
70 | |
71 | static cl::opt<DebugLogging> DebugPM( |
72 | "debug-pass-manager" , cl::Hidden, cl::ValueOptional, |
73 | cl::desc("Print pass management debugging information" ), |
74 | cl::init(Val: DebugLogging::None), |
75 | cl::values( |
76 | clEnumValN(DebugLogging::Normal, "" , "" ), |
77 | clEnumValN(DebugLogging::Quiet, "quiet" , |
78 | "Skip printing info about analyses" ), |
79 | clEnumValN( |
80 | DebugLogging::Verbose, "verbose" , |
81 | "Print extra information about adaptors and pass managers" ))); |
82 | |
83 | // This flag specifies a textual description of the alias analysis pipeline to |
84 | // use when querying for aliasing information. It only works in concert with |
85 | // the "passes" flag above. |
86 | static cl::opt<std::string> |
87 | AAPipeline("aa-pipeline" , |
88 | cl::desc("A textual description of the alias analysis " |
89 | "pipeline for handling managed aliasing queries" ), |
90 | cl::Hidden, cl::init(Val: "default" )); |
91 | |
92 | /// {{@ These options accept textual pipeline descriptions which will be |
93 | /// inserted into default pipelines at the respective extension points |
94 | static cl::opt<std::string> PeepholeEPPipeline( |
95 | "passes-ep-peephole" , |
96 | cl::desc("A textual description of the function pass pipeline inserted at " |
97 | "the Peephole extension points into default pipelines" ), |
98 | cl::Hidden); |
99 | static cl::opt<std::string> LateLoopOptimizationsEPPipeline( |
100 | "passes-ep-late-loop-optimizations" , |
101 | cl::desc( |
102 | "A textual description of the loop pass pipeline inserted at " |
103 | "the LateLoopOptimizations extension point into default pipelines" ), |
104 | cl::Hidden); |
105 | static cl::opt<std::string> LoopOptimizerEndEPPipeline( |
106 | "passes-ep-loop-optimizer-end" , |
107 | cl::desc("A textual description of the loop pass pipeline inserted at " |
108 | "the LoopOptimizerEnd extension point into default pipelines" ), |
109 | cl::Hidden); |
110 | static cl::opt<std::string> ScalarOptimizerLateEPPipeline( |
111 | "passes-ep-scalar-optimizer-late" , |
112 | cl::desc("A textual description of the function pass pipeline inserted at " |
113 | "the ScalarOptimizerLate extension point into default pipelines" ), |
114 | cl::Hidden); |
115 | static cl::opt<std::string> CGSCCOptimizerLateEPPipeline( |
116 | "passes-ep-cgscc-optimizer-late" , |
117 | cl::desc("A textual description of the cgscc pass pipeline inserted at " |
118 | "the CGSCCOptimizerLate extension point into default pipelines" ), |
119 | cl::Hidden); |
120 | static cl::opt<std::string> VectorizerStartEPPipeline( |
121 | "passes-ep-vectorizer-start" , |
122 | cl::desc("A textual description of the function pass pipeline inserted at " |
123 | "the VectorizerStart extension point into default pipelines" ), |
124 | cl::Hidden); |
125 | static cl::opt<std::string> PipelineStartEPPipeline( |
126 | "passes-ep-pipeline-start" , |
127 | cl::desc("A textual description of the module pass pipeline inserted at " |
128 | "the PipelineStart extension point into default pipelines" ), |
129 | cl::Hidden); |
130 | static cl::opt<std::string> PipelineEarlySimplificationEPPipeline( |
131 | "passes-ep-pipeline-early-simplification" , |
132 | cl::desc("A textual description of the module pass pipeline inserted at " |
133 | "the EarlySimplification extension point into default pipelines" ), |
134 | cl::Hidden); |
135 | static cl::opt<std::string> OptimizerEarlyEPPipeline( |
136 | "passes-ep-optimizer-early" , |
137 | cl::desc("A textual description of the module pass pipeline inserted at " |
138 | "the OptimizerEarly extension point into default pipelines" ), |
139 | cl::Hidden); |
140 | static cl::opt<std::string> OptimizerLastEPPipeline( |
141 | "passes-ep-optimizer-last" , |
142 | cl::desc("A textual description of the module pass pipeline inserted at " |
143 | "the OptimizerLast extension point into default pipelines" ), |
144 | cl::Hidden); |
145 | static cl::opt<std::string> FullLinkTimeOptimizationEarlyEPPipeline( |
146 | "passes-ep-full-link-time-optimization-early" , |
147 | cl::desc("A textual description of the module pass pipeline inserted at " |
148 | "the FullLinkTimeOptimizationEarly extension point into default " |
149 | "pipelines" ), |
150 | cl::Hidden); |
151 | static cl::opt<std::string> FullLinkTimeOptimizationLastEPPipeline( |
152 | "passes-ep-full-link-time-optimization-last" , |
153 | cl::desc("A textual description of the module pass pipeline inserted at " |
154 | "the FullLinkTimeOptimizationLast extension point into default " |
155 | "pipelines" ), |
156 | cl::Hidden); |
157 | /// @}} |
158 | |
159 | static cl::opt<bool> DisablePipelineVerification( |
160 | "disable-pipeline-verification" , |
161 | cl::desc("Only has an effect when specified with -print-pipeline-passes. " |
162 | "Disables verifying that the textual pipeline generated by " |
163 | "-print-pipeline-passes can be used to create a pipeline." ), |
164 | cl::Hidden); |
165 | |
166 | |
167 | static cl::opt<PGOKind> |
168 | PGOKindFlag("pgo-kind" , cl::init(Val: NoPGO), cl::Hidden, |
169 | cl::desc("The kind of profile guided optimization" ), |
170 | cl::values(clEnumValN(NoPGO, "nopgo" , "Do not use PGO." ), |
171 | clEnumValN(InstrGen, "pgo-instr-gen-pipeline" , |
172 | "Instrument the IR to generate profile." ), |
173 | clEnumValN(InstrUse, "pgo-instr-use-pipeline" , |
174 | "Use instrumented profile to guide PGO." ), |
175 | clEnumValN(SampleUse, "pgo-sample-use-pipeline" , |
176 | "Use sampled profile to guide PGO." ))); |
177 | static cl::opt<std::string> ProfileFile("profile-file" , |
178 | cl::desc("Path to the profile." ), cl::Hidden); |
179 | static cl::opt<std::string> |
180 | MemoryProfileFile("memory-profile-file" , |
181 | cl::desc("Path to the memory profile." ), cl::Hidden); |
182 | |
183 | static cl::opt<CSPGOKind> CSPGOKindFlag( |
184 | "cspgo-kind" , cl::init(Val: NoCSPGO), cl::Hidden, |
185 | cl::desc("The kind of context sensitive profile guided optimization" ), |
186 | cl::values( |
187 | clEnumValN(NoCSPGO, "nocspgo" , "Do not use CSPGO." ), |
188 | clEnumValN( |
189 | CSInstrGen, "cspgo-instr-gen-pipeline" , |
190 | "Instrument (context sensitive) the IR to generate profile." ), |
191 | clEnumValN( |
192 | CSInstrUse, "cspgo-instr-use-pipeline" , |
193 | "Use instrumented (context sensitive) profile to guide PGO." ))); |
194 | |
195 | static cl::opt<std::string> CSProfileGenFile( |
196 | "cs-profilegen-file" , |
197 | cl::desc("Path to the instrumented context sensitive profile." ), |
198 | cl::Hidden); |
199 | |
200 | static cl::opt<std::string> |
201 | ProfileRemappingFile("profile-remapping-file" , |
202 | cl::desc("Path to the profile remapping file." ), |
203 | cl::Hidden); |
204 | |
205 | static cl::opt<PGOOptions::ColdFuncOpt> PGOColdFuncAttr( |
206 | "pgo-cold-func-opt" , cl::init(Val: PGOOptions::ColdFuncOpt::Default), cl::Hidden, |
207 | cl::desc( |
208 | "Function attribute to apply to cold functions as determined by PGO" ), |
209 | cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default" , |
210 | "Default (no attribute)" ), |
211 | clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize" , |
212 | "Mark cold functions with optsize." ), |
213 | clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize" , |
214 | "Mark cold functions with minsize." ), |
215 | clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone" , |
216 | "Mark cold functions with optnone." ))); |
217 | |
218 | static cl::opt<bool> DebugInfoForProfiling( |
219 | "debug-info-for-profiling" , cl::init(Val: false), cl::Hidden, |
220 | cl::desc("Emit special debug info to enable PGO profile generation." )); |
221 | |
222 | static cl::opt<bool> PseudoProbeForProfiling( |
223 | "pseudo-probe-for-profiling" , cl::init(Val: false), cl::Hidden, |
224 | cl::desc("Emit pseudo probes to enable PGO profile generation." )); |
225 | |
226 | static cl::opt<bool> DisableLoopUnrolling( |
227 | "disable-loop-unrolling" , |
228 | cl::desc("Disable loop unrolling in all relevant passes" ), cl::init(Val: false)); |
229 | |
230 | namespace llvm { |
231 | extern cl::opt<bool> PrintPipelinePasses; |
232 | } // namespace llvm |
233 | |
234 | template <typename PassManagerT> |
235 | bool tryParsePipelineText(PassBuilder &PB, |
236 | const cl::opt<std::string> &PipelineOpt) { |
237 | if (PipelineOpt.empty()) |
238 | return false; |
239 | |
240 | // Verify the pipeline is parseable: |
241 | PassManagerT PM; |
242 | if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) { |
243 | errs() << "Could not parse -" << PipelineOpt.ArgStr |
244 | << " pipeline: " << toString(std::move(Err)) |
245 | << "... I'm going to ignore it.\n" ; |
246 | return false; |
247 | } |
248 | return true; |
249 | } |
250 | |
251 | /// If one of the EPPipeline command line options was given, register callbacks |
252 | /// for parsing and inserting the given pipeline |
253 | static void registerEPCallbacks(PassBuilder &PB) { |
254 | if (tryParsePipelineText<FunctionPassManager>(PB, PipelineOpt: PeepholeEPPipeline)) |
255 | PB.registerPeepholeEPCallback( |
256 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
257 | ExitOnError Err("Unable to parse PeepholeEP pipeline: " ); |
258 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: PeepholeEPPipeline)); |
259 | }); |
260 | if (tryParsePipelineText<LoopPassManager>(PB, |
261 | PipelineOpt: LateLoopOptimizationsEPPipeline)) |
262 | PB.registerLateLoopOptimizationsEPCallback( |
263 | C: [&PB](LoopPassManager &PM, OptimizationLevel Level) { |
264 | ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: " ); |
265 | Err(PB.parsePassPipeline(LPM&: PM, PipelineText: LateLoopOptimizationsEPPipeline)); |
266 | }); |
267 | if (tryParsePipelineText<LoopPassManager>(PB, PipelineOpt: LoopOptimizerEndEPPipeline)) |
268 | PB.registerLoopOptimizerEndEPCallback( |
269 | C: [&PB](LoopPassManager &PM, OptimizationLevel Level) { |
270 | ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: " ); |
271 | Err(PB.parsePassPipeline(LPM&: PM, PipelineText: LoopOptimizerEndEPPipeline)); |
272 | }); |
273 | if (tryParsePipelineText<FunctionPassManager>(PB, |
274 | PipelineOpt: ScalarOptimizerLateEPPipeline)) |
275 | PB.registerScalarOptimizerLateEPCallback( |
276 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
277 | ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: " ); |
278 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: ScalarOptimizerLateEPPipeline)); |
279 | }); |
280 | if (tryParsePipelineText<CGSCCPassManager>(PB, PipelineOpt: CGSCCOptimizerLateEPPipeline)) |
281 | PB.registerCGSCCOptimizerLateEPCallback( |
282 | C: [&PB](CGSCCPassManager &PM, OptimizationLevel Level) { |
283 | ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: " ); |
284 | Err(PB.parsePassPipeline(CGPM&: PM, PipelineText: CGSCCOptimizerLateEPPipeline)); |
285 | }); |
286 | if (tryParsePipelineText<FunctionPassManager>(PB, PipelineOpt: VectorizerStartEPPipeline)) |
287 | PB.registerVectorizerStartEPCallback( |
288 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
289 | ExitOnError Err("Unable to parse VectorizerStartEP pipeline: " ); |
290 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: VectorizerStartEPPipeline)); |
291 | }); |
292 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: PipelineStartEPPipeline)) |
293 | PB.registerPipelineStartEPCallback( |
294 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
295 | ExitOnError Err("Unable to parse PipelineStartEP pipeline: " ); |
296 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: PipelineStartEPPipeline)); |
297 | }); |
298 | if (tryParsePipelineText<ModulePassManager>( |
299 | PB, PipelineOpt: PipelineEarlySimplificationEPPipeline)) |
300 | PB.registerPipelineEarlySimplificationEPCallback( |
301 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
302 | ExitOnError Err("Unable to parse EarlySimplification pipeline: " ); |
303 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: PipelineEarlySimplificationEPPipeline)); |
304 | }); |
305 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: OptimizerEarlyEPPipeline)) |
306 | PB.registerOptimizerEarlyEPCallback( |
307 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
308 | ExitOnError Err("Unable to parse OptimizerEarlyEP pipeline: " ); |
309 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: OptimizerEarlyEPPipeline)); |
310 | }); |
311 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: OptimizerLastEPPipeline)) |
312 | PB.registerOptimizerLastEPCallback( |
313 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
314 | ExitOnError Err("Unable to parse OptimizerLastEP pipeline: " ); |
315 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: OptimizerLastEPPipeline)); |
316 | }); |
317 | if (tryParsePipelineText<ModulePassManager>( |
318 | PB, PipelineOpt: FullLinkTimeOptimizationEarlyEPPipeline)) |
319 | PB.registerFullLinkTimeOptimizationEarlyEPCallback( |
320 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
321 | ExitOnError Err( |
322 | "Unable to parse FullLinkTimeOptimizationEarlyEP pipeline: " ); |
323 | Err(PB.parsePassPipeline(MPM&: PM, |
324 | PipelineText: FullLinkTimeOptimizationEarlyEPPipeline)); |
325 | }); |
326 | if (tryParsePipelineText<ModulePassManager>( |
327 | PB, PipelineOpt: FullLinkTimeOptimizationLastEPPipeline)) |
328 | PB.registerFullLinkTimeOptimizationLastEPCallback( |
329 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
330 | ExitOnError Err( |
331 | "Unable to parse FullLinkTimeOptimizationLastEP pipeline: " ); |
332 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: FullLinkTimeOptimizationLastEPPipeline)); |
333 | }); |
334 | } |
335 | |
336 | #define HANDLE_EXTENSION(Ext) \ |
337 | llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); |
338 | #include "llvm/Support/Extension.def" |
339 | |
340 | bool llvm::runPassPipeline( |
341 | StringRef Arg0, Module &M, TargetMachine *TM, TargetLibraryInfoImpl *TLII, |
342 | ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut, |
343 | ToolOutputFile *, StringRef PassPipeline, |
344 | ArrayRef<PassPlugin> PassPlugins, |
345 | ArrayRef<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks, |
346 | OutputKind OK, VerifierKind VK, bool ShouldPreserveAssemblyUseListOrder, |
347 | bool ShouldPreserveBitcodeUseListOrder, bool EmitSummaryIndex, |
348 | bool EmitModuleHash, bool EnableDebugify, bool VerifyDIPreserve, |
349 | bool UnifiedLTO) { |
350 | bool VerifyEachPass = VK == VK_VerifyEachPass; |
351 | |
352 | auto FS = vfs::getRealFileSystem(); |
353 | std::optional<PGOOptions> P; |
354 | switch (PGOKindFlag) { |
355 | case InstrGen: |
356 | P = PGOOptions(ProfileFile, "" , "" , MemoryProfileFile, FS, |
357 | PGOOptions::IRInstr, PGOOptions::NoCSAction, |
358 | PGOColdFuncAttr); |
359 | break; |
360 | case InstrUse: |
361 | P = PGOOptions(ProfileFile, "" , ProfileRemappingFile, MemoryProfileFile, FS, |
362 | PGOOptions::IRUse, PGOOptions::NoCSAction, PGOColdFuncAttr); |
363 | break; |
364 | case SampleUse: |
365 | P = PGOOptions(ProfileFile, "" , ProfileRemappingFile, MemoryProfileFile, FS, |
366 | PGOOptions::SampleUse, PGOOptions::NoCSAction, |
367 | PGOColdFuncAttr); |
368 | break; |
369 | case NoPGO: |
370 | if (DebugInfoForProfiling || PseudoProbeForProfiling || |
371 | !MemoryProfileFile.empty()) |
372 | P = PGOOptions("" , "" , "" , MemoryProfileFile, FS, PGOOptions::NoAction, |
373 | PGOOptions::NoCSAction, PGOColdFuncAttr, |
374 | DebugInfoForProfiling, PseudoProbeForProfiling); |
375 | else |
376 | P = std::nullopt; |
377 | } |
378 | if (CSPGOKindFlag != NoCSPGO) { |
379 | if (P && (P->Action == PGOOptions::IRInstr || |
380 | P->Action == PGOOptions::SampleUse)) { |
381 | errs() << "CSPGOKind cannot be used with IRInstr or SampleUse" ; |
382 | return false; |
383 | } |
384 | if (CSPGOKindFlag == CSInstrGen) { |
385 | if (CSProfileGenFile.empty()) { |
386 | errs() << "CSInstrGen needs to specify CSProfileGenFile" ; |
387 | return false; |
388 | } |
389 | if (P) { |
390 | P->CSAction = PGOOptions::CSIRInstr; |
391 | P->CSProfileGenFile = CSProfileGenFile; |
392 | } else |
393 | P = PGOOptions("" , CSProfileGenFile, ProfileRemappingFile, |
394 | /*MemoryProfile=*/"" , FS, PGOOptions::NoAction, |
395 | PGOOptions::CSIRInstr); |
396 | } else /* CSPGOKindFlag == CSInstrUse */ { |
397 | if (!P) { |
398 | errs() << "CSInstrUse needs to be together with InstrUse" ; |
399 | return false; |
400 | } |
401 | P->CSAction = PGOOptions::CSIRUse; |
402 | } |
403 | } |
404 | if (TM) |
405 | TM->setPGOOption(P); |
406 | |
407 | LoopAnalysisManager LAM; |
408 | FunctionAnalysisManager FAM; |
409 | CGSCCAnalysisManager CGAM; |
410 | ModuleAnalysisManager MAM; |
411 | |
412 | PassInstrumentationCallbacks PIC; |
413 | PrintPassOptions PrintPassOpts; |
414 | PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose; |
415 | PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet; |
416 | StandardInstrumentations SI(M.getContext(), DebugPM != DebugLogging::None, |
417 | VerifyEachPass, PrintPassOpts); |
418 | SI.registerCallbacks(PIC, MAM: &MAM); |
419 | DebugifyEachInstrumentation Debugify; |
420 | DebugifyStatsMap DIStatsMap; |
421 | DebugInfoPerPass DebugInfoBeforePass; |
422 | if (DebugifyEach) { |
423 | Debugify.setDIStatsMap(DIStatsMap); |
424 | Debugify.setDebugifyMode(DebugifyMode::SyntheticDebugInfo); |
425 | Debugify.registerCallbacks(PIC, MAM); |
426 | } else if (VerifyEachDebugInfoPreserve) { |
427 | Debugify.setDebugInfoBeforePass(DebugInfoBeforePass); |
428 | Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo); |
429 | Debugify.setOrigDIVerifyBugsReportFilePath( |
430 | VerifyDIPreserveExport); |
431 | Debugify.registerCallbacks(PIC, MAM); |
432 | } |
433 | |
434 | PipelineTuningOptions PTO; |
435 | // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized |
436 | // to false above so we shouldn't necessarily need to check whether or not the |
437 | // option has been enabled. |
438 | PTO.LoopUnrolling = !DisableLoopUnrolling; |
439 | PTO.UnifiedLTO = UnifiedLTO; |
440 | PassBuilder PB(TM, PTO, P, &PIC); |
441 | registerEPCallbacks(PB); |
442 | |
443 | // For any loaded plugins, let them register pass builder callbacks. |
444 | for (auto &PassPlugin : PassPlugins) |
445 | PassPlugin.registerPassBuilderCallbacks(PB); |
446 | |
447 | // Load any explicitly specified plugins. |
448 | for (auto &PassCallback : PassBuilderCallbacks) |
449 | PassCallback(PB); |
450 | |
451 | #define HANDLE_EXTENSION(Ext) \ |
452 | get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); |
453 | #include "llvm/Support/Extension.def" |
454 | |
455 | // Specially handle the alias analysis manager so that we can register |
456 | // a custom pipeline of AA passes with it. |
457 | AAManager AA; |
458 | if (auto Err = PB.parseAAPipeline(AA, PipelineText: AAPipeline)) { |
459 | errs() << Arg0 << ": " << toString(E: std::move(Err)) << "\n" ; |
460 | return false; |
461 | } |
462 | |
463 | // Register the AA manager first so that our version is the one used. |
464 | FAM.registerPass(PassBuilder: [&] { return std::move(AA); }); |
465 | // Register our TargetLibraryInfoImpl. |
466 | FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(*TLII); }); |
467 | |
468 | // Register all the basic analyses with the managers. |
469 | PB.registerModuleAnalyses(MAM); |
470 | PB.registerCGSCCAnalyses(CGAM); |
471 | PB.registerFunctionAnalyses(FAM); |
472 | PB.registerLoopAnalyses(LAM); |
473 | PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); |
474 | |
475 | ModulePassManager MPM; |
476 | if (EnableDebugify) |
477 | MPM.addPass(Pass: NewPMDebugifyPass()); |
478 | if (VerifyDIPreserve) |
479 | MPM.addPass(Pass: NewPMDebugifyPass(DebugifyMode::OriginalDebugInfo, "" , |
480 | &DebugInfoBeforePass)); |
481 | |
482 | // Add passes according to the -passes options. |
483 | if (!PassPipeline.empty()) { |
484 | if (auto Err = PB.parsePassPipeline(MPM, PipelineText: PassPipeline)) { |
485 | errs() << Arg0 << ": " << toString(E: std::move(Err)) << "\n" ; |
486 | return false; |
487 | } |
488 | } |
489 | |
490 | if (VK > VK_NoVerifier) |
491 | MPM.addPass(Pass: VerifierPass()); |
492 | if (EnableDebugify) |
493 | MPM.addPass(Pass: NewPMCheckDebugifyPass(false, "" , &DIStatsMap)); |
494 | if (VerifyDIPreserve) |
495 | MPM.addPass(Pass: NewPMCheckDebugifyPass( |
496 | false, "" , nullptr, DebugifyMode::OriginalDebugInfo, |
497 | &DebugInfoBeforePass, VerifyDIPreserveExport)); |
498 | |
499 | // Add any relevant output pass at the end of the pipeline. |
500 | switch (OK) { |
501 | case OK_NoOutput: |
502 | break; // No output pass needed. |
503 | case OK_OutputAssembly: |
504 | MPM.addPass(Pass: PrintModulePass( |
505 | Out->os(), "" , ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex)); |
506 | break; |
507 | case OK_OutputBitcode: |
508 | MPM.addPass(Pass: BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder, |
509 | EmitSummaryIndex, EmitModuleHash)); |
510 | break; |
511 | case OK_OutputThinLTOBitcode: |
512 | MPM.addPass(Pass: ThinLTOBitcodeWriterPass( |
513 | Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr)); |
514 | break; |
515 | } |
516 | |
517 | // Before executing passes, print the final values of the LLVM options. |
518 | cl::PrintOptionValues(); |
519 | |
520 | // Print a textual, '-passes=' compatible, representation of pipeline if |
521 | // requested. |
522 | if (PrintPipelinePasses) { |
523 | std::string Pipeline; |
524 | raw_string_ostream SOS(Pipeline); |
525 | MPM.printPipeline(OS&: SOS, MapClassName2PassName: [&PIC](StringRef ClassName) { |
526 | auto PassName = PIC.getPassNameForClassName(ClassName); |
527 | return PassName.empty() ? ClassName : PassName; |
528 | }); |
529 | outs() << Pipeline; |
530 | outs() << "\n" ; |
531 | |
532 | if (!DisablePipelineVerification) { |
533 | // Check that we can parse the returned pipeline string as an actual |
534 | // pipeline. |
535 | ModulePassManager TempPM; |
536 | if (auto Err = PB.parsePassPipeline(MPM&: TempPM, PipelineText: Pipeline)) { |
537 | errs() << "Could not parse dumped pass pipeline: " |
538 | << toString(E: std::move(Err)) << "\n" ; |
539 | return false; |
540 | } |
541 | } |
542 | |
543 | return true; |
544 | } |
545 | |
546 | // Now that we have all of the passes ready, run them. |
547 | MPM.run(IR&: M, AM&: MAM); |
548 | |
549 | // Declare success. |
550 | if (OK != OK_NoOutput) { |
551 | Out->keep(); |
552 | if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut) |
553 | ThinLTOLinkOut->keep(); |
554 | } |
555 | |
556 | if (OptRemarkFile) |
557 | OptRemarkFile->keep(); |
558 | |
559 | if (DebugifyEach && !DebugifyExport.empty()) |
560 | exportDebugifyStats(Path: DebugifyExport, Map: Debugify.getDebugifyStatsMap()); |
561 | |
562 | return true; |
563 | } |
564 | |
565 | void llvm::printPasses(raw_ostream &OS) { |
566 | PassBuilder PB; |
567 | PB.printPassNames(OS); |
568 | } |
569 | |