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