1 | //===- optdriver.cpp - The LLVM Modular Optimizer -------------------------===// |
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 | // |
9 | // Optimizations may be specified an arbitrary number of times on the command |
10 | // line, They are run in the order specified. Common driver library for re-use |
11 | // by potential downstream opt-variants. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "NewPMDriver.h" |
16 | #include "llvm/Analysis/CallGraph.h" |
17 | #include "llvm/Analysis/CallGraphSCCPass.h" |
18 | #include "llvm/Analysis/LoopPass.h" |
19 | #include "llvm/Analysis/RegionPass.h" |
20 | #include "llvm/Analysis/TargetLibraryInfo.h" |
21 | #include "llvm/Analysis/TargetTransformInfo.h" |
22 | #include "llvm/AsmParser/Parser.h" |
23 | #include "llvm/CodeGen/CommandFlags.h" |
24 | #include "llvm/CodeGen/TargetPassConfig.h" |
25 | #include "llvm/Config/llvm-config.h" |
26 | #include "llvm/IR/DataLayout.h" |
27 | #include "llvm/IR/DebugInfo.h" |
28 | #include "llvm/IR/LLVMContext.h" |
29 | #include "llvm/IR/LLVMRemarkStreamer.h" |
30 | #include "llvm/IR/LegacyPassManager.h" |
31 | #include "llvm/IR/LegacyPassNameParser.h" |
32 | #include "llvm/IR/Module.h" |
33 | #include "llvm/IR/ModuleSummaryIndex.h" |
34 | #include "llvm/IR/Verifier.h" |
35 | #include "llvm/IRReader/IRReader.h" |
36 | #include "llvm/InitializePasses.h" |
37 | #include "llvm/LinkAllIR.h" |
38 | #include "llvm/LinkAllPasses.h" |
39 | #include "llvm/MC/TargetRegistry.h" |
40 | #include "llvm/Passes/PassPlugin.h" |
41 | #include "llvm/Remarks/HotnessThresholdParser.h" |
42 | #include "llvm/Support/Debug.h" |
43 | #include "llvm/Support/ErrorHandling.h" |
44 | #include "llvm/Support/FileSystem.h" |
45 | #include "llvm/Support/InitLLVM.h" |
46 | #include "llvm/Support/PluginLoader.h" |
47 | #include "llvm/Support/SourceMgr.h" |
48 | #include "llvm/Support/SystemUtils.h" |
49 | #include "llvm/Support/TargetSelect.h" |
50 | #include "llvm/Support/ToolOutputFile.h" |
51 | #include "llvm/Support/YAMLTraits.h" |
52 | #include "llvm/Target/TargetMachine.h" |
53 | #include "llvm/TargetParser/Host.h" |
54 | #include "llvm/TargetParser/SubtargetFeature.h" |
55 | #include "llvm/TargetParser/Triple.h" |
56 | #include "llvm/Transforms/IPO/WholeProgramDevirt.h" |
57 | #include "llvm/Transforms/Utils/Cloning.h" |
58 | #include "llvm/Transforms/Utils/Debugify.h" |
59 | #include <algorithm> |
60 | #include <memory> |
61 | #include <optional> |
62 | using namespace llvm; |
63 | using namespace opt_tool; |
64 | |
65 | static codegen::RegisterCodeGenFlags CFG; |
66 | |
67 | // The OptimizationList is automatically populated with registered Passes by the |
68 | // PassNameParser. |
69 | static cl::list<const PassInfo *, bool, PassNameParser> PassList(cl::desc( |
70 | "Optimizations available (use '-passes=' for the new pass manager)" )); |
71 | |
72 | static cl::opt<bool> EnableLegacyPassManager( |
73 | "bugpoint-enable-legacy-pm" , |
74 | cl::desc( |
75 | "Enable the legacy pass manager. This is strictly for bugpoint " |
76 | "due to it not working with the new PM, please do not use otherwise." ), |
77 | cl::init(Val: false)); |
78 | |
79 | // This flag specifies a textual description of the optimization pass pipeline |
80 | // to run over the module. This flag switches opt to use the new pass manager |
81 | // infrastructure, completely disabling all of the flags specific to the old |
82 | // pass management. |
83 | static cl::opt<std::string> PassPipeline( |
84 | "passes" , |
85 | cl::desc( |
86 | "A textual description of the pass pipeline. To have analysis passes " |
87 | "available before a certain pass, add 'require<foo-analysis>'." )); |
88 | static cl::alias PassPipeline2("p" , cl::aliasopt(PassPipeline), |
89 | cl::desc("Alias for -passes" )); |
90 | |
91 | static cl::opt<bool> PrintPasses("print-passes" , |
92 | cl::desc("Print available passes that can be " |
93 | "specified in -passes=foo and exit" )); |
94 | |
95 | static cl::opt<std::string> InputFilename(cl::Positional, |
96 | cl::desc("<input bitcode file>" ), |
97 | cl::init(Val: "-" ), |
98 | cl::value_desc("filename" )); |
99 | |
100 | static cl::opt<std::string> OutputFilename("o" , |
101 | cl::desc("Override output filename" ), |
102 | cl::value_desc("filename" )); |
103 | |
104 | static cl::opt<bool> Force("f" , cl::desc("Enable binary output on terminals" )); |
105 | |
106 | static cl::opt<bool> NoOutput("disable-output" , |
107 | cl::desc("Do not write result bitcode file" ), |
108 | cl::Hidden); |
109 | |
110 | static cl::opt<bool> OutputAssembly("S" , |
111 | cl::desc("Write output as LLVM assembly" )); |
112 | |
113 | static cl::opt<bool> |
114 | OutputThinLTOBC("thinlto-bc" , |
115 | cl::desc("Write output as ThinLTO-ready bitcode" )); |
116 | |
117 | static cl::opt<bool> |
118 | SplitLTOUnit("thinlto-split-lto-unit" , |
119 | cl::desc("Enable splitting of a ThinLTO LTOUnit" )); |
120 | |
121 | static cl::opt<bool> |
122 | UnifiedLTO("unified-lto" , |
123 | cl::desc("Use unified LTO piplines. Ignored unless -thinlto-bc " |
124 | "is also specified." ), |
125 | cl::Hidden, cl::init(Val: false)); |
126 | |
127 | static cl::opt<std::string> ThinLinkBitcodeFile( |
128 | "thin-link-bitcode-file" , cl::value_desc("filename" ), |
129 | cl::desc( |
130 | "A file in which to write minimized bitcode for the thin link only" )); |
131 | |
132 | static cl::opt<bool> NoVerify("disable-verify" , |
133 | cl::desc("Do not run the verifier" ), cl::Hidden); |
134 | |
135 | static cl::opt<bool> NoUpgradeDebugInfo("disable-upgrade-debug-info" , |
136 | cl::desc("Generate invalid output" ), |
137 | cl::ReallyHidden); |
138 | |
139 | static cl::opt<bool> VerifyEach("verify-each" , |
140 | cl::desc("Verify after each transform" )); |
141 | |
142 | static cl::opt<bool> |
143 | DisableDITypeMap("disable-debug-info-type-map" , |
144 | cl::desc("Don't use a uniquing type map for debug info" )); |
145 | |
146 | static cl::opt<bool> |
147 | StripDebug("strip-debug" , |
148 | cl::desc("Strip debugger symbol info from translation unit" )); |
149 | |
150 | static cl::opt<bool> |
151 | StripNamedMetadata("strip-named-metadata" , |
152 | cl::desc("Strip module-level named metadata" )); |
153 | |
154 | static cl::opt<bool> |
155 | OptLevelO0("O0" , cl::desc("Optimization level 0. Similar to clang -O0. " |
156 | "Same as -passes='default<O0>'" )); |
157 | |
158 | static cl::opt<bool> |
159 | OptLevelO1("O1" , cl::desc("Optimization level 1. Similar to clang -O1. " |
160 | "Same as -passes='default<O1>'" )); |
161 | |
162 | static cl::opt<bool> |
163 | OptLevelO2("O2" , cl::desc("Optimization level 2. Similar to clang -O2. " |
164 | "Same as -passes='default<O2>'" )); |
165 | |
166 | static cl::opt<bool> |
167 | OptLevelOs("Os" , cl::desc("Like -O2 but size-conscious. Similar to clang " |
168 | "-Os. Same as -passes='default<Os>'" )); |
169 | |
170 | static cl::opt<bool> OptLevelOz( |
171 | "Oz" , |
172 | cl::desc("Like -O2 but optimize for code size above all else. Similar to " |
173 | "clang -Oz. Same as -passes='default<Oz>'" )); |
174 | |
175 | static cl::opt<bool> |
176 | OptLevelO3("O3" , cl::desc("Optimization level 3. Similar to clang -O3. " |
177 | "Same as -passes='default<O3>'" )); |
178 | |
179 | static cl::opt<unsigned> CodeGenOptLevelCL( |
180 | "codegen-opt-level" , |
181 | cl::desc("Override optimization level for codegen hooks, legacy PM only" )); |
182 | |
183 | static cl::opt<std::string> |
184 | TargetTriple("mtriple" , cl::desc("Override target triple for module" )); |
185 | |
186 | static cl::opt<bool> EmitSummaryIndex("module-summary" , |
187 | cl::desc("Emit module summary index" ), |
188 | cl::init(Val: false)); |
189 | |
190 | static cl::opt<bool> EmitModuleHash("module-hash" , cl::desc("Emit module hash" ), |
191 | cl::init(Val: false)); |
192 | |
193 | static cl::opt<bool> |
194 | DisableSimplifyLibCalls("disable-simplify-libcalls" , |
195 | cl::desc("Disable simplify-libcalls" )); |
196 | |
197 | static cl::list<std::string> DisableBuiltins( |
198 | "disable-builtin" , |
199 | cl::desc("Disable specific target library builtin function" )); |
200 | |
201 | static cl::opt<bool> EnableDebugify( |
202 | "enable-debugify" , |
203 | cl::desc( |
204 | "Start the pipeline with debugify and end it with check-debugify" )); |
205 | |
206 | static cl::opt<bool> VerifyDebugInfoPreserve( |
207 | "verify-debuginfo-preserve" , |
208 | cl::desc("Start the pipeline with collecting and end it with checking of " |
209 | "debug info preservation." )); |
210 | |
211 | static cl::opt<std::string> ClDataLayout("data-layout" , |
212 | cl::desc("data layout string to use" ), |
213 | cl::value_desc("layout-string" ), |
214 | cl::init(Val: "" )); |
215 | |
216 | static cl::opt<bool> PreserveBitcodeUseListOrder( |
217 | "preserve-bc-uselistorder" , |
218 | cl::desc("Preserve use-list order when writing LLVM bitcode." ), |
219 | cl::init(Val: true), cl::Hidden); |
220 | |
221 | static cl::opt<bool> PreserveAssemblyUseListOrder( |
222 | "preserve-ll-uselistorder" , |
223 | cl::desc("Preserve use-list order when writing LLVM assembly." ), |
224 | cl::init(Val: false), cl::Hidden); |
225 | |
226 | static cl::opt<bool> RunTwice("run-twice" , |
227 | cl::desc("Run all passes twice, re-using the " |
228 | "same pass manager (legacy PM only)." ), |
229 | cl::init(Val: false), cl::Hidden); |
230 | |
231 | static cl::opt<bool> DiscardValueNames( |
232 | "discard-value-names" , |
233 | cl::desc("Discard names from Value (other than GlobalValue)." ), |
234 | cl::init(Val: false), cl::Hidden); |
235 | |
236 | static cl::opt<bool> TimeTrace("time-trace" , cl::desc("Record time trace" )); |
237 | |
238 | static cl::opt<unsigned> TimeTraceGranularity( |
239 | "time-trace-granularity" , |
240 | cl::desc( |
241 | "Minimum time granularity (in microseconds) traced by time profiler" ), |
242 | cl::init(Val: 500), cl::Hidden); |
243 | |
244 | static cl::opt<std::string> |
245 | TimeTraceFile("time-trace-file" , |
246 | cl::desc("Specify time trace file destination" ), |
247 | cl::value_desc("filename" )); |
248 | |
249 | static cl::opt<bool> ( |
250 | "pass-remarks-with-hotness" , |
251 | cl::desc("With PGO, include profile count in optimization remarks" ), |
252 | cl::Hidden); |
253 | |
254 | static cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser> |
255 | ( |
256 | "pass-remarks-hotness-threshold" , |
257 | cl::desc("Minimum profile count required for " |
258 | "an optimization remark to be output. " |
259 | "Use 'auto' to apply the threshold from profile summary" ), |
260 | cl::value_desc("N or 'auto'" ), cl::init(Val: 0), cl::Hidden); |
261 | |
262 | static cl::opt<std::string> |
263 | ("pass-remarks-output" , |
264 | cl::desc("Output filename for pass remarks" ), |
265 | cl::value_desc("filename" )); |
266 | |
267 | static cl::opt<std::string> |
268 | ("pass-remarks-filter" , |
269 | cl::desc("Only record optimization remarks from passes whose " |
270 | "names match the given regular expression" ), |
271 | cl::value_desc("regex" )); |
272 | |
273 | static cl::opt<std::string> ( |
274 | "pass-remarks-format" , |
275 | cl::desc("The format used for serializing remarks (default: YAML)" ), |
276 | cl::value_desc("format" ), cl::init(Val: "yaml" )); |
277 | |
278 | static cl::list<std::string> |
279 | PassPlugins("load-pass-plugin" , |
280 | cl::desc("Load passes from plugin library" )); |
281 | |
282 | static cl::opt<bool> TryUseNewDbgInfoFormat( |
283 | "try-experimental-debuginfo-iterators" , |
284 | cl::desc("Enable debuginfo iterator positions, if they're built in" ), |
285 | cl::init(Val: false), cl::Hidden); |
286 | |
287 | extern cl::opt<bool> UseNewDbgInfoFormat; |
288 | |
289 | //===----------------------------------------------------------------------===// |
290 | // CodeGen-related helper functions. |
291 | // |
292 | |
293 | static CodeGenOptLevel GetCodeGenOptLevel() { |
294 | return static_cast<CodeGenOptLevel>(unsigned(CodeGenOptLevelCL)); |
295 | } |
296 | |
297 | struct TimeTracerRAII { |
298 | TimeTracerRAII(StringRef ProgramName) { |
299 | if (TimeTrace) |
300 | timeTraceProfilerInitialize(TimeTraceGranularity, ProcName: ProgramName); |
301 | } |
302 | ~TimeTracerRAII() { |
303 | if (TimeTrace) { |
304 | if (auto E = timeTraceProfilerWrite(PreferredFileName: TimeTraceFile, FallbackFileName: OutputFilename)) { |
305 | handleAllErrors(E: std::move(E), Handlers: [&](const StringError &SE) { |
306 | errs() << SE.getMessage() << "\n" ; |
307 | }); |
308 | return; |
309 | } |
310 | timeTraceProfilerCleanup(); |
311 | } |
312 | } |
313 | }; |
314 | |
315 | // For use in NPM transition. Currently this contains most codegen-specific |
316 | // passes. Remove passes from here when porting to the NPM. |
317 | // TODO: use a codegen version of PassRegistry.def/PassBuilder::is*Pass() once |
318 | // it exists. |
319 | static bool shouldPinPassToLegacyPM(StringRef Pass) { |
320 | std::vector<StringRef> PassNameExactToIgnore = { |
321 | "nvvm-reflect" , |
322 | "nvvm-intr-range" , |
323 | "amdgpu-simplifylib" , |
324 | "amdgpu-image-intrinsic-opt" , |
325 | "amdgpu-usenative" , |
326 | "amdgpu-promote-alloca" , |
327 | "amdgpu-promote-alloca-to-vector" , |
328 | "amdgpu-lower-kernel-attributes" , |
329 | "amdgpu-propagate-attributes-early" , |
330 | "amdgpu-propagate-attributes-late" , |
331 | "amdgpu-unify-metadata" , |
332 | "amdgpu-printf-runtime-binding" , |
333 | "amdgpu-always-inline" }; |
334 | if (llvm::is_contained(Range&: PassNameExactToIgnore, Element: Pass)) |
335 | return false; |
336 | |
337 | std::vector<StringRef> PassNamePrefix = { |
338 | "x86-" , "xcore-" , "wasm-" , "systemz-" , "ppc-" , "nvvm-" , |
339 | "nvptx-" , "mips-" , "lanai-" , "hexagon-" , "bpf-" , "avr-" , |
340 | "thumb2-" , "arm-" , "si-" , "gcn-" , "amdgpu-" , "aarch64-" , |
341 | "amdgcn-" , "polly-" , "riscv-" , "dxil-" }; |
342 | std::vector<StringRef> PassNameContain = {"-eh-prepare" }; |
343 | std::vector<StringRef> PassNameExact = { |
344 | "safe-stack" , |
345 | "cost-model" , |
346 | "codegenprepare" , |
347 | "interleaved-load-combine" , |
348 | "unreachableblockelim" , |
349 | "verify-safepoint-ir" , |
350 | "atomic-expand" , |
351 | "expandvp" , |
352 | "mve-tail-predication" , |
353 | "interleaved-access" , |
354 | "global-merge" , |
355 | "pre-isel-intrinsic-lowering" , |
356 | "expand-reductions" , |
357 | "indirectbr-expand" , |
358 | "generic-to-nvvm" , |
359 | "expand-memcmp" , |
360 | "loop-reduce" , |
361 | "lower-amx-type" , |
362 | "lower-amx-intrinsics" , |
363 | "polyhedral-info" , |
364 | "print-polyhedral-info" , |
365 | "replace-with-veclib" , |
366 | "jmc-instrumenter" , |
367 | "dot-regions" , |
368 | "dot-regions-only" , |
369 | "view-regions" , |
370 | "view-regions-only" , |
371 | "select-optimize" , |
372 | "expand-large-div-rem" , |
373 | "structurizecfg" , |
374 | "fix-irreducible" , |
375 | "expand-large-fp-convert" , |
376 | "callbrprepare" , |
377 | }; |
378 | for (const auto &P : PassNamePrefix) |
379 | if (Pass.starts_with(Prefix: P)) |
380 | return true; |
381 | for (const auto &P : PassNameContain) |
382 | if (Pass.contains(Other: P)) |
383 | return true; |
384 | return llvm::is_contained(Range&: PassNameExact, Element: Pass); |
385 | } |
386 | |
387 | // For use in NPM transition. |
388 | static bool shouldForceLegacyPM() { |
389 | for (const auto &P : PassList) { |
390 | StringRef Arg = P->getPassArgument(); |
391 | if (shouldPinPassToLegacyPM(Pass: Arg)) |
392 | return true; |
393 | } |
394 | return false; |
395 | } |
396 | |
397 | //===----------------------------------------------------------------------===// |
398 | // main for opt |
399 | // |
400 | extern "C" int optMain( |
401 | int argc, char **argv, |
402 | ArrayRef<std::function<void(llvm::PassBuilder &)>> PassBuilderCallbacks) { |
403 | InitLLVM X(argc, argv); |
404 | |
405 | // Enable debug stream buffering. |
406 | EnableDebugBuffering = true; |
407 | |
408 | InitializeAllTargets(); |
409 | InitializeAllTargetMCs(); |
410 | InitializeAllAsmPrinters(); |
411 | InitializeAllAsmParsers(); |
412 | |
413 | // Initialize passes |
414 | PassRegistry &Registry = *PassRegistry::getPassRegistry(); |
415 | initializeCore(Registry); |
416 | initializeScalarOpts(Registry); |
417 | initializeVectorization(Registry); |
418 | initializeIPO(Registry); |
419 | initializeAnalysis(Registry); |
420 | initializeTransformUtils(Registry); |
421 | initializeInstCombine(Registry); |
422 | initializeTarget(Registry); |
423 | // For codegen passes, only passes that do IR to IR transformation are |
424 | // supported. |
425 | initializeExpandLargeDivRemLegacyPassPass(Registry); |
426 | initializeExpandLargeFpConvertLegacyPassPass(Registry); |
427 | initializeExpandMemCmpLegacyPassPass(Registry); |
428 | initializeScalarizeMaskedMemIntrinLegacyPassPass(Registry); |
429 | initializeSelectOptimizePass(Registry); |
430 | initializeCallBrPreparePass(Registry); |
431 | initializeCodeGenPrepareLegacyPassPass(Registry); |
432 | initializeAtomicExpandPass(Registry); |
433 | initializeWinEHPreparePass(Registry); |
434 | initializeDwarfEHPrepareLegacyPassPass(Registry); |
435 | initializeSafeStackLegacyPassPass(Registry); |
436 | initializeSjLjEHPreparePass(Registry); |
437 | initializePreISelIntrinsicLoweringLegacyPassPass(Registry); |
438 | initializeGlobalMergePass(Registry); |
439 | initializeIndirectBrExpandLegacyPassPass(Registry); |
440 | initializeInterleavedLoadCombinePass(Registry); |
441 | initializeInterleavedAccessPass(Registry); |
442 | initializeUnreachableBlockElimLegacyPassPass(Registry); |
443 | initializeExpandReductionsPass(Registry); |
444 | initializeExpandVectorPredicationPass(Registry); |
445 | initializeWasmEHPreparePass(Registry); |
446 | initializeWriteBitcodePassPass(Registry); |
447 | initializeReplaceWithVeclibLegacyPass(Registry); |
448 | initializeJMCInstrumenterPass(Registry); |
449 | |
450 | SmallVector<PassPlugin, 1> PluginList; |
451 | PassPlugins.setCallback([&](const std::string &PluginPath) { |
452 | auto Plugin = PassPlugin::Load(Filename: PluginPath); |
453 | if (!Plugin) |
454 | report_fatal_error(Err: Plugin.takeError(), /*gen_crash_diag=*/false); |
455 | PluginList.emplace_back(Args&: Plugin.get()); |
456 | }); |
457 | |
458 | // Register the Target and CPU printer for --version. |
459 | cl::AddExtraVersionPrinter(func: sys::printDefaultTargetAndDetectedCPU); |
460 | |
461 | cl::ParseCommandLineOptions( |
462 | argc, argv, Overview: "llvm .bc -> .bc modular optimizer and analysis printer\n" ); |
463 | |
464 | // RemoveDIs debug-info transition: tests may request that we /try/ to use the |
465 | // new debug-info format. |
466 | if (TryUseNewDbgInfoFormat) { |
467 | // Turn the new debug-info format on. |
468 | UseNewDbgInfoFormat = true; |
469 | } |
470 | |
471 | LLVMContext Context; |
472 | |
473 | // TODO: remove shouldForceLegacyPM(). |
474 | const bool UseNPM = (!EnableLegacyPassManager && !shouldForceLegacyPM()) || |
475 | PassPipeline.getNumOccurrences() > 0; |
476 | |
477 | if (UseNPM && !PassList.empty()) { |
478 | errs() << "The `opt -passname` syntax for the new pass manager is " |
479 | "not supported, please use `opt -passes=<pipeline>` (or the `-p` " |
480 | "alias for a more concise version).\n" ; |
481 | errs() << "See https://llvm.org/docs/NewPassManager.html#invoking-opt " |
482 | "for more details on the pass pipeline syntax.\n\n" ; |
483 | return 1; |
484 | } |
485 | |
486 | if (!UseNPM && PluginList.size()) { |
487 | errs() << argv[0] << ": " << PassPlugins.ArgStr |
488 | << " specified with legacy PM.\n" ; |
489 | return 1; |
490 | } |
491 | |
492 | // FIXME: once the legacy PM code is deleted, move runPassPipeline() here and |
493 | // construct the PassBuilder before parsing IR so we can reuse the same |
494 | // PassBuilder for print passes. |
495 | if (PrintPasses) { |
496 | printPasses(OS&: outs()); |
497 | return 0; |
498 | } |
499 | |
500 | TimeTracerRAII TimeTracer(argv[0]); |
501 | |
502 | SMDiagnostic Err; |
503 | |
504 | Context.setDiscardValueNames(DiscardValueNames); |
505 | if (!DisableDITypeMap) |
506 | Context.enableDebugTypeODRUniquing(); |
507 | |
508 | Expected<std::unique_ptr<ToolOutputFile>> = |
509 | setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, |
510 | RemarksFormat, RemarksWithHotness, |
511 | RemarksHotnessThreshold); |
512 | if (Error E = RemarksFileOrErr.takeError()) { |
513 | errs() << toString(E: std::move(E)) << '\n'; |
514 | return 1; |
515 | } |
516 | std::unique_ptr<ToolOutputFile> = std::move(*RemarksFileOrErr); |
517 | |
518 | // Load the input module... |
519 | auto SetDataLayout = [&](StringRef IRTriple, |
520 | StringRef IRLayout) -> std::optional<std::string> { |
521 | // Data layout specified on the command line has the highest priority. |
522 | if (!ClDataLayout.empty()) |
523 | return ClDataLayout; |
524 | // If an explicit data layout is already defined in the IR, don't infer. |
525 | if (!IRLayout.empty()) |
526 | return std::nullopt; |
527 | |
528 | // If an explicit triple was specified (either in the IR or on the |
529 | // command line), use that to infer the default data layout. However, the |
530 | // command line target triple should override the IR file target triple. |
531 | std::string TripleStr = |
532 | TargetTriple.empty() ? IRTriple.str() : Triple::normalize(Str: TargetTriple); |
533 | // If the triple string is still empty, we don't fall back to |
534 | // sys::getDefaultTargetTriple() since we do not want to have differing |
535 | // behaviour dependent on the configured default triple. Therefore, if the |
536 | // user did not pass -mtriple or define an explicit triple/datalayout in |
537 | // the IR, we should default to an empty (default) DataLayout. |
538 | if (TripleStr.empty()) |
539 | return std::nullopt; |
540 | // Otherwise we infer the DataLayout from the target machine. |
541 | Expected<std::unique_ptr<TargetMachine>> ExpectedTM = |
542 | codegen::createTargetMachineForTriple(TargetTriple: TripleStr, OptLevel: GetCodeGenOptLevel()); |
543 | if (!ExpectedTM) { |
544 | errs() << argv[0] << ": warning: failed to infer data layout: " |
545 | << toString(E: ExpectedTM.takeError()) << "\n" ; |
546 | return std::nullopt; |
547 | } |
548 | return (*ExpectedTM)->createDataLayout().getStringRepresentation(); |
549 | }; |
550 | std::unique_ptr<Module> M; |
551 | if (NoUpgradeDebugInfo) |
552 | M = parseAssemblyFileWithIndexNoUpgradeDebugInfo( |
553 | Filename: InputFilename, Err, Context, Slots: nullptr, DataLayoutCallback: SetDataLayout) |
554 | .Mod; |
555 | else |
556 | M = parseIRFile(Filename: InputFilename, Err, Context, |
557 | Callbacks: ParserCallbacks(SetDataLayout)); |
558 | |
559 | if (!M) { |
560 | Err.print(ProgName: argv[0], S&: errs()); |
561 | return 1; |
562 | } |
563 | |
564 | // Strip debug info before running the verifier. |
565 | if (StripDebug) |
566 | StripDebugInfo(M&: *M); |
567 | |
568 | // Erase module-level named metadata, if requested. |
569 | if (StripNamedMetadata) { |
570 | while (!M->named_metadata_empty()) { |
571 | NamedMDNode *NMD = &*M->named_metadata_begin(); |
572 | M->eraseNamedMetadata(NMD); |
573 | } |
574 | } |
575 | |
576 | // If we are supposed to override the target triple, do so now. |
577 | if (!TargetTriple.empty()) |
578 | M->setTargetTriple(Triple::normalize(Str: TargetTriple)); |
579 | |
580 | // Immediately run the verifier to catch any problems before starting up the |
581 | // pass pipelines. Otherwise we can crash on broken code during |
582 | // doInitialization(). |
583 | if (!NoVerify && verifyModule(M: *M, OS: &errs())) { |
584 | errs() << argv[0] << ": " << InputFilename |
585 | << ": error: input module is broken!\n" ; |
586 | return 1; |
587 | } |
588 | |
589 | // Enable testing of whole program devirtualization on this module by invoking |
590 | // the facility for updating public visibility to linkage unit visibility when |
591 | // specified by an internal option. This is normally done during LTO which is |
592 | // not performed via opt. |
593 | updateVCallVisibilityInModule( |
594 | M&: *M, |
595 | /*WholeProgramVisibilityEnabledInLTO=*/false, |
596 | // FIXME: These need linker information via a |
597 | // TBD new interface. |
598 | /*DynamicExportSymbols=*/{}, |
599 | /*ValidateAllVtablesHaveTypeInfos=*/false, |
600 | /*IsVisibleToRegularObj=*/[](StringRef) { return true; }); |
601 | |
602 | // Figure out what stream we are supposed to write to... |
603 | std::unique_ptr<ToolOutputFile> Out; |
604 | std::unique_ptr<ToolOutputFile> ThinLinkOut; |
605 | if (NoOutput) { |
606 | if (!OutputFilename.empty()) |
607 | errs() << "WARNING: The -o (output filename) option is ignored when\n" |
608 | "the --disable-output option is used.\n" ; |
609 | } else { |
610 | // Default to standard output. |
611 | if (OutputFilename.empty()) |
612 | OutputFilename = "-" ; |
613 | |
614 | std::error_code EC; |
615 | sys::fs::OpenFlags Flags = |
616 | OutputAssembly ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None; |
617 | Out.reset(p: new ToolOutputFile(OutputFilename, EC, Flags)); |
618 | if (EC) { |
619 | errs() << EC.message() << '\n'; |
620 | return 1; |
621 | } |
622 | |
623 | if (!ThinLinkBitcodeFile.empty()) { |
624 | ThinLinkOut.reset( |
625 | p: new ToolOutputFile(ThinLinkBitcodeFile, EC, sys::fs::OF_None)); |
626 | if (EC) { |
627 | errs() << EC.message() << '\n'; |
628 | return 1; |
629 | } |
630 | } |
631 | } |
632 | |
633 | Triple ModuleTriple(M->getTargetTriple()); |
634 | std::string CPUStr, FeaturesStr; |
635 | std::unique_ptr<TargetMachine> TM; |
636 | if (ModuleTriple.getArch()) { |
637 | CPUStr = codegen::getCPUStr(); |
638 | FeaturesStr = codegen::getFeaturesStr(); |
639 | Expected<std::unique_ptr<TargetMachine>> ExpectedTM = |
640 | codegen::createTargetMachineForTriple(TargetTriple: ModuleTriple.str(), |
641 | OptLevel: GetCodeGenOptLevel()); |
642 | if (auto E = ExpectedTM.takeError()) { |
643 | errs() << argv[0] << ": WARNING: failed to create target machine for '" |
644 | << ModuleTriple.str() << "': " << toString(E: std::move(E)) << "\n" ; |
645 | } else { |
646 | TM = std::move(*ExpectedTM); |
647 | } |
648 | } else if (ModuleTriple.getArchName() != "unknown" && |
649 | ModuleTriple.getArchName() != "" ) { |
650 | errs() << argv[0] << ": unrecognized architecture '" |
651 | << ModuleTriple.getArchName() << "' provided.\n" ; |
652 | return 1; |
653 | } |
654 | |
655 | // Override function attributes based on CPUStr, FeaturesStr, and command line |
656 | // flags. |
657 | codegen::setFunctionAttributes(CPU: CPUStr, Features: FeaturesStr, M&: *M); |
658 | |
659 | // If the output is set to be emitted to standard out, and standard out is a |
660 | // console, print out a warning message and refuse to do it. We don't |
661 | // impress anyone by spewing tons of binary goo to a terminal. |
662 | if (!Force && !NoOutput && !OutputAssembly) |
663 | if (CheckBitcodeOutputToConsole(stream_to_check&: Out->os())) |
664 | NoOutput = true; |
665 | |
666 | if (OutputThinLTOBC) { |
667 | M->addModuleFlag(Behavior: Module::Error, Key: "EnableSplitLTOUnit" , Val: SplitLTOUnit); |
668 | if (UnifiedLTO) |
669 | M->addModuleFlag(Behavior: Module::Error, Key: "UnifiedLTO" , Val: 1); |
670 | } |
671 | |
672 | // Add an appropriate TargetLibraryInfo pass for the module's triple. |
673 | TargetLibraryInfoImpl TLII(ModuleTriple); |
674 | |
675 | // The -disable-simplify-libcalls flag actually disables all builtin optzns. |
676 | if (DisableSimplifyLibCalls) |
677 | TLII.disableAllFunctions(); |
678 | else { |
679 | // Disable individual builtin functions in TargetLibraryInfo. |
680 | LibFunc F; |
681 | for (auto &FuncName : DisableBuiltins) |
682 | if (TLII.getLibFunc(funcName: FuncName, F)) |
683 | TLII.setUnavailable(F); |
684 | else { |
685 | errs() << argv[0] << ": cannot disable nonexistent builtin function " |
686 | << FuncName << '\n'; |
687 | return 1; |
688 | } |
689 | } |
690 | |
691 | if (UseNPM) { |
692 | if (legacy::debugPassSpecified()) { |
693 | errs() << "-debug-pass does not work with the new PM, either use " |
694 | "-debug-pass-manager, or use the legacy PM\n" ; |
695 | return 1; |
696 | } |
697 | auto NumOLevel = OptLevelO0 + OptLevelO1 + OptLevelO2 + OptLevelO3 + |
698 | OptLevelOs + OptLevelOz; |
699 | if (NumOLevel > 1) { |
700 | errs() << "Cannot specify multiple -O#\n" ; |
701 | return 1; |
702 | } |
703 | if (NumOLevel > 0 && (PassPipeline.getNumOccurrences() > 0)) { |
704 | errs() << "Cannot specify -O# and --passes=/--foo-pass, use " |
705 | "-passes='default<O#>,other-pass'\n" ; |
706 | return 1; |
707 | } |
708 | std::string Pipeline = PassPipeline; |
709 | |
710 | if (OptLevelO0) |
711 | Pipeline = "default<O0>" ; |
712 | if (OptLevelO1) |
713 | Pipeline = "default<O1>" ; |
714 | if (OptLevelO2) |
715 | Pipeline = "default<O2>" ; |
716 | if (OptLevelO3) |
717 | Pipeline = "default<O3>" ; |
718 | if (OptLevelOs) |
719 | Pipeline = "default<Os>" ; |
720 | if (OptLevelOz) |
721 | Pipeline = "default<Oz>" ; |
722 | OutputKind OK = OK_NoOutput; |
723 | if (!NoOutput) |
724 | OK = OutputAssembly |
725 | ? OK_OutputAssembly |
726 | : (OutputThinLTOBC ? OK_OutputThinLTOBitcode : OK_OutputBitcode); |
727 | |
728 | VerifierKind VK = VK_VerifyOut; |
729 | if (NoVerify) |
730 | VK = VK_NoVerifier; |
731 | else if (VerifyEach) |
732 | VK = VK_VerifyEachPass; |
733 | |
734 | // The user has asked to use the new pass manager and provided a pipeline |
735 | // string. Hand off the rest of the functionality to the new code for that |
736 | // layer. |
737 | return runPassPipeline( |
738 | Arg0: argv[0], M&: *M, TM: TM.get(), TLII: &TLII, Out: Out.get(), ThinLinkOut: ThinLinkOut.get(), |
739 | OptRemarkFile: RemarksFile.get(), PassPipeline: Pipeline, PassPlugins: PluginList, PassBuilderCallbacks, |
740 | OK, VK, ShouldPreserveAssemblyUseListOrder: PreserveAssemblyUseListOrder, |
741 | ShouldPreserveBitcodeUseListOrder: PreserveBitcodeUseListOrder, EmitSummaryIndex, EmitModuleHash, |
742 | EnableDebugify, VerifyDIPreserve: VerifyDebugInfoPreserve, UnifiedLTO) |
743 | ? 0 |
744 | : 1; |
745 | } |
746 | |
747 | if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || |
748 | OptLevelO3) { |
749 | errs() << "Cannot use -O# with legacy PM.\n" ; |
750 | return 1; |
751 | } |
752 | if (EmitSummaryIndex) { |
753 | errs() << "Cannot use -module-summary with legacy PM.\n" ; |
754 | return 1; |
755 | } |
756 | if (EmitModuleHash) { |
757 | errs() << "Cannot use -module-hash with legacy PM.\n" ; |
758 | return 1; |
759 | } |
760 | if (OutputThinLTOBC) { |
761 | errs() << "Cannot use -thinlto-bc with legacy PM.\n" ; |
762 | return 1; |
763 | } |
764 | // Create a PassManager to hold and optimize the collection of passes we are |
765 | // about to build. If the -debugify-each option is set, wrap each pass with |
766 | // the (-check)-debugify passes. |
767 | DebugifyCustomPassManager Passes; |
768 | DebugifyStatsMap DIStatsMap; |
769 | DebugInfoPerPass DebugInfoBeforePass; |
770 | if (DebugifyEach) { |
771 | Passes.setDebugifyMode(DebugifyMode::SyntheticDebugInfo); |
772 | Passes.setDIStatsMap(DIStatsMap); |
773 | } else if (VerifyEachDebugInfoPreserve) { |
774 | Passes.setDebugifyMode(DebugifyMode::OriginalDebugInfo); |
775 | Passes.setDebugInfoBeforePass(DebugInfoBeforePass); |
776 | if (!VerifyDIPreserveExport.empty()) |
777 | Passes.setOrigDIVerifyBugsReportFilePath(VerifyDIPreserveExport); |
778 | } |
779 | |
780 | bool AddOneTimeDebugifyPasses = |
781 | (EnableDebugify && !DebugifyEach) || |
782 | (VerifyDebugInfoPreserve && !VerifyEachDebugInfoPreserve); |
783 | |
784 | Passes.add(P: new TargetLibraryInfoWrapperPass(TLII)); |
785 | |
786 | // Add internal analysis passes from the target machine. |
787 | Passes.add(P: createTargetTransformInfoWrapperPass(TIRA: TM ? TM->getTargetIRAnalysis() |
788 | : TargetIRAnalysis())); |
789 | |
790 | if (AddOneTimeDebugifyPasses) { |
791 | if (EnableDebugify) { |
792 | Passes.setDIStatsMap(DIStatsMap); |
793 | Passes.add(P: createDebugifyModulePass()); |
794 | } else if (VerifyDebugInfoPreserve) { |
795 | Passes.setDebugInfoBeforePass(DebugInfoBeforePass); |
796 | Passes.add(P: createDebugifyModulePass(Mode: DebugifyMode::OriginalDebugInfo, NameOfWrappedPass: "" , |
797 | DebugInfoBeforePass: &(Passes.getDebugInfoPerPass()))); |
798 | } |
799 | } |
800 | |
801 | if (TM) { |
802 | // FIXME: We should dyn_cast this when supported. |
803 | auto <M = static_cast<LLVMTargetMachine &>(*TM); |
804 | Pass *TPC = LTM.createPassConfig(PM&: Passes); |
805 | Passes.add(P: TPC); |
806 | } |
807 | |
808 | // Create a new optimization pass for each one specified on the command line |
809 | for (unsigned i = 0; i < PassList.size(); ++i) { |
810 | const PassInfo *PassInf = PassList[i]; |
811 | if (PassInf->getNormalCtor()) { |
812 | Pass *P = PassInf->getNormalCtor()(); |
813 | if (P) { |
814 | // Add the pass to the pass manager. |
815 | Passes.add(P); |
816 | // If we are verifying all of the intermediate steps, add the verifier. |
817 | if (VerifyEach) |
818 | Passes.add(P: createVerifierPass()); |
819 | } |
820 | } else |
821 | errs() << argv[0] << ": cannot create pass: " << PassInf->getPassName() |
822 | << "\n" ; |
823 | } |
824 | |
825 | // Check that the module is well formed on completion of optimization |
826 | if (!NoVerify && !VerifyEach) |
827 | Passes.add(P: createVerifierPass()); |
828 | |
829 | if (AddOneTimeDebugifyPasses) { |
830 | if (EnableDebugify) |
831 | Passes.add(P: createCheckDebugifyModulePass(Strip: false)); |
832 | else if (VerifyDebugInfoPreserve) { |
833 | if (!VerifyDIPreserveExport.empty()) |
834 | Passes.setOrigDIVerifyBugsReportFilePath(VerifyDIPreserveExport); |
835 | Passes.add(P: createCheckDebugifyModulePass( |
836 | Strip: false, NameOfWrappedPass: "" , StatsMap: nullptr, Mode: DebugifyMode::OriginalDebugInfo, |
837 | DebugInfoBeforePass: &(Passes.getDebugInfoPerPass()), OrigDIVerifyBugsReportFilePath: VerifyDIPreserveExport)); |
838 | } |
839 | } |
840 | |
841 | // In run twice mode, we want to make sure the output is bit-by-bit |
842 | // equivalent if we run the pass manager again, so setup two buffers and |
843 | // a stream to write to them. Note that llc does something similar and it |
844 | // may be worth to abstract this out in the future. |
845 | SmallVector<char, 0> Buffer; |
846 | SmallVector<char, 0> FirstRunBuffer; |
847 | std::unique_ptr<raw_svector_ostream> BOS; |
848 | raw_ostream *OS = nullptr; |
849 | |
850 | const bool ShouldEmitOutput = !NoOutput; |
851 | |
852 | // Write bitcode or assembly to the output as the last step... |
853 | if (ShouldEmitOutput || RunTwice) { |
854 | assert(Out); |
855 | OS = &Out->os(); |
856 | if (RunTwice) { |
857 | BOS = std::make_unique<raw_svector_ostream>(args&: Buffer); |
858 | OS = BOS.get(); |
859 | } |
860 | if (OutputAssembly) |
861 | Passes.add(P: createPrintModulePass(OS&: *OS, Banner: "" , ShouldPreserveUseListOrder: PreserveAssemblyUseListOrder)); |
862 | else |
863 | Passes.add(P: createBitcodeWriterPass(Str&: *OS, ShouldPreserveUseListOrder: PreserveBitcodeUseListOrder)); |
864 | } |
865 | |
866 | // Before executing passes, print the final values of the LLVM options. |
867 | cl::PrintOptionValues(); |
868 | |
869 | if (!RunTwice) { |
870 | // Now that we have all of the passes ready, run them. |
871 | Passes.run(M&: *M); |
872 | } else { |
873 | // If requested, run all passes twice with the same pass manager to catch |
874 | // bugs caused by persistent state in the passes. |
875 | std::unique_ptr<Module> M2(CloneModule(M: *M)); |
876 | // Run all passes on the original module first, so the second run processes |
877 | // the clone to catch CloneModule bugs. |
878 | Passes.run(M&: *M); |
879 | FirstRunBuffer = Buffer; |
880 | Buffer.clear(); |
881 | |
882 | Passes.run(M&: *M2); |
883 | |
884 | // Compare the two outputs and make sure they're the same |
885 | assert(Out); |
886 | if (Buffer.size() != FirstRunBuffer.size() || |
887 | (memcmp(s1: Buffer.data(), s2: FirstRunBuffer.data(), n: Buffer.size()) != 0)) { |
888 | errs() |
889 | << "Running the pass manager twice changed the output.\n" |
890 | "Writing the result of the second run to the specified output.\n" |
891 | "To generate the one-run comparison binary, just run without\n" |
892 | "the compile-twice option\n" ; |
893 | if (ShouldEmitOutput) { |
894 | Out->os() << BOS->str(); |
895 | Out->keep(); |
896 | } |
897 | if (RemarksFile) |
898 | RemarksFile->keep(); |
899 | return 1; |
900 | } |
901 | if (ShouldEmitOutput) |
902 | Out->os() << BOS->str(); |
903 | } |
904 | |
905 | if (DebugifyEach && !DebugifyExport.empty()) |
906 | exportDebugifyStats(Path: DebugifyExport, Map: Passes.getDebugifyStatsMap()); |
907 | |
908 | // Declare success. |
909 | if (!NoOutput) |
910 | Out->keep(); |
911 | |
912 | if (RemarksFile) |
913 | RemarksFile->keep(); |
914 | |
915 | if (ThinLinkOut) |
916 | ThinLinkOut->keep(); |
917 | |
918 | return 0; |
919 | } |
920 | |