xref: /freebsd/contrib/llvm-project/llvm/tools/opt/opt.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- opt.cpp - The LLVM Modular Optimizer -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Optimizations may be specified an arbitrary number of times on the command
100b57cec5SDimitry Andric // line, They are run in the order specified.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "BreakpointPrinter.h"
150b57cec5SDimitry Andric #include "NewPMDriver.h"
160b57cec5SDimitry Andric #include "PassPrinters.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h"
200b57cec5SDimitry Andric #include "llvm/Analysis/LoopPass.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/RegionPass.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
24*5ffd83dbSDimitry Andric #include "llvm/AsmParser/Parser.h"
250b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriterPass.h"
26*5ffd83dbSDimitry Andric #include "llvm/CodeGen/CommandFlags.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
280b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
290b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
300b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
310b57cec5SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
320b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
33*5ffd83dbSDimitry Andric #include "llvm/IR/LLVMRemarkStreamer.h"
340b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
350b57cec5SDimitry Andric #include "llvm/IR/LegacyPassNameParser.h"
360b57cec5SDimitry Andric #include "llvm/IR/Module.h"
370b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
380b57cec5SDimitry Andric #include "llvm/IRReader/IRReader.h"
390b57cec5SDimitry Andric #include "llvm/InitializePasses.h"
400b57cec5SDimitry Andric #include "llvm/LinkAllIR.h"
410b57cec5SDimitry Andric #include "llvm/LinkAllPasses.h"
420b57cec5SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
430b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
440b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
450b57cec5SDimitry Andric #include "llvm/Support/Host.h"
460b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
470b57cec5SDimitry Andric #include "llvm/Support/PluginLoader.h"
480b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
490b57cec5SDimitry Andric #include "llvm/Support/SystemUtils.h"
500b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
510b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
520b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
530b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
540b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
550b57cec5SDimitry Andric #include "llvm/Transforms/Coroutines.h"
560b57cec5SDimitry Andric #include "llvm/Transforms/IPO/AlwaysInliner.h"
570b57cec5SDimitry Andric #include "llvm/Transforms/IPO/PassManagerBuilder.h"
58*5ffd83dbSDimitry Andric #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
590b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
60480093f4SDimitry Andric #include "llvm/Transforms/Utils/Debugify.h"
610b57cec5SDimitry Andric #include <algorithm>
620b57cec5SDimitry Andric #include <memory>
630b57cec5SDimitry Andric using namespace llvm;
640b57cec5SDimitry Andric using namespace opt_tool;
650b57cec5SDimitry Andric 
66*5ffd83dbSDimitry Andric static codegen::RegisterCodeGenFlags CFG;
67*5ffd83dbSDimitry Andric 
680b57cec5SDimitry Andric // The OptimizationList is automatically populated with registered Passes by the
690b57cec5SDimitry Andric // PassNameParser.
700b57cec5SDimitry Andric //
710b57cec5SDimitry Andric static cl::list<const PassInfo*, bool, PassNameParser>
720b57cec5SDimitry Andric PassList(cl::desc("Optimizations available:"));
730b57cec5SDimitry Andric 
74*5ffd83dbSDimitry Andric static cl::opt<bool> EnableNewPassManager(
75*5ffd83dbSDimitry Andric     "enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));
76*5ffd83dbSDimitry Andric 
770b57cec5SDimitry Andric // This flag specifies a textual description of the optimization pass pipeline
780b57cec5SDimitry Andric // to run over the module. This flag switches opt to use the new pass manager
790b57cec5SDimitry Andric // infrastructure, completely disabling all of the flags specific to the old
800b57cec5SDimitry Andric // pass management.
810b57cec5SDimitry Andric static cl::opt<std::string> PassPipeline(
820b57cec5SDimitry Andric     "passes",
830b57cec5SDimitry Andric     cl::desc("A textual description of the pass pipeline for optimizing"),
840b57cec5SDimitry Andric     cl::Hidden);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric // Other command line options...
870b57cec5SDimitry Andric //
880b57cec5SDimitry Andric static cl::opt<std::string>
890b57cec5SDimitry Andric InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
900b57cec5SDimitry Andric     cl::init("-"), cl::value_desc("filename"));
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric static cl::opt<std::string>
930b57cec5SDimitry Andric OutputFilename("o", cl::desc("Override output filename"),
940b57cec5SDimitry Andric                cl::value_desc("filename"));
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric static cl::opt<bool>
970b57cec5SDimitry Andric Force("f", cl::desc("Enable binary output on terminals"));
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric static cl::opt<bool>
1000b57cec5SDimitry Andric PrintEachXForm("p", cl::desc("Print module after each transformation"));
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric static cl::opt<bool>
1030b57cec5SDimitry Andric NoOutput("disable-output",
1040b57cec5SDimitry Andric          cl::desc("Do not write result bitcode file"), cl::Hidden);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric static cl::opt<bool>
1070b57cec5SDimitry Andric OutputAssembly("S", cl::desc("Write output as LLVM assembly"));
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric static cl::opt<bool>
1100b57cec5SDimitry Andric     OutputThinLTOBC("thinlto-bc",
1110b57cec5SDimitry Andric                     cl::desc("Write output as ThinLTO-ready bitcode"));
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric static cl::opt<bool>
1140b57cec5SDimitry Andric     SplitLTOUnit("thinlto-split-lto-unit",
1150b57cec5SDimitry Andric                  cl::desc("Enable splitting of a ThinLTO LTOUnit"));
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric static cl::opt<std::string> ThinLinkBitcodeFile(
1180b57cec5SDimitry Andric     "thin-link-bitcode-file", cl::value_desc("filename"),
1190b57cec5SDimitry Andric     cl::desc(
1200b57cec5SDimitry Andric         "A file in which to write minimized bitcode for the thin link only"));
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric static cl::opt<bool>
1230b57cec5SDimitry Andric NoVerify("disable-verify", cl::desc("Do not run the verifier"), cl::Hidden);
1240b57cec5SDimitry Andric 
125*5ffd83dbSDimitry Andric static cl::opt<bool> NoUpgradeDebugInfo("disable-upgrade-debug-info",
126*5ffd83dbSDimitry Andric                                         cl::desc("Generate invalid output"),
127*5ffd83dbSDimitry Andric                                         cl::ReallyHidden);
128*5ffd83dbSDimitry Andric 
129*5ffd83dbSDimitry Andric static cl::opt<bool> VerifyEach("verify-each",
130*5ffd83dbSDimitry Andric                                 cl::desc("Verify after each transform"));
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric static cl::opt<bool>
1330b57cec5SDimitry Andric     DisableDITypeMap("disable-debug-info-type-map",
1340b57cec5SDimitry Andric                      cl::desc("Don't use a uniquing type map for debug info"));
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric static cl::opt<bool>
1370b57cec5SDimitry Andric StripDebug("strip-debug",
1380b57cec5SDimitry Andric            cl::desc("Strip debugger symbol info from translation unit"));
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric static cl::opt<bool>
1410b57cec5SDimitry Andric     StripNamedMetadata("strip-named-metadata",
1420b57cec5SDimitry Andric                        cl::desc("Strip module-level named metadata"));
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric static cl::opt<bool> DisableInline("disable-inlining",
1450b57cec5SDimitry Andric                                    cl::desc("Do not run the inliner pass"));
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric static cl::opt<bool>
1480b57cec5SDimitry Andric DisableOptimizations("disable-opt",
1490b57cec5SDimitry Andric                      cl::desc("Do not run any optimization passes"));
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric static cl::opt<bool>
1520b57cec5SDimitry Andric StandardLinkOpts("std-link-opts",
1530b57cec5SDimitry Andric                  cl::desc("Include the standard link time optimizations"));
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric static cl::opt<bool>
1560b57cec5SDimitry Andric OptLevelO0("O0",
1570b57cec5SDimitry Andric   cl::desc("Optimization level 0. Similar to clang -O0"));
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric static cl::opt<bool>
1600b57cec5SDimitry Andric OptLevelO1("O1",
1610b57cec5SDimitry Andric            cl::desc("Optimization level 1. Similar to clang -O1"));
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric static cl::opt<bool>
1640b57cec5SDimitry Andric OptLevelO2("O2",
1650b57cec5SDimitry Andric            cl::desc("Optimization level 2. Similar to clang -O2"));
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric static cl::opt<bool>
1680b57cec5SDimitry Andric OptLevelOs("Os",
1690b57cec5SDimitry Andric            cl::desc("Like -O2 with extra optimizations for size. Similar to clang -Os"));
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric static cl::opt<bool>
1720b57cec5SDimitry Andric OptLevelOz("Oz",
1730b57cec5SDimitry Andric            cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric static cl::opt<bool>
1760b57cec5SDimitry Andric OptLevelO3("O3",
1770b57cec5SDimitry Andric            cl::desc("Optimization level 3. Similar to clang -O3"));
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric static cl::opt<unsigned>
1800b57cec5SDimitry Andric CodeGenOptLevel("codegen-opt-level",
1810b57cec5SDimitry Andric                 cl::desc("Override optimization level for codegen hooks"));
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric static cl::opt<std::string>
1840b57cec5SDimitry Andric TargetTriple("mtriple", cl::desc("Override target triple for module"));
1850b57cec5SDimitry Andric 
186*5ffd83dbSDimitry Andric cl::opt<bool> DisableLoopUnrolling(
187*5ffd83dbSDimitry Andric     "disable-loop-unrolling",
188*5ffd83dbSDimitry Andric     cl::desc("Disable loop unrolling in all relevant passes"), cl::init(false));
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric static cl::opt<bool> EmitSummaryIndex("module-summary",
1910b57cec5SDimitry Andric                                       cl::desc("Emit module summary index"),
1920b57cec5SDimitry Andric                                       cl::init(false));
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric static cl::opt<bool> EmitModuleHash("module-hash", cl::desc("Emit module hash"),
1950b57cec5SDimitry Andric                                     cl::init(false));
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric static cl::opt<bool>
1980b57cec5SDimitry Andric DisableSimplifyLibCalls("disable-simplify-libcalls",
1990b57cec5SDimitry Andric                         cl::desc("Disable simplify-libcalls"));
2000b57cec5SDimitry Andric 
201480093f4SDimitry Andric static cl::list<std::string>
202480093f4SDimitry Andric DisableBuiltins("disable-builtin",
203480093f4SDimitry Andric                 cl::desc("Disable specific target library builtin function"),
204480093f4SDimitry Andric                 cl::ZeroOrMore);
205480093f4SDimitry Andric 
2060b57cec5SDimitry Andric static cl::opt<bool>
2070b57cec5SDimitry Andric AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization"));
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric static cl::opt<bool> EnableDebugify(
2100b57cec5SDimitry Andric     "enable-debugify",
2110b57cec5SDimitry Andric     cl::desc(
2120b57cec5SDimitry Andric         "Start the pipeline with debugify and end it with check-debugify"));
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric static cl::opt<bool> DebugifyEach(
2150b57cec5SDimitry Andric     "debugify-each",
2160b57cec5SDimitry Andric     cl::desc(
2170b57cec5SDimitry Andric         "Start each pass with debugify and end it with check-debugify"));
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric static cl::opt<std::string>
2200b57cec5SDimitry Andric     DebugifyExport("debugify-export",
2210b57cec5SDimitry Andric                    cl::desc("Export per-pass debugify statistics to this file"),
2220b57cec5SDimitry Andric                    cl::value_desc("filename"), cl::init(""));
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric static cl::opt<bool>
2250b57cec5SDimitry Andric PrintBreakpoints("print-breakpoints-for-testing",
2260b57cec5SDimitry Andric                  cl::desc("Print select breakpoints location for testing"));
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric static cl::opt<std::string> ClDataLayout("data-layout",
2290b57cec5SDimitry Andric                                          cl::desc("data layout string to use"),
2300b57cec5SDimitry Andric                                          cl::value_desc("layout-string"),
2310b57cec5SDimitry Andric                                          cl::init(""));
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric static cl::opt<bool> PreserveBitcodeUseListOrder(
2340b57cec5SDimitry Andric     "preserve-bc-uselistorder",
2350b57cec5SDimitry Andric     cl::desc("Preserve use-list order when writing LLVM bitcode."),
2360b57cec5SDimitry Andric     cl::init(true), cl::Hidden);
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric static cl::opt<bool> PreserveAssemblyUseListOrder(
2390b57cec5SDimitry Andric     "preserve-ll-uselistorder",
2400b57cec5SDimitry Andric     cl::desc("Preserve use-list order when writing LLVM assembly."),
2410b57cec5SDimitry Andric     cl::init(false), cl::Hidden);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric static cl::opt<bool>
2440b57cec5SDimitry Andric     RunTwice("run-twice",
2450b57cec5SDimitry Andric              cl::desc("Run all passes twice, re-using the same pass manager."),
2460b57cec5SDimitry Andric              cl::init(false), cl::Hidden);
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric static cl::opt<bool> DiscardValueNames(
2490b57cec5SDimitry Andric     "discard-value-names",
2500b57cec5SDimitry Andric     cl::desc("Discard names from Value (other than GlobalValue)."),
2510b57cec5SDimitry Andric     cl::init(false), cl::Hidden);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric static cl::opt<bool> Coroutines(
2540b57cec5SDimitry Andric   "enable-coroutines",
2550b57cec5SDimitry Andric   cl::desc("Enable coroutine passes."),
2560b57cec5SDimitry Andric   cl::init(false), cl::Hidden);
2570b57cec5SDimitry Andric 
258*5ffd83dbSDimitry Andric static cl::opt<bool> TimeTrace(
259*5ffd83dbSDimitry Andric     "time-trace",
260*5ffd83dbSDimitry Andric     cl::desc("Record time trace"));
261*5ffd83dbSDimitry Andric 
262*5ffd83dbSDimitry Andric static cl::opt<unsigned> TimeTraceGranularity(
263*5ffd83dbSDimitry Andric     "time-trace-granularity",
264*5ffd83dbSDimitry Andric     cl::desc("Minimum time granularity (in microseconds) traced by time profiler"),
265*5ffd83dbSDimitry Andric     cl::init(500), cl::Hidden);
266*5ffd83dbSDimitry Andric 
267*5ffd83dbSDimitry Andric static cl::opt<std::string>
268*5ffd83dbSDimitry Andric     TimeTraceFile("time-trace-file",
269*5ffd83dbSDimitry Andric                     cl::desc("Specify time trace file destination"),
270*5ffd83dbSDimitry Andric                     cl::value_desc("filename"));
271*5ffd83dbSDimitry Andric 
2720b57cec5SDimitry Andric static cl::opt<bool> RemarksWithHotness(
2730b57cec5SDimitry Andric     "pass-remarks-with-hotness",
2740b57cec5SDimitry Andric     cl::desc("With PGO, include profile count in optimization remarks"),
2750b57cec5SDimitry Andric     cl::Hidden);
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric static cl::opt<unsigned>
2780b57cec5SDimitry Andric     RemarksHotnessThreshold("pass-remarks-hotness-threshold",
2790b57cec5SDimitry Andric                             cl::desc("Minimum profile count required for "
2800b57cec5SDimitry Andric                                      "an optimization remark to be output"),
2810b57cec5SDimitry Andric                             cl::Hidden);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric static cl::opt<std::string>
2840b57cec5SDimitry Andric     RemarksFilename("pass-remarks-output",
2850b57cec5SDimitry Andric                     cl::desc("Output filename for pass remarks"),
2860b57cec5SDimitry Andric                     cl::value_desc("filename"));
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric static cl::opt<std::string>
2890b57cec5SDimitry Andric     RemarksPasses("pass-remarks-filter",
2900b57cec5SDimitry Andric                   cl::desc("Only record optimization remarks from passes whose "
2910b57cec5SDimitry Andric                            "names match the given regular expression"),
2920b57cec5SDimitry Andric                   cl::value_desc("regex"));
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric static cl::opt<std::string> RemarksFormat(
2950b57cec5SDimitry Andric     "pass-remarks-format",
2960b57cec5SDimitry Andric     cl::desc("The format used for serializing remarks (default: YAML)"),
2970b57cec5SDimitry Andric     cl::value_desc("format"), cl::init("yaml"));
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric cl::opt<PGOKind>
3000b57cec5SDimitry Andric     PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
3010b57cec5SDimitry Andric                 cl::desc("The kind of profile guided optimization"),
3020b57cec5SDimitry Andric                 cl::values(clEnumValN(NoPGO, "nopgo", "Do not use PGO."),
3030b57cec5SDimitry Andric                            clEnumValN(InstrGen, "pgo-instr-gen-pipeline",
3040b57cec5SDimitry Andric                                       "Instrument the IR to generate profile."),
3050b57cec5SDimitry Andric                            clEnumValN(InstrUse, "pgo-instr-use-pipeline",
3060b57cec5SDimitry Andric                                       "Use instrumented profile to guide PGO."),
3070b57cec5SDimitry Andric                            clEnumValN(SampleUse, "pgo-sample-use-pipeline",
3080b57cec5SDimitry Andric                                       "Use sampled profile to guide PGO.")));
3090b57cec5SDimitry Andric cl::opt<std::string> ProfileFile("profile-file",
3100b57cec5SDimitry Andric                                  cl::desc("Path to the profile."), cl::Hidden);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric cl::opt<CSPGOKind> CSPGOKindFlag(
3130b57cec5SDimitry Andric     "cspgo-kind", cl::init(NoCSPGO), cl::Hidden,
3140b57cec5SDimitry Andric     cl::desc("The kind of context sensitive profile guided optimization"),
3150b57cec5SDimitry Andric     cl::values(
3160b57cec5SDimitry Andric         clEnumValN(NoCSPGO, "nocspgo", "Do not use CSPGO."),
3170b57cec5SDimitry Andric         clEnumValN(
3180b57cec5SDimitry Andric             CSInstrGen, "cspgo-instr-gen-pipeline",
3190b57cec5SDimitry Andric             "Instrument (context sensitive) the IR to generate profile."),
3200b57cec5SDimitry Andric         clEnumValN(
3210b57cec5SDimitry Andric             CSInstrUse, "cspgo-instr-use-pipeline",
3220b57cec5SDimitry Andric             "Use instrumented (context sensitive) profile to guide PGO.")));
3230b57cec5SDimitry Andric cl::opt<std::string> CSProfileGenFile(
3240b57cec5SDimitry Andric     "cs-profilegen-file",
3250b57cec5SDimitry Andric     cl::desc("Path to the instrumented context sensitive profile."),
3260b57cec5SDimitry Andric     cl::Hidden);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric class OptCustomPassManager : public legacy::PassManager {
3290b57cec5SDimitry Andric   DebugifyStatsMap DIStatsMap;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric public:
3320b57cec5SDimitry Andric   using super = legacy::PassManager;
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   void add(Pass *P) override {
3350b57cec5SDimitry Andric     // Wrap each pass with (-check)-debugify passes if requested, making
3360b57cec5SDimitry Andric     // exceptions for passes which shouldn't see -debugify instrumentation.
3370b57cec5SDimitry Andric     bool WrapWithDebugify = DebugifyEach && !P->getAsImmutablePass() &&
3380b57cec5SDimitry Andric                             !isIRPrintingPass(P) && !isBitcodeWriterPass(P);
3390b57cec5SDimitry Andric     if (!WrapWithDebugify) {
3400b57cec5SDimitry Andric       super::add(P);
3410b57cec5SDimitry Andric       return;
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric     // Apply -debugify/-check-debugify before/after each pass and collect
3450b57cec5SDimitry Andric     // debug info loss statistics.
3460b57cec5SDimitry Andric     PassKind Kind = P->getPassKind();
3470b57cec5SDimitry Andric     StringRef Name = P->getPassName();
3480b57cec5SDimitry Andric 
349480093f4SDimitry Andric     // TODO: Implement Debugify for LoopPass.
3500b57cec5SDimitry Andric     switch (Kind) {
3510b57cec5SDimitry Andric       case PT_Function:
3520b57cec5SDimitry Andric         super::add(createDebugifyFunctionPass());
3530b57cec5SDimitry Andric         super::add(P);
3540b57cec5SDimitry Andric         super::add(createCheckDebugifyFunctionPass(true, Name, &DIStatsMap));
3550b57cec5SDimitry Andric         break;
3560b57cec5SDimitry Andric       case PT_Module:
3570b57cec5SDimitry Andric         super::add(createDebugifyModulePass());
3580b57cec5SDimitry Andric         super::add(P);
3590b57cec5SDimitry Andric         super::add(createCheckDebugifyModulePass(true, Name, &DIStatsMap));
3600b57cec5SDimitry Andric         break;
3610b57cec5SDimitry Andric       default:
3620b57cec5SDimitry Andric         super::add(P);
3630b57cec5SDimitry Andric         break;
3640b57cec5SDimitry Andric     }
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   const DebugifyStatsMap &getDebugifyStatsMap() const { return DIStatsMap; }
3680b57cec5SDimitry Andric };
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
3710b57cec5SDimitry Andric   // Add the pass to the pass manager...
3720b57cec5SDimitry Andric   PM.add(P);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   // If we are verifying all of the intermediate steps, add the verifier...
3750b57cec5SDimitry Andric   if (VerifyEach)
3760b57cec5SDimitry Andric     PM.add(createVerifierPass());
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric /// This routine adds optimization passes based on selected optimization level,
3800b57cec5SDimitry Andric /// OptLevel.
3810b57cec5SDimitry Andric ///
3820b57cec5SDimitry Andric /// OptLevel - Optimization Level
3830b57cec5SDimitry Andric static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
3840b57cec5SDimitry Andric                                   legacy::FunctionPassManager &FPM,
3850b57cec5SDimitry Andric                                   TargetMachine *TM, unsigned OptLevel,
3860b57cec5SDimitry Andric                                   unsigned SizeLevel) {
3870b57cec5SDimitry Andric   if (!NoVerify || VerifyEach)
3880b57cec5SDimitry Andric     FPM.add(createVerifierPass()); // Verify that input is correct
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   PassManagerBuilder Builder;
3910b57cec5SDimitry Andric   Builder.OptLevel = OptLevel;
3920b57cec5SDimitry Andric   Builder.SizeLevel = SizeLevel;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   if (DisableInline) {
3950b57cec5SDimitry Andric     // No inlining pass
3960b57cec5SDimitry Andric   } else if (OptLevel > 1) {
3970b57cec5SDimitry Andric     Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
3980b57cec5SDimitry Andric   } else {
3990b57cec5SDimitry Andric     Builder.Inliner = createAlwaysInlinerLegacyPass();
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric   Builder.DisableUnrollLoops = (DisableLoopUnrolling.getNumOccurrences() > 0) ?
4020b57cec5SDimitry Andric                                DisableLoopUnrolling : OptLevel == 0;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   Builder.LoopVectorize = OptLevel > 1 && SizeLevel < 2;
4050b57cec5SDimitry Andric 
406*5ffd83dbSDimitry Andric   Builder.SLPVectorize = OptLevel > 1 && SizeLevel < 2;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   if (TM)
4090b57cec5SDimitry Andric     TM->adjustPassManager(Builder);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   if (Coroutines)
4120b57cec5SDimitry Andric     addCoroutinePassesToExtensionPoints(Builder);
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   switch (PGOKindFlag) {
4150b57cec5SDimitry Andric   case InstrGen:
4160b57cec5SDimitry Andric     Builder.EnablePGOInstrGen = true;
4170b57cec5SDimitry Andric     Builder.PGOInstrGen = ProfileFile;
4180b57cec5SDimitry Andric     break;
4190b57cec5SDimitry Andric   case InstrUse:
4200b57cec5SDimitry Andric     Builder.PGOInstrUse = ProfileFile;
4210b57cec5SDimitry Andric     break;
4220b57cec5SDimitry Andric   case SampleUse:
4230b57cec5SDimitry Andric     Builder.PGOSampleUse = ProfileFile;
4240b57cec5SDimitry Andric     break;
4250b57cec5SDimitry Andric   default:
4260b57cec5SDimitry Andric     break;
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   switch (CSPGOKindFlag) {
4300b57cec5SDimitry Andric   case CSInstrGen:
4310b57cec5SDimitry Andric     Builder.EnablePGOCSInstrGen = true;
4320b57cec5SDimitry Andric     break;
4330b57cec5SDimitry Andric   case CSInstrUse:
4340b57cec5SDimitry Andric     Builder.EnablePGOCSInstrUse = true;
4350b57cec5SDimitry Andric     break;
4360b57cec5SDimitry Andric   default:
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   Builder.populateFunctionPassManager(FPM);
4410b57cec5SDimitry Andric   Builder.populateModulePassManager(MPM);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric static void AddStandardLinkPasses(legacy::PassManagerBase &PM) {
4450b57cec5SDimitry Andric   PassManagerBuilder Builder;
4460b57cec5SDimitry Andric   Builder.VerifyInput = true;
4470b57cec5SDimitry Andric   if (DisableOptimizations)
4480b57cec5SDimitry Andric     Builder.OptLevel = 0;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   if (!DisableInline)
4510b57cec5SDimitry Andric     Builder.Inliner = createFunctionInliningPass();
4520b57cec5SDimitry Andric   Builder.populateLTOPassManager(PM);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4560b57cec5SDimitry Andric // CodeGen-related helper functions.
4570b57cec5SDimitry Andric //
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric static CodeGenOpt::Level GetCodeGenOptLevel() {
4600b57cec5SDimitry Andric   if (CodeGenOptLevel.getNumOccurrences())
4610b57cec5SDimitry Andric     return static_cast<CodeGenOpt::Level>(unsigned(CodeGenOptLevel));
4620b57cec5SDimitry Andric   if (OptLevelO1)
4630b57cec5SDimitry Andric     return CodeGenOpt::Less;
4640b57cec5SDimitry Andric   if (OptLevelO2)
4650b57cec5SDimitry Andric     return CodeGenOpt::Default;
4660b57cec5SDimitry Andric   if (OptLevelO3)
4670b57cec5SDimitry Andric     return CodeGenOpt::Aggressive;
4680b57cec5SDimitry Andric   return CodeGenOpt::None;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric // Returns the TargetMachine instance or zero if no triple is provided.
4720b57cec5SDimitry Andric static TargetMachine* GetTargetMachine(Triple TheTriple, StringRef CPUStr,
4730b57cec5SDimitry Andric                                        StringRef FeaturesStr,
4740b57cec5SDimitry Andric                                        const TargetOptions &Options) {
4750b57cec5SDimitry Andric   std::string Error;
476*5ffd83dbSDimitry Andric   const Target *TheTarget =
477*5ffd83dbSDimitry Andric       TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
4780b57cec5SDimitry Andric   // Some modules don't specify a triple, and this is okay.
4790b57cec5SDimitry Andric   if (!TheTarget) {
4800b57cec5SDimitry Andric     return nullptr;
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric 
483*5ffd83dbSDimitry Andric   return TheTarget->createTargetMachine(
484*5ffd83dbSDimitry Andric       TheTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(),
485*5ffd83dbSDimitry Andric       Options, codegen::getExplicitRelocModel(),
486*5ffd83dbSDimitry Andric       codegen::getExplicitCodeModel(), GetCodeGenOptLevel());
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
489480093f4SDimitry Andric #ifdef BUILD_EXAMPLES
490480093f4SDimitry Andric void initializeExampleIRTransforms(llvm::PassRegistry &Registry);
4910b57cec5SDimitry Andric #endif
4920b57cec5SDimitry Andric 
493480093f4SDimitry Andric 
494480093f4SDimitry Andric void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
495480093f4SDimitry Andric   std::error_code EC;
496480093f4SDimitry Andric   raw_fd_ostream OS{Path, EC};
497480093f4SDimitry Andric   if (EC) {
498480093f4SDimitry Andric     errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
499480093f4SDimitry Andric     return;
500480093f4SDimitry Andric   }
501480093f4SDimitry Andric 
502480093f4SDimitry Andric   OS << "Pass Name" << ',' << "# of missing debug values" << ','
503480093f4SDimitry Andric      << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
504480093f4SDimitry Andric      << "Missing/Expected location ratio" << '\n';
505480093f4SDimitry Andric   for (const auto &Entry : Map) {
506480093f4SDimitry Andric     StringRef Pass = Entry.first;
507480093f4SDimitry Andric     DebugifyStatistics Stats = Entry.second;
508480093f4SDimitry Andric 
509480093f4SDimitry Andric     OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
510480093f4SDimitry Andric        << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
511480093f4SDimitry Andric        << Stats.getEmptyLocationRatio() << '\n';
512480093f4SDimitry Andric   }
513480093f4SDimitry Andric }
514480093f4SDimitry Andric 
515*5ffd83dbSDimitry Andric struct TimeTracerRAII {
516*5ffd83dbSDimitry Andric   TimeTracerRAII(StringRef ProgramName) {
517*5ffd83dbSDimitry Andric     if (TimeTrace)
518*5ffd83dbSDimitry Andric       timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName);
519*5ffd83dbSDimitry Andric   }
520*5ffd83dbSDimitry Andric   ~TimeTracerRAII() {
521*5ffd83dbSDimitry Andric     if (TimeTrace) {
522*5ffd83dbSDimitry Andric       if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
523*5ffd83dbSDimitry Andric         handleAllErrors(std::move(E), [&](const StringError &SE) {
524*5ffd83dbSDimitry Andric           errs() << SE.getMessage() << "\n";
525*5ffd83dbSDimitry Andric         });
526*5ffd83dbSDimitry Andric         return;
527*5ffd83dbSDimitry Andric       }
528*5ffd83dbSDimitry Andric       timeTraceProfilerCleanup();
529*5ffd83dbSDimitry Andric     }
530*5ffd83dbSDimitry Andric   }
531*5ffd83dbSDimitry Andric };
532*5ffd83dbSDimitry Andric 
5330b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5340b57cec5SDimitry Andric // main for opt
5350b57cec5SDimitry Andric //
5360b57cec5SDimitry Andric int main(int argc, char **argv) {
5370b57cec5SDimitry Andric   InitLLVM X(argc, argv);
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   // Enable debug stream buffering.
5400b57cec5SDimitry Andric   EnableDebugBuffering = true;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   LLVMContext Context;
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   InitializeAllTargets();
5450b57cec5SDimitry Andric   InitializeAllTargetMCs();
5460b57cec5SDimitry Andric   InitializeAllAsmPrinters();
5470b57cec5SDimitry Andric   InitializeAllAsmParsers();
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   // Initialize passes
5500b57cec5SDimitry Andric   PassRegistry &Registry = *PassRegistry::getPassRegistry();
5510b57cec5SDimitry Andric   initializeCore(Registry);
5520b57cec5SDimitry Andric   initializeCoroutines(Registry);
5530b57cec5SDimitry Andric   initializeScalarOpts(Registry);
5540b57cec5SDimitry Andric   initializeObjCARCOpts(Registry);
5550b57cec5SDimitry Andric   initializeVectorization(Registry);
5560b57cec5SDimitry Andric   initializeIPO(Registry);
5570b57cec5SDimitry Andric   initializeAnalysis(Registry);
5580b57cec5SDimitry Andric   initializeTransformUtils(Registry);
5590b57cec5SDimitry Andric   initializeInstCombine(Registry);
5600b57cec5SDimitry Andric   initializeAggressiveInstCombine(Registry);
5610b57cec5SDimitry Andric   initializeInstrumentation(Registry);
5620b57cec5SDimitry Andric   initializeTarget(Registry);
5630b57cec5SDimitry Andric   // For codegen passes, only passes that do IR to IR transformation are
5640b57cec5SDimitry Andric   // supported.
5650b57cec5SDimitry Andric   initializeExpandMemCmpPassPass(Registry);
5660b57cec5SDimitry Andric   initializeScalarizeMaskedMemIntrinPass(Registry);
5670b57cec5SDimitry Andric   initializeCodeGenPreparePass(Registry);
5680b57cec5SDimitry Andric   initializeAtomicExpandPass(Registry);
5690b57cec5SDimitry Andric   initializeRewriteSymbolsLegacyPassPass(Registry);
5700b57cec5SDimitry Andric   initializeWinEHPreparePass(Registry);
5710b57cec5SDimitry Andric   initializeDwarfEHPreparePass(Registry);
5720b57cec5SDimitry Andric   initializeSafeStackLegacyPassPass(Registry);
5730b57cec5SDimitry Andric   initializeSjLjEHPreparePass(Registry);
5740b57cec5SDimitry Andric   initializePreISelIntrinsicLoweringLegacyPassPass(Registry);
5750b57cec5SDimitry Andric   initializeGlobalMergePass(Registry);
5760b57cec5SDimitry Andric   initializeIndirectBrExpandPassPass(Registry);
5770b57cec5SDimitry Andric   initializeInterleavedLoadCombinePass(Registry);
5780b57cec5SDimitry Andric   initializeInterleavedAccessPass(Registry);
5790b57cec5SDimitry Andric   initializeEntryExitInstrumenterPass(Registry);
5800b57cec5SDimitry Andric   initializePostInlineEntryExitInstrumenterPass(Registry);
5810b57cec5SDimitry Andric   initializeUnreachableBlockElimLegacyPassPass(Registry);
5820b57cec5SDimitry Andric   initializeExpandReductionsPass(Registry);
5830b57cec5SDimitry Andric   initializeWasmEHPreparePass(Registry);
5840b57cec5SDimitry Andric   initializeWriteBitcodePassPass(Registry);
5850b57cec5SDimitry Andric   initializeHardwareLoopsPass(Registry);
586480093f4SDimitry Andric   initializeTypePromotionPass(Registry);
5870b57cec5SDimitry Andric 
588480093f4SDimitry Andric #ifdef BUILD_EXAMPLES
589480093f4SDimitry Andric   initializeExampleIRTransforms(Registry);
5900b57cec5SDimitry Andric #endif
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   cl::ParseCommandLineOptions(argc, argv,
5930b57cec5SDimitry Andric     "llvm .bc -> .bc modular optimizer and analysis printer\n");
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   if (AnalyzeOnly && NoOutput) {
5960b57cec5SDimitry Andric     errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n";
5970b57cec5SDimitry Andric     return 1;
5980b57cec5SDimitry Andric   }
5990b57cec5SDimitry Andric 
600*5ffd83dbSDimitry Andric   TimeTracerRAII TimeTracer(argv[0]);
601*5ffd83dbSDimitry Andric 
6020b57cec5SDimitry Andric   SMDiagnostic Err;
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   Context.setDiscardValueNames(DiscardValueNames);
6050b57cec5SDimitry Andric   if (!DisableDITypeMap)
6060b57cec5SDimitry Andric     Context.enableDebugTypeODRUniquing();
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
609*5ffd83dbSDimitry Andric       setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
6100b57cec5SDimitry Andric                                    RemarksFormat, RemarksWithHotness,
6110b57cec5SDimitry Andric                                    RemarksHotnessThreshold);
6120b57cec5SDimitry Andric   if (Error E = RemarksFileOrErr.takeError()) {
6130b57cec5SDimitry Andric     errs() << toString(std::move(E)) << '\n';
6140b57cec5SDimitry Andric     return 1;
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric   std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr);
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   // Load the input module...
619*5ffd83dbSDimitry Andric   auto SetDataLayout = [](StringRef) -> Optional<std::string> {
620*5ffd83dbSDimitry Andric     if (ClDataLayout.empty())
621*5ffd83dbSDimitry Andric       return None;
622*5ffd83dbSDimitry Andric     return ClDataLayout;
623*5ffd83dbSDimitry Andric   };
624*5ffd83dbSDimitry Andric   std::unique_ptr<Module> M;
625*5ffd83dbSDimitry Andric   if (NoUpgradeDebugInfo)
626*5ffd83dbSDimitry Andric     M = parseAssemblyFileWithIndexNoUpgradeDebugInfo(
627*5ffd83dbSDimitry Andric             InputFilename, Err, Context, nullptr, SetDataLayout)
628*5ffd83dbSDimitry Andric             .Mod;
629*5ffd83dbSDimitry Andric   else
630*5ffd83dbSDimitry Andric     M = parseIRFile(InputFilename, Err, Context, SetDataLayout);
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   if (!M) {
6330b57cec5SDimitry Andric     Err.print(argv[0], errs());
6340b57cec5SDimitry Andric     return 1;
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   // Strip debug info before running the verifier.
6380b57cec5SDimitry Andric   if (StripDebug)
6390b57cec5SDimitry Andric     StripDebugInfo(*M);
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   // Erase module-level named metadata, if requested.
6420b57cec5SDimitry Andric   if (StripNamedMetadata) {
6430b57cec5SDimitry Andric     while (!M->named_metadata_empty()) {
6440b57cec5SDimitry Andric       NamedMDNode *NMD = &*M->named_metadata_begin();
6450b57cec5SDimitry Andric       M->eraseNamedMetadata(NMD);
6460b57cec5SDimitry Andric     }
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // If we are supposed to override the target triple or data layout, do so now.
6500b57cec5SDimitry Andric   if (!TargetTriple.empty())
6510b57cec5SDimitry Andric     M->setTargetTriple(Triple::normalize(TargetTriple));
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   // Immediately run the verifier to catch any problems before starting up the
6540b57cec5SDimitry Andric   // pass pipelines.  Otherwise we can crash on broken code during
6550b57cec5SDimitry Andric   // doInitialization().
6560b57cec5SDimitry Andric   if (!NoVerify && verifyModule(*M, &errs())) {
6570b57cec5SDimitry Andric     errs() << argv[0] << ": " << InputFilename
6580b57cec5SDimitry Andric            << ": error: input module is broken!\n";
6590b57cec5SDimitry Andric     return 1;
6600b57cec5SDimitry Andric   }
6610b57cec5SDimitry Andric 
662*5ffd83dbSDimitry Andric   // Enable testing of whole program devirtualization on this module by invoking
663*5ffd83dbSDimitry Andric   // the facility for updating public visibility to linkage unit visibility when
664*5ffd83dbSDimitry Andric   // specified by an internal option. This is normally done during LTO which is
665*5ffd83dbSDimitry Andric   // not performed via opt.
666*5ffd83dbSDimitry Andric   updateVCallVisibilityInModule(*M,
667*5ffd83dbSDimitry Andric                                 /* WholeProgramVisibilityEnabledInLTO */ false);
668*5ffd83dbSDimitry Andric 
6690b57cec5SDimitry Andric   // Figure out what stream we are supposed to write to...
6700b57cec5SDimitry Andric   std::unique_ptr<ToolOutputFile> Out;
6710b57cec5SDimitry Andric   std::unique_ptr<ToolOutputFile> ThinLinkOut;
6720b57cec5SDimitry Andric   if (NoOutput) {
6730b57cec5SDimitry Andric     if (!OutputFilename.empty())
6740b57cec5SDimitry Andric       errs() << "WARNING: The -o (output filename) option is ignored when\n"
6750b57cec5SDimitry Andric                 "the --disable-output option is used.\n";
6760b57cec5SDimitry Andric   } else {
6770b57cec5SDimitry Andric     // Default to standard output.
6780b57cec5SDimitry Andric     if (OutputFilename.empty())
6790b57cec5SDimitry Andric       OutputFilename = "-";
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric     std::error_code EC;
6828bcb0991SDimitry Andric     sys::fs::OpenFlags Flags = OutputAssembly ? sys::fs::OF_Text
6838bcb0991SDimitry Andric                                               : sys::fs::OF_None;
6848bcb0991SDimitry Andric     Out.reset(new ToolOutputFile(OutputFilename, EC, Flags));
6850b57cec5SDimitry Andric     if (EC) {
6860b57cec5SDimitry Andric       errs() << EC.message() << '\n';
6870b57cec5SDimitry Andric       return 1;
6880b57cec5SDimitry Andric     }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric     if (!ThinLinkBitcodeFile.empty()) {
6910b57cec5SDimitry Andric       ThinLinkOut.reset(
6928bcb0991SDimitry Andric           new ToolOutputFile(ThinLinkBitcodeFile, EC, sys::fs::OF_None));
6930b57cec5SDimitry Andric       if (EC) {
6940b57cec5SDimitry Andric         errs() << EC.message() << '\n';
6950b57cec5SDimitry Andric         return 1;
6960b57cec5SDimitry Andric       }
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   Triple ModuleTriple(M->getTargetTriple());
7010b57cec5SDimitry Andric   std::string CPUStr, FeaturesStr;
7020b57cec5SDimitry Andric   TargetMachine *Machine = nullptr;
703*5ffd83dbSDimitry Andric   const TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags();
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   if (ModuleTriple.getArch()) {
706*5ffd83dbSDimitry Andric     CPUStr = codegen::getCPUStr();
707*5ffd83dbSDimitry Andric     FeaturesStr = codegen::getFeaturesStr();
7080b57cec5SDimitry Andric     Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
7090b57cec5SDimitry Andric   } else if (ModuleTriple.getArchName() != "unknown" &&
7100b57cec5SDimitry Andric              ModuleTriple.getArchName() != "") {
7110b57cec5SDimitry Andric     errs() << argv[0] << ": unrecognized architecture '"
7120b57cec5SDimitry Andric            << ModuleTriple.getArchName() << "' provided.\n";
7130b57cec5SDimitry Andric     return 1;
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   std::unique_ptr<TargetMachine> TM(Machine);
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   // Override function attributes based on CPUStr, FeaturesStr, and command line
7190b57cec5SDimitry Andric   // flags.
720*5ffd83dbSDimitry Andric   codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   // If the output is set to be emitted to standard out, and standard out is a
7230b57cec5SDimitry Andric   // console, print out a warning message and refuse to do it.  We don't
7240b57cec5SDimitry Andric   // impress anyone by spewing tons of binary goo to a terminal.
7250b57cec5SDimitry Andric   if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly)
726*5ffd83dbSDimitry Andric     if (CheckBitcodeOutputToConsole(Out->os()))
7270b57cec5SDimitry Andric       NoOutput = true;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   if (OutputThinLTOBC)
7300b57cec5SDimitry Andric     M->addModuleFlag(Module::Error, "EnableSplitLTOUnit", SplitLTOUnit);
7310b57cec5SDimitry Andric 
732*5ffd83dbSDimitry Andric   if (EnableNewPassManager || PassPipeline.getNumOccurrences() > 0) {
733*5ffd83dbSDimitry Andric     if (PassPipeline.getNumOccurrences() > 0 && PassList.size() > 0) {
734*5ffd83dbSDimitry Andric       errs()
735*5ffd83dbSDimitry Andric           << "Cannot specify passes via both -foo-pass and --passes=foo-pass";
736*5ffd83dbSDimitry Andric       return 1;
737*5ffd83dbSDimitry Andric     }
738*5ffd83dbSDimitry Andric     SmallVector<StringRef, 4> Passes;
739*5ffd83dbSDimitry Andric     for (const auto &P : PassList) {
740*5ffd83dbSDimitry Andric       Passes.push_back(P->getPassArgument());
741*5ffd83dbSDimitry Andric     }
742*5ffd83dbSDimitry Andric     if (OptLevelO0)
743*5ffd83dbSDimitry Andric       Passes.push_back("default<O0>");
744*5ffd83dbSDimitry Andric     if (OptLevelO1)
745*5ffd83dbSDimitry Andric       Passes.push_back("default<O1>");
746*5ffd83dbSDimitry Andric     if (OptLevelO2)
747*5ffd83dbSDimitry Andric       Passes.push_back("default<O2>");
748*5ffd83dbSDimitry Andric     if (OptLevelO3)
749*5ffd83dbSDimitry Andric       Passes.push_back("default<O3>");
750*5ffd83dbSDimitry Andric     if (OptLevelOs)
751*5ffd83dbSDimitry Andric       Passes.push_back("default<Os>");
752*5ffd83dbSDimitry Andric     if (OptLevelOz)
753*5ffd83dbSDimitry Andric       Passes.push_back("default<Oz>");
7540b57cec5SDimitry Andric     OutputKind OK = OK_NoOutput;
7550b57cec5SDimitry Andric     if (!NoOutput)
7560b57cec5SDimitry Andric       OK = OutputAssembly
7570b57cec5SDimitry Andric                ? OK_OutputAssembly
7580b57cec5SDimitry Andric                : (OutputThinLTOBC ? OK_OutputThinLTOBitcode : OK_OutputBitcode);
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric     VerifierKind VK = VK_VerifyInAndOut;
7610b57cec5SDimitry Andric     if (NoVerify)
7620b57cec5SDimitry Andric       VK = VK_NoVerifier;
7630b57cec5SDimitry Andric     else if (VerifyEach)
7640b57cec5SDimitry Andric       VK = VK_VerifyEachPass;
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     // The user has asked to use the new pass manager and provided a pipeline
7670b57cec5SDimitry Andric     // string. Hand off the rest of the functionality to the new code for that
7680b57cec5SDimitry Andric     // layer.
7690b57cec5SDimitry Andric     return runPassPipeline(argv[0], *M, TM.get(), Out.get(), ThinLinkOut.get(),
770*5ffd83dbSDimitry Andric                            RemarksFile.get(), PassPipeline, Passes, OK, VK,
7710b57cec5SDimitry Andric                            PreserveAssemblyUseListOrder,
7720b57cec5SDimitry Andric                            PreserveBitcodeUseListOrder, EmitSummaryIndex,
773*5ffd83dbSDimitry Andric                            EmitModuleHash, EnableDebugify, Coroutines)
7740b57cec5SDimitry Andric                ? 0
7750b57cec5SDimitry Andric                : 1;
7760b57cec5SDimitry Andric   }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   // Create a PassManager to hold and optimize the collection of passes we are
7790b57cec5SDimitry Andric   // about to build.
7800b57cec5SDimitry Andric   OptCustomPassManager Passes;
7810b57cec5SDimitry Andric   bool AddOneTimeDebugifyPasses = EnableDebugify && !DebugifyEach;
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric   // Add an appropriate TargetLibraryInfo pass for the module's triple.
7840b57cec5SDimitry Andric   TargetLibraryInfoImpl TLII(ModuleTriple);
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   // The -disable-simplify-libcalls flag actually disables all builtin optzns.
7870b57cec5SDimitry Andric   if (DisableSimplifyLibCalls)
7880b57cec5SDimitry Andric     TLII.disableAllFunctions();
789480093f4SDimitry Andric   else {
790480093f4SDimitry Andric     // Disable individual builtin functions in TargetLibraryInfo.
791480093f4SDimitry Andric     LibFunc F;
792480093f4SDimitry Andric     for (auto &FuncName : DisableBuiltins)
793480093f4SDimitry Andric       if (TLII.getLibFunc(FuncName, F))
794480093f4SDimitry Andric         TLII.setUnavailable(F);
795480093f4SDimitry Andric       else {
796480093f4SDimitry Andric         errs() << argv[0] << ": cannot disable nonexistent builtin function "
797480093f4SDimitry Andric                << FuncName << '\n';
798480093f4SDimitry Andric         return 1;
799480093f4SDimitry Andric       }
800480093f4SDimitry Andric   }
801480093f4SDimitry Andric 
8020b57cec5SDimitry Andric   Passes.add(new TargetLibraryInfoWrapperPass(TLII));
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric   // Add internal analysis passes from the target machine.
8050b57cec5SDimitry Andric   Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis()
8060b57cec5SDimitry Andric                                                      : TargetIRAnalysis()));
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   if (AddOneTimeDebugifyPasses)
8090b57cec5SDimitry Andric     Passes.add(createDebugifyModulePass());
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric   std::unique_ptr<legacy::FunctionPassManager> FPasses;
8120b57cec5SDimitry Andric   if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
8130b57cec5SDimitry Andric       OptLevelO3) {
8140b57cec5SDimitry Andric     FPasses.reset(new legacy::FunctionPassManager(M.get()));
8150b57cec5SDimitry Andric     FPasses->add(createTargetTransformInfoWrapperPass(
8160b57cec5SDimitry Andric         TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()));
8170b57cec5SDimitry Andric   }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   if (PrintBreakpoints) {
8200b57cec5SDimitry Andric     // Default to standard output.
8210b57cec5SDimitry Andric     if (!Out) {
8220b57cec5SDimitry Andric       if (OutputFilename.empty())
8230b57cec5SDimitry Andric         OutputFilename = "-";
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric       std::error_code EC;
8268bcb0991SDimitry Andric       Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,
8278bcb0991SDimitry Andric                                               sys::fs::OF_None);
8280b57cec5SDimitry Andric       if (EC) {
8290b57cec5SDimitry Andric         errs() << EC.message() << '\n';
8300b57cec5SDimitry Andric         return 1;
8310b57cec5SDimitry Andric       }
8320b57cec5SDimitry Andric     }
8330b57cec5SDimitry Andric     Passes.add(createBreakpointPrinter(Out->os()));
8340b57cec5SDimitry Andric     NoOutput = true;
8350b57cec5SDimitry Andric   }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   if (TM) {
8380b57cec5SDimitry Andric     // FIXME: We should dyn_cast this when supported.
8390b57cec5SDimitry Andric     auto &LTM = static_cast<LLVMTargetMachine &>(*TM);
8400b57cec5SDimitry Andric     Pass *TPC = LTM.createPassConfig(Passes);
8410b57cec5SDimitry Andric     Passes.add(TPC);
8420b57cec5SDimitry Andric   }
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric   // Create a new optimization pass for each one specified on the command line
8450b57cec5SDimitry Andric   for (unsigned i = 0; i < PassList.size(); ++i) {
8460b57cec5SDimitry Andric     if (StandardLinkOpts &&
8470b57cec5SDimitry Andric         StandardLinkOpts.getPosition() < PassList.getPosition(i)) {
8480b57cec5SDimitry Andric       AddStandardLinkPasses(Passes);
8490b57cec5SDimitry Andric       StandardLinkOpts = false;
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric     if (OptLevelO0 && OptLevelO0.getPosition() < PassList.getPosition(i)) {
8530b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 0, 0);
8540b57cec5SDimitry Andric       OptLevelO0 = false;
8550b57cec5SDimitry Andric     }
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric     if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) {
8580b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 1, 0);
8590b57cec5SDimitry Andric       OptLevelO1 = false;
8600b57cec5SDimitry Andric     }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric     if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) {
8630b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 0);
8640b57cec5SDimitry Andric       OptLevelO2 = false;
8650b57cec5SDimitry Andric     }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric     if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) {
8680b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 1);
8690b57cec5SDimitry Andric       OptLevelOs = false;
8700b57cec5SDimitry Andric     }
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) {
8730b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 2);
8740b57cec5SDimitry Andric       OptLevelOz = false;
8750b57cec5SDimitry Andric     }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric     if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) {
8780b57cec5SDimitry Andric       AddOptimizationPasses(Passes, *FPasses, TM.get(), 3, 0);
8790b57cec5SDimitry Andric       OptLevelO3 = false;
8800b57cec5SDimitry Andric     }
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric     const PassInfo *PassInf = PassList[i];
8830b57cec5SDimitry Andric     Pass *P = nullptr;
8840b57cec5SDimitry Andric     if (PassInf->getNormalCtor())
8850b57cec5SDimitry Andric       P = PassInf->getNormalCtor()();
8860b57cec5SDimitry Andric     else
8870b57cec5SDimitry Andric       errs() << argv[0] << ": cannot create pass: "
8880b57cec5SDimitry Andric              << PassInf->getPassName() << "\n";
8890b57cec5SDimitry Andric     if (P) {
8900b57cec5SDimitry Andric       PassKind Kind = P->getPassKind();
8910b57cec5SDimitry Andric       addPass(Passes, P);
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric       if (AnalyzeOnly) {
8940b57cec5SDimitry Andric         switch (Kind) {
8950b57cec5SDimitry Andric         case PT_Region:
896*5ffd83dbSDimitry Andric           Passes.add(createRegionPassPrinter(PassInf, Out->os()));
8970b57cec5SDimitry Andric           break;
8980b57cec5SDimitry Andric         case PT_Loop:
899*5ffd83dbSDimitry Andric           Passes.add(createLoopPassPrinter(PassInf, Out->os()));
9000b57cec5SDimitry Andric           break;
9010b57cec5SDimitry Andric         case PT_Function:
902*5ffd83dbSDimitry Andric           Passes.add(createFunctionPassPrinter(PassInf, Out->os()));
9030b57cec5SDimitry Andric           break;
9040b57cec5SDimitry Andric         case PT_CallGraphSCC:
905*5ffd83dbSDimitry Andric           Passes.add(createCallGraphPassPrinter(PassInf, Out->os()));
9060b57cec5SDimitry Andric           break;
9070b57cec5SDimitry Andric         default:
908*5ffd83dbSDimitry Andric           Passes.add(createModulePassPrinter(PassInf, Out->os()));
9090b57cec5SDimitry Andric           break;
9100b57cec5SDimitry Andric         }
9110b57cec5SDimitry Andric       }
9120b57cec5SDimitry Andric     }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric     if (PrintEachXForm)
9150b57cec5SDimitry Andric       Passes.add(
9160b57cec5SDimitry Andric           createPrintModulePass(errs(), "", PreserveAssemblyUseListOrder));
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   if (StandardLinkOpts) {
9200b57cec5SDimitry Andric     AddStandardLinkPasses(Passes);
9210b57cec5SDimitry Andric     StandardLinkOpts = false;
9220b57cec5SDimitry Andric   }
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   if (OptLevelO0)
9250b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 0, 0);
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   if (OptLevelO1)
9280b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 1, 0);
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   if (OptLevelO2)
9310b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 0);
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric   if (OptLevelOs)
9340b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 1);
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   if (OptLevelOz)
9370b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 2);
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   if (OptLevelO3)
9400b57cec5SDimitry Andric     AddOptimizationPasses(Passes, *FPasses, TM.get(), 3, 0);
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   if (FPasses) {
9430b57cec5SDimitry Andric     FPasses->doInitialization();
9440b57cec5SDimitry Andric     for (Function &F : *M)
9450b57cec5SDimitry Andric       FPasses->run(F);
9460b57cec5SDimitry Andric     FPasses->doFinalization();
9470b57cec5SDimitry Andric   }
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   // Check that the module is well formed on completion of optimization
9500b57cec5SDimitry Andric   if (!NoVerify && !VerifyEach)
9510b57cec5SDimitry Andric     Passes.add(createVerifierPass());
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   if (AddOneTimeDebugifyPasses)
9540b57cec5SDimitry Andric     Passes.add(createCheckDebugifyModulePass(false));
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric   // In run twice mode, we want to make sure the output is bit-by-bit
9570b57cec5SDimitry Andric   // equivalent if we run the pass manager again, so setup two buffers and
9580b57cec5SDimitry Andric   // a stream to write to them. Note that llc does something similar and it
9590b57cec5SDimitry Andric   // may be worth to abstract this out in the future.
9600b57cec5SDimitry Andric   SmallVector<char, 0> Buffer;
9610b57cec5SDimitry Andric   SmallVector<char, 0> FirstRunBuffer;
9620b57cec5SDimitry Andric   std::unique_ptr<raw_svector_ostream> BOS;
9630b57cec5SDimitry Andric   raw_ostream *OS = nullptr;
9640b57cec5SDimitry Andric 
965480093f4SDimitry Andric   const bool ShouldEmitOutput = !NoOutput && !AnalyzeOnly;
966480093f4SDimitry Andric 
9670b57cec5SDimitry Andric   // Write bitcode or assembly to the output as the last step...
968480093f4SDimitry Andric   if (ShouldEmitOutput || RunTwice) {
9690b57cec5SDimitry Andric     assert(Out);
9700b57cec5SDimitry Andric     OS = &Out->os();
9710b57cec5SDimitry Andric     if (RunTwice) {
9728bcb0991SDimitry Andric       BOS = std::make_unique<raw_svector_ostream>(Buffer);
9730b57cec5SDimitry Andric       OS = BOS.get();
9740b57cec5SDimitry Andric     }
9750b57cec5SDimitry Andric     if (OutputAssembly) {
9760b57cec5SDimitry Andric       if (EmitSummaryIndex)
9770b57cec5SDimitry Andric         report_fatal_error("Text output is incompatible with -module-summary");
9780b57cec5SDimitry Andric       if (EmitModuleHash)
9790b57cec5SDimitry Andric         report_fatal_error("Text output is incompatible with -module-hash");
9800b57cec5SDimitry Andric       Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder));
9810b57cec5SDimitry Andric     } else if (OutputThinLTOBC)
9820b57cec5SDimitry Andric       Passes.add(createWriteThinLTOBitcodePass(
9830b57cec5SDimitry Andric           *OS, ThinLinkOut ? &ThinLinkOut->os() : nullptr));
9840b57cec5SDimitry Andric     else
9850b57cec5SDimitry Andric       Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder,
9860b57cec5SDimitry Andric                                          EmitSummaryIndex, EmitModuleHash));
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric   // Before executing passes, print the final values of the LLVM options.
9900b57cec5SDimitry Andric   cl::PrintOptionValues();
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   if (!RunTwice) {
9930b57cec5SDimitry Andric     // Now that we have all of the passes ready, run them.
9940b57cec5SDimitry Andric     Passes.run(*M);
9950b57cec5SDimitry Andric   } else {
9960b57cec5SDimitry Andric     // If requested, run all passes twice with the same pass manager to catch
9970b57cec5SDimitry Andric     // bugs caused by persistent state in the passes.
9980b57cec5SDimitry Andric     std::unique_ptr<Module> M2(CloneModule(*M));
9990b57cec5SDimitry Andric     // Run all passes on the original module first, so the second run processes
10000b57cec5SDimitry Andric     // the clone to catch CloneModule bugs.
10010b57cec5SDimitry Andric     Passes.run(*M);
10020b57cec5SDimitry Andric     FirstRunBuffer = Buffer;
10030b57cec5SDimitry Andric     Buffer.clear();
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric     Passes.run(*M2);
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric     // Compare the two outputs and make sure they're the same
10080b57cec5SDimitry Andric     assert(Out);
10090b57cec5SDimitry Andric     if (Buffer.size() != FirstRunBuffer.size() ||
10100b57cec5SDimitry Andric         (memcmp(Buffer.data(), FirstRunBuffer.data(), Buffer.size()) != 0)) {
10110b57cec5SDimitry Andric       errs()
10120b57cec5SDimitry Andric           << "Running the pass manager twice changed the output.\n"
10130b57cec5SDimitry Andric              "Writing the result of the second run to the specified output.\n"
10140b57cec5SDimitry Andric              "To generate the one-run comparison binary, just run without\n"
10150b57cec5SDimitry Andric              "the compile-twice option\n";
1016480093f4SDimitry Andric       if (ShouldEmitOutput) {
10170b57cec5SDimitry Andric         Out->os() << BOS->str();
10180b57cec5SDimitry Andric         Out->keep();
1019480093f4SDimitry Andric       }
10200b57cec5SDimitry Andric       if (RemarksFile)
10210b57cec5SDimitry Andric         RemarksFile->keep();
10220b57cec5SDimitry Andric       return 1;
10230b57cec5SDimitry Andric     }
1024480093f4SDimitry Andric     if (ShouldEmitOutput)
10250b57cec5SDimitry Andric       Out->os() << BOS->str();
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric   if (DebugifyEach && !DebugifyExport.empty())
10290b57cec5SDimitry Andric     exportDebugifyStats(DebugifyExport, Passes.getDebugifyStatsMap());
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   // Declare success.
10320b57cec5SDimitry Andric   if (!NoOutput || PrintBreakpoints)
10330b57cec5SDimitry Andric     Out->keep();
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   if (RemarksFile)
10360b57cec5SDimitry Andric     RemarksFile->keep();
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   if (ThinLinkOut)
10390b57cec5SDimitry Andric     ThinLinkOut->keep();
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   return 0;
10420b57cec5SDimitry Andric }
1043