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