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