xref: /src/contrib/llvm-project/llvm/lib/CodeGen/TargetPassConfig.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
19df3605dSDimitry Andric //===- TargetPassConfig.cpp - Target independent code generation passes ---===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric //
901095a5dSDimitry Andric // This file defines interfaces to access the target independent code
1001095a5dSDimitry Andric // generation passes provided by the LLVM backend.
1101095a5dSDimitry Andric //
1201095a5dSDimitry Andric //===---------------------------------------------------------------------===//
1301095a5dSDimitry Andric 
1401095a5dSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
159df3605dSDimitry Andric #include "llvm/ADT/DenseMap.h"
169df3605dSDimitry Andric #include "llvm/ADT/SmallVector.h"
179df3605dSDimitry Andric #include "llvm/ADT/StringRef.h"
1801095a5dSDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h"
1901095a5dSDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h"
2001095a5dSDimitry Andric #include "llvm/Analysis/ScopedNoAliasAA.h"
217ab83427SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
2201095a5dSDimitry Andric #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
23145449b1SDimitry Andric #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
24e6d15924SDimitry Andric #include "llvm/CodeGen/CSEConfigBase.h"
2501095a5dSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
269df3605dSDimitry Andric #include "llvm/CodeGen/MachinePassRegistry.h"
279df3605dSDimitry Andric #include "llvm/CodeGen/Passes.h"
2801095a5dSDimitry Andric #include "llvm/CodeGen/RegAllocRegistry.h"
2901095a5dSDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
3001095a5dSDimitry Andric #include "llvm/IR/LegacyPassManager.h"
31b60736ecSDimitry Andric #include "llvm/IR/PassInstrumentation.h"
3201095a5dSDimitry Andric #include "llvm/IR/Verifier.h"
33706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
3401095a5dSDimitry Andric #include "llvm/MC/MCAsmInfo.h"
359df3605dSDimitry Andric #include "llvm/MC/MCTargetOptions.h"
369df3605dSDimitry Andric #include "llvm/Pass.h"
379df3605dSDimitry Andric #include "llvm/Support/CodeGen.h"
389df3605dSDimitry Andric #include "llvm/Support/CommandLine.h"
399df3605dSDimitry Andric #include "llvm/Support/Compiler.h"
4001095a5dSDimitry Andric #include "llvm/Support/Debug.h"
41344a3780SDimitry Andric #include "llvm/Support/Discriminator.h"
4201095a5dSDimitry Andric #include "llvm/Support/ErrorHandling.h"
43d8e91e46SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
44706b4fc4SDimitry Andric #include "llvm/Support/Threading.h"
457fa27ce4SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
467fa27ce4SDimitry Andric #include "llvm/Support/WithColor.h"
47b60736ecSDimitry Andric #include "llvm/Target/CGPassBuilderOption.h"
4801095a5dSDimitry Andric #include "llvm/Target/TargetMachine.h"
4901095a5dSDimitry Andric #include "llvm/Transforms/Scalar.h"
50eb11fae6SDimitry Andric #include "llvm/Transforms/Utils.h"
519df3605dSDimitry Andric #include <cassert>
52e3b55780SDimitry Andric #include <optional>
539df3605dSDimitry Andric #include <string>
5401095a5dSDimitry Andric 
5501095a5dSDimitry Andric using namespace llvm;
5601095a5dSDimitry Andric 
571d5ae102SDimitry Andric static cl::opt<bool>
581d5ae102SDimitry Andric     EnableIPRA("enable-ipra", cl::init(false), cl::Hidden,
59044eb2f6SDimitry Andric                cl::desc("Enable interprocedural register allocation "
60044eb2f6SDimitry Andric                         "to reduce load/store at procedure calls."));
61b915e9e0SDimitry Andric static cl::opt<bool> DisablePostRASched("disable-post-ra", cl::Hidden,
62b915e9e0SDimitry Andric     cl::desc("Disable Post Regalloc Scheduler"));
6301095a5dSDimitry Andric static cl::opt<bool> DisableBranchFold("disable-branch-fold", cl::Hidden,
6401095a5dSDimitry Andric     cl::desc("Disable branch folding"));
6501095a5dSDimitry Andric static cl::opt<bool> DisableTailDuplicate("disable-tail-duplicate", cl::Hidden,
6601095a5dSDimitry Andric     cl::desc("Disable tail duplication"));
6701095a5dSDimitry Andric static cl::opt<bool> DisableEarlyTailDup("disable-early-taildup", cl::Hidden,
6801095a5dSDimitry Andric     cl::desc("Disable pre-register allocation tail duplication"));
6901095a5dSDimitry Andric static cl::opt<bool> DisableBlockPlacement("disable-block-placement",
7001095a5dSDimitry Andric     cl::Hidden, cl::desc("Disable probability-driven block placement"));
7101095a5dSDimitry Andric static cl::opt<bool> EnableBlockPlacementStats("enable-block-placement-stats",
7201095a5dSDimitry Andric     cl::Hidden, cl::desc("Collect probability-driven block placement stats"));
7301095a5dSDimitry Andric static cl::opt<bool> DisableSSC("disable-ssc", cl::Hidden,
7401095a5dSDimitry Andric     cl::desc("Disable Stack Slot Coloring"));
7501095a5dSDimitry Andric static cl::opt<bool> DisableMachineDCE("disable-machine-dce", cl::Hidden,
7601095a5dSDimitry Andric     cl::desc("Disable Machine Dead Code Elimination"));
7701095a5dSDimitry Andric static cl::opt<bool> DisableEarlyIfConversion("disable-early-ifcvt", cl::Hidden,
7801095a5dSDimitry Andric     cl::desc("Disable Early If-conversion"));
7901095a5dSDimitry Andric static cl::opt<bool> DisableMachineLICM("disable-machine-licm", cl::Hidden,
8001095a5dSDimitry Andric     cl::desc("Disable Machine LICM"));
8101095a5dSDimitry Andric static cl::opt<bool> DisableMachineCSE("disable-machine-cse", cl::Hidden,
8201095a5dSDimitry Andric     cl::desc("Disable Machine Common Subexpression Elimination"));
8301095a5dSDimitry Andric static cl::opt<cl::boolOrDefault> OptimizeRegAlloc(
8401095a5dSDimitry Andric     "optimize-regalloc", cl::Hidden,
8501095a5dSDimitry Andric     cl::desc("Enable optimized register allocation compilation path."));
8601095a5dSDimitry Andric static cl::opt<bool> DisablePostRAMachineLICM("disable-postra-machine-licm",
8701095a5dSDimitry Andric     cl::Hidden,
8801095a5dSDimitry Andric     cl::desc("Disable Machine LICM"));
8901095a5dSDimitry Andric static cl::opt<bool> DisableMachineSink("disable-machine-sink", cl::Hidden,
9001095a5dSDimitry Andric     cl::desc("Disable Machine Sinking"));
91eb11fae6SDimitry Andric static cl::opt<bool> DisablePostRAMachineSink("disable-postra-machine-sink",
92eb11fae6SDimitry Andric     cl::Hidden,
93eb11fae6SDimitry Andric     cl::desc("Disable PostRA Machine Sinking"));
9401095a5dSDimitry Andric static cl::opt<bool> DisableLSR("disable-lsr", cl::Hidden,
9501095a5dSDimitry Andric     cl::desc("Disable Loop Strength Reduction Pass"));
9601095a5dSDimitry Andric static cl::opt<bool> DisableConstantHoisting("disable-constant-hoisting",
9701095a5dSDimitry Andric     cl::Hidden, cl::desc("Disable ConstantHoisting"));
9801095a5dSDimitry Andric static cl::opt<bool> DisableCGP("disable-cgp", cl::Hidden,
9901095a5dSDimitry Andric     cl::desc("Disable Codegen Prepare"));
10001095a5dSDimitry Andric static cl::opt<bool> DisableCopyProp("disable-copyprop", cl::Hidden,
10101095a5dSDimitry Andric     cl::desc("Disable Copy Propagation pass"));
10201095a5dSDimitry Andric static cl::opt<bool> DisablePartialLibcallInlining("disable-partial-libcall-inlining",
10301095a5dSDimitry Andric     cl::Hidden, cl::desc("Disable Partial Libcall Inlining"));
1047fa27ce4SDimitry Andric static cl::opt<bool> DisableAtExitBasedGlobalDtorLowering(
1057fa27ce4SDimitry Andric     "disable-atexit-based-global-dtor-lowering", cl::Hidden,
1067fa27ce4SDimitry Andric     cl::desc("For MachO, disable atexit()-based global destructor lowering"));
10701095a5dSDimitry Andric static cl::opt<bool> EnableImplicitNullChecks(
10801095a5dSDimitry Andric     "enable-implicit-null-checks",
10901095a5dSDimitry Andric     cl::desc("Fold null checks into faulting memory operations"),
110044eb2f6SDimitry Andric     cl::init(false), cl::Hidden);
111eb11fae6SDimitry Andric static cl::opt<bool> DisableMergeICmps("disable-mergeicmps",
112eb11fae6SDimitry Andric     cl::desc("Disable MergeICmps Pass"),
113044eb2f6SDimitry Andric     cl::init(false), cl::Hidden);
11401095a5dSDimitry Andric static cl::opt<bool> PrintLSR("print-lsr-output", cl::Hidden,
11501095a5dSDimitry Andric     cl::desc("Print LLVM IR produced by the loop-reduce pass"));
116312c0ed1SDimitry Andric static cl::opt<bool>
117312c0ed1SDimitry Andric     PrintISelInput("print-isel-input", cl::Hidden,
11801095a5dSDimitry Andric                    cl::desc("Print LLVM IR input to isel pass"));
119d8e91e46SDimitry Andric static cl::opt<cl::boolOrDefault>
120d8e91e46SDimitry Andric     VerifyMachineCode("verify-machineinstrs", cl::Hidden,
121145449b1SDimitry Andric                       cl::desc("Verify generated machine code"));
122145449b1SDimitry Andric static cl::opt<cl::boolOrDefault>
123145449b1SDimitry Andric     DebugifyAndStripAll("debugify-and-strip-all-safe", cl::Hidden,
124145449b1SDimitry Andric                         cl::desc("Debugify MIR before and Strip debug after "
125145449b1SDimitry Andric                                  "each pass except those known to be unsafe "
126145449b1SDimitry Andric                                  "when debug info is present"));
127b60736ecSDimitry Andric static cl::opt<cl::boolOrDefault> DebugifyCheckAndStripAll(
128b60736ecSDimitry Andric     "debugify-check-and-strip-all-safe", cl::Hidden,
129b60736ecSDimitry Andric     cl::desc(
130b60736ecSDimitry Andric         "Debugify MIR before, by checking and stripping the debug info after, "
131145449b1SDimitry Andric         "each pass except those known to be unsafe when debug info is "
132145449b1SDimitry Andric         "present"));
133eb11fae6SDimitry Andric // Enable or disable the MachineOutliner.
134eb11fae6SDimitry Andric static cl::opt<RunOutliner> EnableMachineOutliner(
135eb11fae6SDimitry Andric     "enable-machine-outliner", cl::desc("Enable the machine outliner"),
136b60736ecSDimitry Andric     cl::Hidden, cl::ValueOptional, cl::init(RunOutliner::TargetDefault),
137b60736ecSDimitry Andric     cl::values(clEnumValN(RunOutliner::AlwaysOutline, "always",
138eb11fae6SDimitry Andric                           "Run on all functions guaranteed to be beneficial"),
139b60736ecSDimitry Andric                clEnumValN(RunOutliner::NeverOutline, "never",
140b60736ecSDimitry Andric                           "Disable all outlining"),
141eb11fae6SDimitry Andric                // Sentinel value for unspecified option.
142b60736ecSDimitry Andric                clEnumValN(RunOutliner::AlwaysOutline, "", "")));
143145449b1SDimitry Andric // Disable the pass to fix unwind information. Whether the pass is included in
144145449b1SDimitry Andric // the pipeline is controlled via the target options, this option serves as
145145449b1SDimitry Andric // manual override.
146145449b1SDimitry Andric static cl::opt<bool> DisableCFIFixup("disable-cfi-fixup", cl::Hidden,
147145449b1SDimitry Andric                                      cl::desc("Disable the CFI fixup pass"));
1487ab83427SDimitry Andric // Enable or disable FastISel. Both options are needed, because
1497ab83427SDimitry Andric // FastISel is enabled by default with -fast, and we wish to be
1507ab83427SDimitry Andric // able to enable or disable fast-isel independently from -O0.
1517ab83427SDimitry Andric static cl::opt<cl::boolOrDefault>
1527ab83427SDimitry Andric EnableFastISelOption("fast-isel", cl::Hidden,
1537ab83427SDimitry Andric   cl::desc("Enable the \"fast\" instruction selector"));
1547ab83427SDimitry Andric 
155eb11fae6SDimitry Andric static cl::opt<cl::boolOrDefault> EnableGlobalISelOption(
156eb11fae6SDimitry Andric     "global-isel", cl::Hidden,
1577ab83427SDimitry Andric     cl::desc("Enable the \"global\" instruction selector"));
15801095a5dSDimitry Andric 
159b60736ecSDimitry Andric // FIXME: remove this after switching to NPM or GlobalISel, whichever gets there
160b60736ecSDimitry Andric //        first...
161b60736ecSDimitry Andric static cl::opt<bool>
162b60736ecSDimitry Andric     PrintAfterISel("print-after-isel", cl::init(false), cl::Hidden,
163b60736ecSDimitry Andric                    cl::desc("Print machine instrs after ISel"));
16401095a5dSDimitry Andric 
165d8e91e46SDimitry Andric static cl::opt<GlobalISelAbortMode> EnableGlobalISelAbort(
166b915e9e0SDimitry Andric     "global-isel-abort", cl::Hidden,
167b915e9e0SDimitry Andric     cl::desc("Enable abort calls when \"global\" instruction selection "
168d8e91e46SDimitry Andric              "fails to lower/select an instruction"),
169d8e91e46SDimitry Andric     cl::values(
170d8e91e46SDimitry Andric         clEnumValN(GlobalISelAbortMode::Disable, "0", "Disable the abort"),
171d8e91e46SDimitry Andric         clEnumValN(GlobalISelAbortMode::Enable, "1", "Enable the abort"),
172d8e91e46SDimitry Andric         clEnumValN(GlobalISelAbortMode::DisableWithDiag, "2",
173d8e91e46SDimitry Andric                    "Disable the abort but emit a diagnostic on failure")));
174b915e9e0SDimitry Andric 
175c0981da4SDimitry Andric // Disable MIRProfileLoader before RegAlloc. This is for for debugging and
176c0981da4SDimitry Andric // tuning purpose.
177c0981da4SDimitry Andric static cl::opt<bool> DisableRAFSProfileLoader(
178145449b1SDimitry Andric     "disable-ra-fsprofile-loader", cl::init(false), cl::Hidden,
179c0981da4SDimitry Andric     cl::desc("Disable MIRProfileLoader before RegAlloc"));
180c0981da4SDimitry Andric // Disable MIRProfileLoader before BloackPlacement. This is for for debugging
181c0981da4SDimitry Andric // and tuning purpose.
182c0981da4SDimitry Andric static cl::opt<bool> DisableLayoutFSProfileLoader(
183145449b1SDimitry Andric     "disable-layout-fsprofile-loader", cl::init(false), cl::Hidden,
184c0981da4SDimitry Andric     cl::desc("Disable MIRProfileLoader before BlockPlacement"));
185c0981da4SDimitry Andric // Specify FSProfile file name.
186c0981da4SDimitry Andric static cl::opt<std::string>
187c0981da4SDimitry Andric     FSProfileFile("fs-profile-file", cl::init(""), cl::value_desc("filename"),
188c0981da4SDimitry Andric                   cl::desc("Flow Sensitive profile file name."), cl::Hidden);
189c0981da4SDimitry Andric // Specify Remapping file for FSProfile.
190c0981da4SDimitry Andric static cl::opt<std::string> FSRemappingFile(
191c0981da4SDimitry Andric     "fs-remapping-file", cl::init(""), cl::value_desc("filename"),
192c0981da4SDimitry Andric     cl::desc("Flow Sensitive profile remapping file name."), cl::Hidden);
193344a3780SDimitry Andric 
19401095a5dSDimitry Andric // Temporary option to allow experimenting with MachineScheduler as a post-RA
19501095a5dSDimitry Andric // scheduler. Targets can "properly" enable this with
19601095a5dSDimitry Andric // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID).
19701095a5dSDimitry Andric // Targets can return true in targetSchedulesPostRAScheduling() and
19801095a5dSDimitry Andric // insert a PostRA scheduling pass wherever it wants.
1991d5ae102SDimitry Andric static cl::opt<bool> MISchedPostRA(
2001d5ae102SDimitry Andric     "misched-postra", cl::Hidden,
2011d5ae102SDimitry Andric     cl::desc(
2021d5ae102SDimitry Andric         "Run MachineScheduler post regalloc (independent of preRA sched)"));
20301095a5dSDimitry Andric 
20401095a5dSDimitry Andric // Experimental option to run live interval analysis early.
20501095a5dSDimitry Andric static cl::opt<bool> EarlyLiveIntervals("early-live-intervals", cl::Hidden,
20601095a5dSDimitry Andric     cl::desc("Run live interval analysis earlier in the pipeline"));
20701095a5dSDimitry Andric 
208ac9a064cSDimitry Andric static cl::opt<bool> DisableReplaceWithVecLib(
209ac9a064cSDimitry Andric     "disable-replace-with-vec-lib", cl::Hidden,
210ac9a064cSDimitry Andric     cl::desc("Disable replace with vector math call pass"));
211ac9a064cSDimitry Andric 
212044eb2f6SDimitry Andric /// Option names for limiting the codegen pipeline.
213044eb2f6SDimitry Andric /// Those are used in error reporting and we didn't want
214044eb2f6SDimitry Andric /// to duplicate their names all over the place.
215706b4fc4SDimitry Andric static const char StartAfterOptName[] = "start-after";
216706b4fc4SDimitry Andric static const char StartBeforeOptName[] = "start-before";
217706b4fc4SDimitry Andric static const char StopAfterOptName[] = "stop-after";
218706b4fc4SDimitry Andric static const char StopBeforeOptName[] = "stop-before";
219044eb2f6SDimitry Andric 
220044eb2f6SDimitry Andric static cl::opt<std::string>
221044eb2f6SDimitry Andric     StartAfterOpt(StringRef(StartAfterOptName),
222044eb2f6SDimitry Andric                   cl::desc("Resume compilation after a specific pass"),
223044eb2f6SDimitry Andric                   cl::value_desc("pass-name"), cl::init(""), cl::Hidden);
224044eb2f6SDimitry Andric 
225044eb2f6SDimitry Andric static cl::opt<std::string>
226044eb2f6SDimitry Andric     StartBeforeOpt(StringRef(StartBeforeOptName),
227044eb2f6SDimitry Andric                    cl::desc("Resume compilation before a specific pass"),
228044eb2f6SDimitry Andric                    cl::value_desc("pass-name"), cl::init(""), cl::Hidden);
229044eb2f6SDimitry Andric 
230044eb2f6SDimitry Andric static cl::opt<std::string>
231044eb2f6SDimitry Andric     StopAfterOpt(StringRef(StopAfterOptName),
232044eb2f6SDimitry Andric                  cl::desc("Stop compilation after a specific pass"),
233044eb2f6SDimitry Andric                  cl::value_desc("pass-name"), cl::init(""), cl::Hidden);
234044eb2f6SDimitry Andric 
235044eb2f6SDimitry Andric static cl::opt<std::string>
236044eb2f6SDimitry Andric     StopBeforeOpt(StringRef(StopBeforeOptName),
237044eb2f6SDimitry Andric                   cl::desc("Stop compilation before a specific pass"),
238044eb2f6SDimitry Andric                   cl::value_desc("pass-name"), cl::init(""), cl::Hidden);
239044eb2f6SDimitry Andric 
240b60736ecSDimitry Andric /// Enable the machine function splitter pass.
241b60736ecSDimitry Andric static cl::opt<bool> EnableMachineFunctionSplitter(
242b60736ecSDimitry Andric     "enable-split-machine-functions", cl::Hidden,
243b60736ecSDimitry Andric     cl::desc("Split out cold blocks from machine functions based on profile "
244b60736ecSDimitry Andric              "information."));
245b60736ecSDimitry Andric 
246b60736ecSDimitry Andric /// Disable the expand reductions pass for testing.
247b60736ecSDimitry Andric static cl::opt<bool> DisableExpandReductions(
248b60736ecSDimitry Andric     "disable-expand-reductions", cl::init(false), cl::Hidden,
249b60736ecSDimitry Andric     cl::desc("Disable the expand reduction intrinsics pass from running"));
250b60736ecSDimitry Andric 
251145449b1SDimitry Andric /// Disable the select optimization pass.
252145449b1SDimitry Andric static cl::opt<bool> DisableSelectOptimize(
253145449b1SDimitry Andric     "disable-select-optimize", cl::init(true), cl::Hidden,
254145449b1SDimitry Andric     cl::desc("Disable the select-optimization pass from running"));
255145449b1SDimitry Andric 
256b1c73532SDimitry Andric /// Enable garbage-collecting empty basic blocks.
257b1c73532SDimitry Andric static cl::opt<bool>
258b1c73532SDimitry Andric     GCEmptyBlocks("gc-empty-basic-blocks", cl::init(false), cl::Hidden,
259b1c73532SDimitry Andric                   cl::desc("Enable garbage-collecting empty basic blocks"));
260b1c73532SDimitry Andric 
26101095a5dSDimitry Andric /// Allow standard passes to be disabled by command line options. This supports
26201095a5dSDimitry Andric /// simple binary flags that either suppress the pass or do nothing.
26301095a5dSDimitry Andric /// i.e. -disable-mypass=false has no effect.
26401095a5dSDimitry Andric /// These should be converted to boolOrDefault in order to use applyOverride.
applyDisable(IdentifyingPassPtr PassID,bool Override)26501095a5dSDimitry Andric static IdentifyingPassPtr applyDisable(IdentifyingPassPtr PassID,
26601095a5dSDimitry Andric                                        bool Override) {
26701095a5dSDimitry Andric   if (Override)
26801095a5dSDimitry Andric     return IdentifyingPassPtr();
26901095a5dSDimitry Andric   return PassID;
27001095a5dSDimitry Andric }
27101095a5dSDimitry Andric 
27201095a5dSDimitry Andric /// Allow standard passes to be disabled by the command line, regardless of who
27301095a5dSDimitry Andric /// is adding the pass.
27401095a5dSDimitry Andric ///
27501095a5dSDimitry Andric /// StandardID is the pass identified in the standard pass pipeline and provided
27601095a5dSDimitry Andric /// to addPass(). It may be a target-specific ID in the case that the target
27701095a5dSDimitry Andric /// directly adds its own pass, but in that case we harmlessly fall through.
27801095a5dSDimitry Andric ///
27901095a5dSDimitry Andric /// TargetID is the pass that the target has configured to override StandardID.
28001095a5dSDimitry Andric ///
28101095a5dSDimitry Andric /// StandardID may be a pseudo ID. In that case TargetID is the name of the real
28201095a5dSDimitry Andric /// pass to run. This allows multiple options to control a single pass depending
28301095a5dSDimitry Andric /// on where in the pipeline that pass is added.
overridePass(AnalysisID StandardID,IdentifyingPassPtr TargetID)28401095a5dSDimitry Andric static IdentifyingPassPtr overridePass(AnalysisID StandardID,
28501095a5dSDimitry Andric                                        IdentifyingPassPtr TargetID) {
28601095a5dSDimitry Andric   if (StandardID == &PostRASchedulerID)
287b915e9e0SDimitry Andric     return applyDisable(TargetID, DisablePostRASched);
28801095a5dSDimitry Andric 
28901095a5dSDimitry Andric   if (StandardID == &BranchFolderPassID)
29001095a5dSDimitry Andric     return applyDisable(TargetID, DisableBranchFold);
29101095a5dSDimitry Andric 
29201095a5dSDimitry Andric   if (StandardID == &TailDuplicateID)
29301095a5dSDimitry Andric     return applyDisable(TargetID, DisableTailDuplicate);
29401095a5dSDimitry Andric 
295eb11fae6SDimitry Andric   if (StandardID == &EarlyTailDuplicateID)
29601095a5dSDimitry Andric     return applyDisable(TargetID, DisableEarlyTailDup);
29701095a5dSDimitry Andric 
29801095a5dSDimitry Andric   if (StandardID == &MachineBlockPlacementID)
29901095a5dSDimitry Andric     return applyDisable(TargetID, DisableBlockPlacement);
30001095a5dSDimitry Andric 
30101095a5dSDimitry Andric   if (StandardID == &StackSlotColoringID)
30201095a5dSDimitry Andric     return applyDisable(TargetID, DisableSSC);
30301095a5dSDimitry Andric 
30401095a5dSDimitry Andric   if (StandardID == &DeadMachineInstructionElimID)
30501095a5dSDimitry Andric     return applyDisable(TargetID, DisableMachineDCE);
30601095a5dSDimitry Andric 
30701095a5dSDimitry Andric   if (StandardID == &EarlyIfConverterID)
30801095a5dSDimitry Andric     return applyDisable(TargetID, DisableEarlyIfConversion);
30901095a5dSDimitry Andric 
310eb11fae6SDimitry Andric   if (StandardID == &EarlyMachineLICMID)
31101095a5dSDimitry Andric     return applyDisable(TargetID, DisableMachineLICM);
31201095a5dSDimitry Andric 
31301095a5dSDimitry Andric   if (StandardID == &MachineCSEID)
31401095a5dSDimitry Andric     return applyDisable(TargetID, DisableMachineCSE);
31501095a5dSDimitry Andric 
316eb11fae6SDimitry Andric   if (StandardID == &MachineLICMID)
31701095a5dSDimitry Andric     return applyDisable(TargetID, DisablePostRAMachineLICM);
31801095a5dSDimitry Andric 
31901095a5dSDimitry Andric   if (StandardID == &MachineSinkingID)
32001095a5dSDimitry Andric     return applyDisable(TargetID, DisableMachineSink);
32101095a5dSDimitry Andric 
322eb11fae6SDimitry Andric   if (StandardID == &PostRAMachineSinkingID)
323eb11fae6SDimitry Andric     return applyDisable(TargetID, DisablePostRAMachineSink);
324eb11fae6SDimitry Andric 
32501095a5dSDimitry Andric   if (StandardID == &MachineCopyPropagationID)
32601095a5dSDimitry Andric     return applyDisable(TargetID, DisableCopyProp);
32701095a5dSDimitry Andric 
32801095a5dSDimitry Andric   return TargetID;
32901095a5dSDimitry Andric }
33001095a5dSDimitry Andric 
331c0981da4SDimitry Andric // Find the FSProfile file name. The internal option takes the precedence
332c0981da4SDimitry Andric // before getting from TargetMachine.
getFSProfileFile(const TargetMachine * TM)3336f8fc217SDimitry Andric static std::string getFSProfileFile(const TargetMachine *TM) {
334c0981da4SDimitry Andric   if (!FSProfileFile.empty())
335c0981da4SDimitry Andric     return FSProfileFile.getValue();
336e3b55780SDimitry Andric   const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
337e3b55780SDimitry Andric   if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
338c0981da4SDimitry Andric     return std::string();
339c0981da4SDimitry Andric   return PGOOpt->ProfileFile;
340c0981da4SDimitry Andric }
341c0981da4SDimitry Andric 
342c0981da4SDimitry Andric // Find the Profile remapping file name. The internal option takes the
343c0981da4SDimitry Andric // precedence before getting from TargetMachine.
getFSRemappingFile(const TargetMachine * TM)3446f8fc217SDimitry Andric static std::string getFSRemappingFile(const TargetMachine *TM) {
345c0981da4SDimitry Andric   if (!FSRemappingFile.empty())
346c0981da4SDimitry Andric     return FSRemappingFile.getValue();
347e3b55780SDimitry Andric   const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
348e3b55780SDimitry Andric   if (PGOOpt == std::nullopt || PGOOpt->Action != PGOOptions::SampleUse)
349c0981da4SDimitry Andric     return std::string();
350c0981da4SDimitry Andric   return PGOOpt->ProfileRemappingFile;
351c0981da4SDimitry Andric }
352c0981da4SDimitry Andric 
35301095a5dSDimitry Andric //===---------------------------------------------------------------------===//
35401095a5dSDimitry Andric /// TargetPassConfig
35501095a5dSDimitry Andric //===---------------------------------------------------------------------===//
35601095a5dSDimitry Andric 
35701095a5dSDimitry Andric INITIALIZE_PASS(TargetPassConfig, "targetpassconfig",
35801095a5dSDimitry Andric                 "Target Pass Configuration", false, false)
35901095a5dSDimitry Andric char TargetPassConfig::ID = 0;
36001095a5dSDimitry Andric 
36101095a5dSDimitry Andric namespace {
3629df3605dSDimitry Andric 
36301095a5dSDimitry Andric struct InsertedPass {
36401095a5dSDimitry Andric   AnalysisID TargetPassID;
36501095a5dSDimitry Andric   IdentifyingPassPtr InsertedPassID;
36601095a5dSDimitry Andric 
InsertedPass__anon3d82281d0111::InsertedPass367c0981da4SDimitry Andric   InsertedPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID)
368c0981da4SDimitry Andric       : TargetPassID(TargetPassID), InsertedPassID(InsertedPassID) {}
36901095a5dSDimitry Andric 
getInsertedPass__anon3d82281d0111::InsertedPass37001095a5dSDimitry Andric   Pass *getInsertedPass() const {
37101095a5dSDimitry Andric     assert(InsertedPassID.isValid() && "Illegal Pass ID!");
37201095a5dSDimitry Andric     if (InsertedPassID.isInstance())
37301095a5dSDimitry Andric       return InsertedPassID.getInstance();
37401095a5dSDimitry Andric     Pass *NP = Pass::createPass(InsertedPassID.getID());
37501095a5dSDimitry Andric     assert(NP && "Pass ID not registered");
37601095a5dSDimitry Andric     return NP;
37701095a5dSDimitry Andric   }
37801095a5dSDimitry Andric };
3799df3605dSDimitry Andric 
3809df3605dSDimitry Andric } // end anonymous namespace
38101095a5dSDimitry Andric 
38201095a5dSDimitry Andric namespace llvm {
3839df3605dSDimitry Andric 
384344a3780SDimitry Andric extern cl::opt<bool> EnableFSDiscriminator;
385344a3780SDimitry Andric 
38601095a5dSDimitry Andric class PassConfigImpl {
38701095a5dSDimitry Andric public:
38801095a5dSDimitry Andric   // List of passes explicitly substituted by this target. Normally this is
38901095a5dSDimitry Andric   // empty, but it is a convenient way to suppress or replace specific passes
39001095a5dSDimitry Andric   // that are part of a standard pass pipeline without overridding the entire
39101095a5dSDimitry Andric   // pipeline. This mechanism allows target options to inherit a standard pass's
39201095a5dSDimitry Andric   // user interface. For example, a target may disable a standard pass by
39301095a5dSDimitry Andric   // default by substituting a pass ID of zero, and the user may still enable
39401095a5dSDimitry Andric   // that standard pass with an explicit command line option.
39501095a5dSDimitry Andric   DenseMap<AnalysisID,IdentifyingPassPtr> TargetPasses;
39601095a5dSDimitry Andric 
39701095a5dSDimitry Andric   /// Store the pairs of <AnalysisID, AnalysisID> of which the second pass
39801095a5dSDimitry Andric   /// is inserted after each instance of the first one.
39901095a5dSDimitry Andric   SmallVector<InsertedPass, 4> InsertedPasses;
40001095a5dSDimitry Andric };
4019df3605dSDimitry Andric 
4029df3605dSDimitry Andric } // end namespace llvm
40301095a5dSDimitry Andric 
40401095a5dSDimitry Andric // Out of line virtual method.
~TargetPassConfig()40501095a5dSDimitry Andric TargetPassConfig::~TargetPassConfig() {
40601095a5dSDimitry Andric   delete Impl;
40701095a5dSDimitry Andric }
40801095a5dSDimitry Andric 
getPassInfo(StringRef PassName)409044eb2f6SDimitry Andric static const PassInfo *getPassInfo(StringRef PassName) {
410044eb2f6SDimitry Andric   if (PassName.empty())
411044eb2f6SDimitry Andric     return nullptr;
412044eb2f6SDimitry Andric 
413044eb2f6SDimitry Andric   const PassRegistry &PR = *PassRegistry::getPassRegistry();
414044eb2f6SDimitry Andric   const PassInfo *PI = PR.getPassInfo(PassName);
415044eb2f6SDimitry Andric   if (!PI)
416044eb2f6SDimitry Andric     report_fatal_error(Twine('\"') + Twine(PassName) +
417044eb2f6SDimitry Andric                        Twine("\" pass is not registered."));
418044eb2f6SDimitry Andric   return PI;
419044eb2f6SDimitry Andric }
420044eb2f6SDimitry Andric 
getPassIDFromName(StringRef PassName)421044eb2f6SDimitry Andric static AnalysisID getPassIDFromName(StringRef PassName) {
422044eb2f6SDimitry Andric   const PassInfo *PI = getPassInfo(PassName);
423044eb2f6SDimitry Andric   return PI ? PI->getTypeInfo() : nullptr;
424044eb2f6SDimitry Andric }
425044eb2f6SDimitry Andric 
426d8e91e46SDimitry Andric static std::pair<StringRef, unsigned>
getPassNameAndInstanceNum(StringRef PassName)427d8e91e46SDimitry Andric getPassNameAndInstanceNum(StringRef PassName) {
428d8e91e46SDimitry Andric   StringRef Name, InstanceNumStr;
429d8e91e46SDimitry Andric   std::tie(Name, InstanceNumStr) = PassName.split(',');
430d8e91e46SDimitry Andric 
431d8e91e46SDimitry Andric   unsigned InstanceNum = 0;
432d8e91e46SDimitry Andric   if (!InstanceNumStr.empty() && InstanceNumStr.getAsInteger(10, InstanceNum))
433d8e91e46SDimitry Andric     report_fatal_error("invalid pass instance specifier " + PassName);
434d8e91e46SDimitry Andric 
435d8e91e46SDimitry Andric   return std::make_pair(Name, InstanceNum);
436d8e91e46SDimitry Andric }
437d8e91e46SDimitry Andric 
setStartStopPasses()438044eb2f6SDimitry Andric void TargetPassConfig::setStartStopPasses() {
439d8e91e46SDimitry Andric   StringRef StartBeforeName;
440d8e91e46SDimitry Andric   std::tie(StartBeforeName, StartBeforeInstanceNum) =
441d8e91e46SDimitry Andric     getPassNameAndInstanceNum(StartBeforeOpt);
442d8e91e46SDimitry Andric 
443d8e91e46SDimitry Andric   StringRef StartAfterName;
444d8e91e46SDimitry Andric   std::tie(StartAfterName, StartAfterInstanceNum) =
445d8e91e46SDimitry Andric     getPassNameAndInstanceNum(StartAfterOpt);
446d8e91e46SDimitry Andric 
447d8e91e46SDimitry Andric   StringRef StopBeforeName;
448d8e91e46SDimitry Andric   std::tie(StopBeforeName, StopBeforeInstanceNum)
449d8e91e46SDimitry Andric     = getPassNameAndInstanceNum(StopBeforeOpt);
450d8e91e46SDimitry Andric 
451d8e91e46SDimitry Andric   StringRef StopAfterName;
452d8e91e46SDimitry Andric   std::tie(StopAfterName, StopAfterInstanceNum)
453d8e91e46SDimitry Andric     = getPassNameAndInstanceNum(StopAfterOpt);
454d8e91e46SDimitry Andric 
455d8e91e46SDimitry Andric   StartBefore = getPassIDFromName(StartBeforeName);
456d8e91e46SDimitry Andric   StartAfter = getPassIDFromName(StartAfterName);
457d8e91e46SDimitry Andric   StopBefore = getPassIDFromName(StopBeforeName);
458d8e91e46SDimitry Andric   StopAfter = getPassIDFromName(StopAfterName);
459044eb2f6SDimitry Andric   if (StartBefore && StartAfter)
460044eb2f6SDimitry Andric     report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") +
461044eb2f6SDimitry Andric                        Twine(StartAfterOptName) + Twine(" specified!"));
462044eb2f6SDimitry Andric   if (StopBefore && StopAfter)
463044eb2f6SDimitry Andric     report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
464044eb2f6SDimitry Andric                        Twine(StopAfterOptName) + Twine(" specified!"));
465044eb2f6SDimitry Andric   Started = (StartAfter == nullptr) && (StartBefore == nullptr);
466044eb2f6SDimitry Andric }
467044eb2f6SDimitry Andric 
getCGPassBuilderOption()468b60736ecSDimitry Andric CGPassBuilderOption llvm::getCGPassBuilderOption() {
469b60736ecSDimitry Andric   CGPassBuilderOption Opt;
470b60736ecSDimitry Andric 
471b60736ecSDimitry Andric #define SET_OPTION(Option)                                                     \
472b60736ecSDimitry Andric   if (Option.getNumOccurrences())                                              \
473b60736ecSDimitry Andric     Opt.Option = Option;
474b60736ecSDimitry Andric 
475b60736ecSDimitry Andric   SET_OPTION(EnableFastISelOption)
476b60736ecSDimitry Andric   SET_OPTION(EnableGlobalISelAbort)
477b60736ecSDimitry Andric   SET_OPTION(EnableGlobalISelOption)
478b60736ecSDimitry Andric   SET_OPTION(EnableIPRA)
479b60736ecSDimitry Andric   SET_OPTION(OptimizeRegAlloc)
480b60736ecSDimitry Andric   SET_OPTION(VerifyMachineCode)
481312c0ed1SDimitry Andric   SET_OPTION(DisableAtExitBasedGlobalDtorLowering)
482312c0ed1SDimitry Andric   SET_OPTION(DisableExpandReductions)
483312c0ed1SDimitry Andric   SET_OPTION(PrintAfterISel)
484312c0ed1SDimitry Andric   SET_OPTION(FSProfileFile)
485312c0ed1SDimitry Andric   SET_OPTION(GCEmptyBlocks)
486b60736ecSDimitry Andric 
487b60736ecSDimitry Andric #define SET_BOOLEAN_OPTION(Option) Opt.Option = Option;
488b60736ecSDimitry Andric 
489b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(EarlyLiveIntervals)
490b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(EnableBlockPlacementStats)
491b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(EnableImplicitNullChecks)
492b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(EnableMachineOutliner)
493b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(MISchedPostRA)
494b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(DisableMergeICmps)
495b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(DisableLSR)
496b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(DisableConstantHoisting)
497b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(DisableCGP)
498b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(DisablePartialLibcallInlining)
499145449b1SDimitry Andric   SET_BOOLEAN_OPTION(DisableSelectOptimize)
500b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(PrintLSR)
501b60736ecSDimitry Andric   SET_BOOLEAN_OPTION(PrintISelInput)
502312c0ed1SDimitry Andric   SET_BOOLEAN_OPTION(DebugifyAndStripAll)
503312c0ed1SDimitry Andric   SET_BOOLEAN_OPTION(DebugifyCheckAndStripAll)
504312c0ed1SDimitry Andric   SET_BOOLEAN_OPTION(DisableRAFSProfileLoader)
505312c0ed1SDimitry Andric   SET_BOOLEAN_OPTION(DisableCFIFixup)
506312c0ed1SDimitry Andric   SET_BOOLEAN_OPTION(EnableMachineFunctionSplitter)
507b60736ecSDimitry Andric 
508b60736ecSDimitry Andric   return Opt;
509b60736ecSDimitry Andric }
510b60736ecSDimitry Andric 
registerCodeGenCallback(PassInstrumentationCallbacks & PIC,LLVMTargetMachine & LLVMTM)511b60736ecSDimitry Andric void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
512b60736ecSDimitry Andric                                    LLVMTargetMachine &LLVMTM) {
513b60736ecSDimitry Andric 
514b60736ecSDimitry Andric   // Register a callback for disabling passes.
515b60736ecSDimitry Andric   PIC.registerShouldRunOptionalPassCallback([](StringRef P, Any) {
516b60736ecSDimitry Andric 
517b60736ecSDimitry Andric #define DISABLE_PASS(Option, Name)                                             \
518b60736ecSDimitry Andric   if (Option && P.contains(#Name))                                             \
519b60736ecSDimitry Andric     return false;
520b60736ecSDimitry Andric     DISABLE_PASS(DisableBlockPlacement, MachineBlockPlacementPass)
521b60736ecSDimitry Andric     DISABLE_PASS(DisableBranchFold, BranchFolderPass)
522b60736ecSDimitry Andric     DISABLE_PASS(DisableCopyProp, MachineCopyPropagationPass)
523b60736ecSDimitry Andric     DISABLE_PASS(DisableEarlyIfConversion, EarlyIfConverterPass)
524b60736ecSDimitry Andric     DISABLE_PASS(DisableEarlyTailDup, EarlyTailDuplicatePass)
525b60736ecSDimitry Andric     DISABLE_PASS(DisableMachineCSE, MachineCSEPass)
526b60736ecSDimitry Andric     DISABLE_PASS(DisableMachineDCE, DeadMachineInstructionElimPass)
527b60736ecSDimitry Andric     DISABLE_PASS(DisableMachineLICM, EarlyMachineLICMPass)
528b60736ecSDimitry Andric     DISABLE_PASS(DisableMachineSink, MachineSinkingPass)
529b60736ecSDimitry Andric     DISABLE_PASS(DisablePostRAMachineLICM, MachineLICMPass)
530b60736ecSDimitry Andric     DISABLE_PASS(DisablePostRAMachineSink, PostRAMachineSinkingPass)
531b60736ecSDimitry Andric     DISABLE_PASS(DisablePostRASched, PostRASchedulerPass)
532b60736ecSDimitry Andric     DISABLE_PASS(DisableSSC, StackSlotColoringPass)
533b60736ecSDimitry Andric     DISABLE_PASS(DisableTailDuplicate, TailDuplicatePass)
534b60736ecSDimitry Andric 
535b60736ecSDimitry Andric     return true;
536b60736ecSDimitry Andric   });
5374df029ccSDimitry Andric }
538b60736ecSDimitry Andric 
5394df029ccSDimitry Andric Expected<TargetPassConfig::StartStopInfo>
getStartStopInfo(PassInstrumentationCallbacks & PIC)5404df029ccSDimitry Andric TargetPassConfig::getStartStopInfo(PassInstrumentationCallbacks &PIC) {
5414df029ccSDimitry Andric   auto [StartBefore, StartBeforeInstanceNum] =
5424df029ccSDimitry Andric       getPassNameAndInstanceNum(StartBeforeOpt);
5434df029ccSDimitry Andric   auto [StartAfter, StartAfterInstanceNum] =
5444df029ccSDimitry Andric       getPassNameAndInstanceNum(StartAfterOpt);
5454df029ccSDimitry Andric   auto [StopBefore, StopBeforeInstanceNum] =
5464df029ccSDimitry Andric       getPassNameAndInstanceNum(StopBeforeOpt);
5474df029ccSDimitry Andric   auto [StopAfter, StopAfterInstanceNum] =
5484df029ccSDimitry Andric       getPassNameAndInstanceNum(StopAfterOpt);
5494df029ccSDimitry Andric 
5504df029ccSDimitry Andric   if (!StartBefore.empty() && !StartAfter.empty())
5514df029ccSDimitry Andric     return make_error<StringError>(
5524df029ccSDimitry Andric         Twine(StartBeforeOptName) + " and " + StartAfterOptName + " specified!",
5534df029ccSDimitry Andric         std::make_error_code(std::errc::invalid_argument));
5544df029ccSDimitry Andric   if (!StopBefore.empty() && !StopAfter.empty())
5554df029ccSDimitry Andric     return make_error<StringError>(
5564df029ccSDimitry Andric         Twine(StopBeforeOptName) + " and " + StopAfterOptName + " specified!",
5574df029ccSDimitry Andric         std::make_error_code(std::errc::invalid_argument));
5584df029ccSDimitry Andric 
5594df029ccSDimitry Andric   StartStopInfo Result;
5604df029ccSDimitry Andric   Result.StartPass = StartBefore.empty() ? StartAfter : StartBefore;
5614df029ccSDimitry Andric   Result.StopPass = StopBefore.empty() ? StopAfter : StopBefore;
5624df029ccSDimitry Andric   Result.StartInstanceNum =
5634df029ccSDimitry Andric       StartBefore.empty() ? StartAfterInstanceNum : StartBeforeInstanceNum;
5644df029ccSDimitry Andric   Result.StopInstanceNum =
5654df029ccSDimitry Andric       StopBefore.empty() ? StopAfterInstanceNum : StopBeforeInstanceNum;
5664df029ccSDimitry Andric   Result.StartAfter = !StartAfter.empty();
5674df029ccSDimitry Andric   Result.StopAfter = !StopAfter.empty();
5684df029ccSDimitry Andric   Result.StartInstanceNum += Result.StartInstanceNum == 0;
5694df029ccSDimitry Andric   Result.StopInstanceNum += Result.StopInstanceNum == 0;
5704df029ccSDimitry Andric   return Result;
571b60736ecSDimitry Andric }
572b60736ecSDimitry Andric 
57301095a5dSDimitry Andric // Out of line constructor provides default values for pass options and
57401095a5dSDimitry Andric // registers all common codegen passes.
TargetPassConfig(LLVMTargetMachine & TM,PassManagerBase & pm)575f382538dSDimitry Andric TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
5769df3605dSDimitry Andric     : ImmutablePass(ID), PM(&pm), TM(&TM) {
57701095a5dSDimitry Andric   Impl = new PassConfigImpl();
57801095a5dSDimitry Andric 
57901095a5dSDimitry Andric   // Register all target independent codegen passes to activate their PassIDs,
58001095a5dSDimitry Andric   // including this pass itself.
58101095a5dSDimitry Andric   initializeCodeGen(*PassRegistry::getPassRegistry());
58201095a5dSDimitry Andric 
58301095a5dSDimitry Andric   // Also register alias analysis passes required by codegen passes.
58401095a5dSDimitry Andric   initializeBasicAAWrapperPassPass(*PassRegistry::getPassRegistry());
58501095a5dSDimitry Andric   initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
58601095a5dSDimitry Andric 
587044eb2f6SDimitry Andric   if (EnableIPRA.getNumOccurrences())
588044eb2f6SDimitry Andric     TM.Options.EnableIPRA = EnableIPRA;
589044eb2f6SDimitry Andric   else {
590044eb2f6SDimitry Andric     // If not explicitly specified, use target default.
591e6d15924SDimitry Andric     TM.Options.EnableIPRA |= TM.useIPRA();
592044eb2f6SDimitry Andric   }
593044eb2f6SDimitry Andric 
594f382538dSDimitry Andric   if (TM.Options.EnableIPRA)
59571d5a254SDimitry Andric     setRequiresCodeGenSCCOrder();
596044eb2f6SDimitry Andric 
597d8e91e46SDimitry Andric   if (EnableGlobalISelAbort.getNumOccurrences())
598d8e91e46SDimitry Andric     TM.Options.GlobalISelAbort = EnableGlobalISelAbort;
599d8e91e46SDimitry Andric 
600044eb2f6SDimitry Andric   setStartStopPasses();
60101095a5dSDimitry Andric }
60201095a5dSDimitry Andric 
getOptLevel() const603b1c73532SDimitry Andric CodeGenOptLevel TargetPassConfig::getOptLevel() const {
60401095a5dSDimitry Andric   return TM->getOptLevel();
60501095a5dSDimitry Andric }
60601095a5dSDimitry Andric 
60701095a5dSDimitry Andric /// Insert InsertedPassID pass after TargetPassID.
insertPass(AnalysisID TargetPassID,IdentifyingPassPtr InsertedPassID)60801095a5dSDimitry Andric void TargetPassConfig::insertPass(AnalysisID TargetPassID,
609c0981da4SDimitry Andric                                   IdentifyingPassPtr InsertedPassID) {
61001095a5dSDimitry Andric   assert(((!InsertedPassID.isInstance() &&
61101095a5dSDimitry Andric            TargetPassID != InsertedPassID.getID()) ||
61201095a5dSDimitry Andric           (InsertedPassID.isInstance() &&
61301095a5dSDimitry Andric            TargetPassID != InsertedPassID.getInstance()->getPassID())) &&
61401095a5dSDimitry Andric          "Insert a pass after itself!");
615c0981da4SDimitry Andric   Impl->InsertedPasses.emplace_back(TargetPassID, InsertedPassID);
61601095a5dSDimitry Andric }
61701095a5dSDimitry Andric 
61801095a5dSDimitry Andric /// createPassConfig - Create a pass configuration object to be used by
61901095a5dSDimitry Andric /// addPassToEmitX methods for generating a pipeline of CodeGen passes.
62001095a5dSDimitry Andric ///
62101095a5dSDimitry Andric /// Targets may override this to extend TargetPassConfig.
createPassConfig(PassManagerBase & PM)62201095a5dSDimitry Andric TargetPassConfig *LLVMTargetMachine::createPassConfig(PassManagerBase &PM) {
623f382538dSDimitry Andric   return new TargetPassConfig(*this, PM);
62401095a5dSDimitry Andric }
62501095a5dSDimitry Andric 
TargetPassConfig()62601095a5dSDimitry Andric TargetPassConfig::TargetPassConfig()
6279df3605dSDimitry Andric   : ImmutablePass(ID) {
628b5630dbaSDimitry Andric   report_fatal_error("Trying to construct TargetPassConfig without a target "
629b5630dbaSDimitry Andric                      "machine. Scheduling a CodeGen pass without a target "
630b5630dbaSDimitry Andric                      "triple set?");
63101095a5dSDimitry Andric }
63201095a5dSDimitry Andric 
willCompleteCodeGenPipeline()633d8e91e46SDimitry Andric bool TargetPassConfig::willCompleteCodeGenPipeline() {
634d8e91e46SDimitry Andric   return StopBeforeOpt.empty() && StopAfterOpt.empty();
635d8e91e46SDimitry Andric }
636d8e91e46SDimitry Andric 
hasLimitedCodeGenPipeline()637d8e91e46SDimitry Andric bool TargetPassConfig::hasLimitedCodeGenPipeline() {
638d8e91e46SDimitry Andric   return !StartBeforeOpt.empty() || !StartAfterOpt.empty() ||
639d8e91e46SDimitry Andric          !willCompleteCodeGenPipeline();
640044eb2f6SDimitry Andric }
641044eb2f6SDimitry Andric 
getLimitedCodeGenPipelineReason()6424df029ccSDimitry Andric std::string TargetPassConfig::getLimitedCodeGenPipelineReason() {
643044eb2f6SDimitry Andric   if (!hasLimitedCodeGenPipeline())
644044eb2f6SDimitry Andric     return std::string();
645044eb2f6SDimitry Andric   std::string Res;
646044eb2f6SDimitry Andric   static cl::opt<std::string> *PassNames[] = {&StartAfterOpt, &StartBeforeOpt,
647044eb2f6SDimitry Andric                                               &StopAfterOpt, &StopBeforeOpt};
648044eb2f6SDimitry Andric   static const char *OptNames[] = {StartAfterOptName, StartBeforeOptName,
649044eb2f6SDimitry Andric                                    StopAfterOptName, StopBeforeOptName};
650044eb2f6SDimitry Andric   bool IsFirst = true;
651044eb2f6SDimitry Andric   for (int Idx = 0; Idx < 4; ++Idx)
652044eb2f6SDimitry Andric     if (!PassNames[Idx]->empty()) {
653044eb2f6SDimitry Andric       if (!IsFirst)
6544df029ccSDimitry Andric         Res += " and ";
655044eb2f6SDimitry Andric       IsFirst = false;
656044eb2f6SDimitry Andric       Res += OptNames[Idx];
657044eb2f6SDimitry Andric     }
658044eb2f6SDimitry Andric   return Res;
659044eb2f6SDimitry Andric }
660044eb2f6SDimitry Andric 
66101095a5dSDimitry Andric // Helper to verify the analysis is really immutable.
setOpt(bool & Opt,bool Val)66201095a5dSDimitry Andric void TargetPassConfig::setOpt(bool &Opt, bool Val) {
66301095a5dSDimitry Andric   assert(!Initialized && "PassConfig is immutable");
66401095a5dSDimitry Andric   Opt = Val;
66501095a5dSDimitry Andric }
66601095a5dSDimitry Andric 
substitutePass(AnalysisID StandardID,IdentifyingPassPtr TargetID)66701095a5dSDimitry Andric void TargetPassConfig::substitutePass(AnalysisID StandardID,
66801095a5dSDimitry Andric                                       IdentifyingPassPtr TargetID) {
66901095a5dSDimitry Andric   Impl->TargetPasses[StandardID] = TargetID;
67001095a5dSDimitry Andric }
67101095a5dSDimitry Andric 
getPassSubstitution(AnalysisID ID) const67201095a5dSDimitry Andric IdentifyingPassPtr TargetPassConfig::getPassSubstitution(AnalysisID ID) const {
67301095a5dSDimitry Andric   DenseMap<AnalysisID, IdentifyingPassPtr>::const_iterator
67401095a5dSDimitry Andric     I = Impl->TargetPasses.find(ID);
67501095a5dSDimitry Andric   if (I == Impl->TargetPasses.end())
67601095a5dSDimitry Andric     return ID;
67701095a5dSDimitry Andric   return I->second;
67801095a5dSDimitry Andric }
67901095a5dSDimitry Andric 
isPassSubstitutedOrOverridden(AnalysisID ID) const68001095a5dSDimitry Andric bool TargetPassConfig::isPassSubstitutedOrOverridden(AnalysisID ID) const {
68101095a5dSDimitry Andric   IdentifyingPassPtr TargetID = getPassSubstitution(ID);
68201095a5dSDimitry Andric   IdentifyingPassPtr FinalPtr = overridePass(ID, TargetID);
68301095a5dSDimitry Andric   return !FinalPtr.isValid() || FinalPtr.isInstance() ||
68401095a5dSDimitry Andric       FinalPtr.getID() != ID;
68501095a5dSDimitry Andric }
68601095a5dSDimitry Andric 
68701095a5dSDimitry Andric /// Add a pass to the PassManager if that pass is supposed to be run.  If the
68801095a5dSDimitry Andric /// Started/Stopped flags indicate either that the compilation should start at
68901095a5dSDimitry Andric /// a later pass or that it should stop after an earlier pass, then do not add
69001095a5dSDimitry Andric /// the pass.  Finally, compare the current pass against the StartAfter
69101095a5dSDimitry Andric /// and StopAfter options and change the Started/Stopped flags accordingly.
addPass(Pass * P)692c0981da4SDimitry Andric void TargetPassConfig::addPass(Pass *P) {
69301095a5dSDimitry Andric   assert(!Initialized && "PassConfig is immutable");
69401095a5dSDimitry Andric 
69501095a5dSDimitry Andric   // Cache the Pass ID here in case the pass manager finds this pass is
69601095a5dSDimitry Andric   // redundant with ones already scheduled / available, and deletes it.
69701095a5dSDimitry Andric   // Fundamentally, once we add the pass to the manager, we no longer own it
69801095a5dSDimitry Andric   // and shouldn't reference it.
69901095a5dSDimitry Andric   AnalysisID PassID = P->getPassID();
70001095a5dSDimitry Andric 
701d8e91e46SDimitry Andric   if (StartBefore == PassID && StartBeforeCount++ == StartBeforeInstanceNum)
70201095a5dSDimitry Andric     Started = true;
703d8e91e46SDimitry Andric   if (StopBefore == PassID && StopBeforeCount++ == StopBeforeInstanceNum)
704b915e9e0SDimitry Andric     Stopped = true;
70501095a5dSDimitry Andric   if (Started && !Stopped) {
706145449b1SDimitry Andric     if (AddingMachinePasses) {
70701095a5dSDimitry Andric       // Construct banner message before PM->add() as that may delete the pass.
708145449b1SDimitry Andric       std::string Banner =
709145449b1SDimitry Andric           std::string("After ") + std::string(P->getPassName());
710145449b1SDimitry Andric       addMachinePrePasses();
71101095a5dSDimitry Andric       PM->add(P);
712c0981da4SDimitry Andric       addMachinePostPasses(Banner);
713145449b1SDimitry Andric     } else {
714145449b1SDimitry Andric       PM->add(P);
715145449b1SDimitry Andric     }
71601095a5dSDimitry Andric 
71701095a5dSDimitry Andric     // Add the passes after the pass P if there is any.
718145449b1SDimitry Andric     for (const auto &IP : Impl->InsertedPasses)
71901095a5dSDimitry Andric       if (IP.TargetPassID == PassID)
720c0981da4SDimitry Andric         addPass(IP.getInsertedPass());
72101095a5dSDimitry Andric   } else {
72201095a5dSDimitry Andric     delete P;
72301095a5dSDimitry Andric   }
724d8e91e46SDimitry Andric 
725d8e91e46SDimitry Andric   if (StopAfter == PassID && StopAfterCount++ == StopAfterInstanceNum)
72601095a5dSDimitry Andric     Stopped = true;
727d8e91e46SDimitry Andric 
728d8e91e46SDimitry Andric   if (StartAfter == PassID && StartAfterCount++ == StartAfterInstanceNum)
72901095a5dSDimitry Andric     Started = true;
73001095a5dSDimitry Andric   if (Stopped && !Started)
73101095a5dSDimitry Andric     report_fatal_error("Cannot stop compilation after pass that is not run");
73201095a5dSDimitry Andric }
73301095a5dSDimitry Andric 
73401095a5dSDimitry Andric /// Add a CodeGen pass at this point in the pipeline after checking for target
73501095a5dSDimitry Andric /// and command line overrides.
73601095a5dSDimitry Andric ///
73701095a5dSDimitry Andric /// addPass cannot return a pointer to the pass instance because is internal the
73801095a5dSDimitry Andric /// PassManager and the instance we create here may already be freed.
addPass(AnalysisID PassID)739c0981da4SDimitry Andric AnalysisID TargetPassConfig::addPass(AnalysisID PassID) {
74001095a5dSDimitry Andric   IdentifyingPassPtr TargetID = getPassSubstitution(PassID);
74101095a5dSDimitry Andric   IdentifyingPassPtr FinalPtr = overridePass(PassID, TargetID);
74201095a5dSDimitry Andric   if (!FinalPtr.isValid())
74301095a5dSDimitry Andric     return nullptr;
74401095a5dSDimitry Andric 
74501095a5dSDimitry Andric   Pass *P;
74601095a5dSDimitry Andric   if (FinalPtr.isInstance())
74701095a5dSDimitry Andric     P = FinalPtr.getInstance();
74801095a5dSDimitry Andric   else {
74901095a5dSDimitry Andric     P = Pass::createPass(FinalPtr.getID());
75001095a5dSDimitry Andric     if (!P)
75101095a5dSDimitry Andric       llvm_unreachable("Pass ID not registered");
75201095a5dSDimitry Andric   }
75301095a5dSDimitry Andric   AnalysisID FinalID = P->getPassID();
754c0981da4SDimitry Andric   addPass(P); // Ends the lifetime of P.
75501095a5dSDimitry Andric 
75601095a5dSDimitry Andric   return FinalID;
75701095a5dSDimitry Andric }
75801095a5dSDimitry Andric 
printAndVerify(const std::string & Banner)75901095a5dSDimitry Andric void TargetPassConfig::printAndVerify(const std::string &Banner) {
76001095a5dSDimitry Andric   addPrintPass(Banner);
76101095a5dSDimitry Andric   addVerifyPass(Banner);
76201095a5dSDimitry Andric }
76301095a5dSDimitry Andric 
addPrintPass(const std::string & Banner)76401095a5dSDimitry Andric void TargetPassConfig::addPrintPass(const std::string &Banner) {
765b60736ecSDimitry Andric   if (PrintAfterISel)
76601095a5dSDimitry Andric     PM->add(createMachineFunctionPrinterPass(dbgs(), Banner));
76701095a5dSDimitry Andric }
76801095a5dSDimitry Andric 
addVerifyPass(const std::string & Banner)76901095a5dSDimitry Andric void TargetPassConfig::addVerifyPass(const std::string &Banner) {
770d8e91e46SDimitry Andric   bool Verify = VerifyMachineCode == cl::BOU_TRUE;
771f382538dSDimitry Andric #ifdef EXPENSIVE_CHECKS
772f382538dSDimitry Andric   if (VerifyMachineCode == cl::BOU_UNSET)
773f382538dSDimitry Andric     Verify = TM->isMachineVerifierClean();
774f382538dSDimitry Andric #endif
775f382538dSDimitry Andric   if (Verify)
77601095a5dSDimitry Andric     PM->add(createMachineVerifierPass(Banner));
77701095a5dSDimitry Andric }
77801095a5dSDimitry Andric 
addDebugifyPass()779cfca06d7SDimitry Andric void TargetPassConfig::addDebugifyPass() {
780cfca06d7SDimitry Andric   PM->add(createDebugifyMachineModulePass());
781cfca06d7SDimitry Andric }
782cfca06d7SDimitry Andric 
addStripDebugPass()783cfca06d7SDimitry Andric void TargetPassConfig::addStripDebugPass() {
784cfca06d7SDimitry Andric   PM->add(createStripDebugMachineModulePass(/*OnlyDebugified=*/true));
785cfca06d7SDimitry Andric }
786cfca06d7SDimitry Andric 
addCheckDebugPass()787b60736ecSDimitry Andric void TargetPassConfig::addCheckDebugPass() {
788b60736ecSDimitry Andric   PM->add(createCheckDebugMachineModulePass());
789b60736ecSDimitry Andric }
790b60736ecSDimitry Andric 
addMachinePrePasses(bool AllowDebugify)791cfca06d7SDimitry Andric void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) {
792b60736ecSDimitry Andric   if (AllowDebugify && DebugifyIsSafe &&
793b60736ecSDimitry Andric       (DebugifyAndStripAll == cl::BOU_TRUE ||
794b60736ecSDimitry Andric        DebugifyCheckAndStripAll == cl::BOU_TRUE))
795cfca06d7SDimitry Andric     addDebugifyPass();
796cfca06d7SDimitry Andric }
797cfca06d7SDimitry Andric 
addMachinePostPasses(const std::string & Banner)798c0981da4SDimitry Andric void TargetPassConfig::addMachinePostPasses(const std::string &Banner) {
799b60736ecSDimitry Andric   if (DebugifyIsSafe) {
800b60736ecSDimitry Andric     if (DebugifyCheckAndStripAll == cl::BOU_TRUE) {
801b60736ecSDimitry Andric       addCheckDebugPass();
802cfca06d7SDimitry Andric       addStripDebugPass();
803b60736ecSDimitry Andric     } else if (DebugifyAndStripAll == cl::BOU_TRUE)
804b60736ecSDimitry Andric       addStripDebugPass();
805b60736ecSDimitry Andric   }
806cfca06d7SDimitry Andric   addVerifyPass(Banner);
807cfca06d7SDimitry Andric }
808cfca06d7SDimitry Andric 
80901095a5dSDimitry Andric /// Add common target configurable passes that perform LLVM IR to IR transforms
81001095a5dSDimitry Andric /// following machine independent optimization.
addIRPasses()81101095a5dSDimitry Andric void TargetPassConfig::addIRPasses() {
812cfca06d7SDimitry Andric   // Before running any passes, run the verifier to determine if the input
813cfca06d7SDimitry Andric   // coming from the front-end and/or optimizer is valid.
814cfca06d7SDimitry Andric   if (!DisableVerify)
815cfca06d7SDimitry Andric     addPass(createVerifierPass());
816cfca06d7SDimitry Andric 
817b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None) {
81801095a5dSDimitry Andric     // Basic AliasAnalysis support.
81901095a5dSDimitry Andric     // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
82001095a5dSDimitry Andric     // BasicAliasAnalysis wins if they disagree. This is intended to help
82101095a5dSDimitry Andric     // support "obvious" type-punning idioms.
82201095a5dSDimitry Andric     addPass(createTypeBasedAAWrapperPass());
82301095a5dSDimitry Andric     addPass(createScopedNoAliasAAWrapperPass());
82401095a5dSDimitry Andric     addPass(createBasicAAWrapperPass());
82501095a5dSDimitry Andric 
82601095a5dSDimitry Andric     // Run loop strength reduction before anything else.
827cfca06d7SDimitry Andric     if (!DisableLSR) {
828cfca06d7SDimitry Andric       addPass(createCanonicalizeFreezeInLoopsPass());
82901095a5dSDimitry Andric       addPass(createLoopStrengthReducePass());
83001095a5dSDimitry Andric       if (PrintLSR)
831cfca06d7SDimitry Andric         addPass(createPrintFunctionPass(dbgs(),
832cfca06d7SDimitry Andric                                         "\n\n*** Code after LSR ***\n"));
83301095a5dSDimitry Andric     }
83401095a5dSDimitry Andric 
835044eb2f6SDimitry Andric     // The MergeICmpsPass tries to create memcmp calls by grouping sequences of
836044eb2f6SDimitry Andric     // loads and compares. ExpandMemCmpPass then tries to expand those calls
837044eb2f6SDimitry Andric     // into optimally-sized loads and compares. The transforms are enabled by a
838044eb2f6SDimitry Andric     // target lowering hook.
839eb11fae6SDimitry Andric     if (!DisableMergeICmps)
840e6d15924SDimitry Andric       addPass(createMergeICmpsLegacyPass());
841312c0ed1SDimitry Andric     addPass(createExpandMemCmpLegacyPass());
842044eb2f6SDimitry Andric   }
843044eb2f6SDimitry Andric 
84401095a5dSDimitry Andric   // Run GC lowering passes for builtin collectors
84501095a5dSDimitry Andric   // TODO: add a pass insertion point here
846344a3780SDimitry Andric   addPass(&GCLoweringID);
847344a3780SDimitry Andric   addPass(&ShadowStackGCLoweringID);
8481d5ae102SDimitry Andric   addPass(createLowerConstantIntrinsicsPass());
84901095a5dSDimitry Andric 
850e3b55780SDimitry Andric   // For MachO, lower @llvm.global_dtors into @llvm.global_ctors with
851145449b1SDimitry Andric   // __cxa_atexit() calls to avoid emitting the deprecated __mod_term_func.
852145449b1SDimitry Andric   if (TM->getTargetTriple().isOSBinFormatMachO() &&
8537fa27ce4SDimitry Andric       !DisableAtExitBasedGlobalDtorLowering)
854145449b1SDimitry Andric     addPass(createLowerGlobalDtorsLegacyPass());
855145449b1SDimitry Andric 
85601095a5dSDimitry Andric   // Make sure that no unreachable blocks are instruction selected.
85701095a5dSDimitry Andric   addPass(createUnreachableBlockEliminationPass());
85801095a5dSDimitry Andric 
85901095a5dSDimitry Andric   // Prepare expensive constants for SelectionDAG.
860b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None && !DisableConstantHoisting)
86101095a5dSDimitry Andric     addPass(createConstantHoistingPass());
86201095a5dSDimitry Andric 
863ac9a064cSDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None && !DisableReplaceWithVecLib)
864344a3780SDimitry Andric     addPass(createReplaceWithVeclibLegacyPass());
865344a3780SDimitry Andric 
866b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None && !DisablePartialLibcallInlining)
86701095a5dSDimitry Andric     addPass(createPartiallyInlineLibCallsPass());
868b915e9e0SDimitry Andric 
869344a3780SDimitry Andric   // Expand vector predication intrinsics into standard IR instructions.
870344a3780SDimitry Andric   // This pass has to run before ScalarizeMaskedMemIntrin and ExpandReduction
871344a3780SDimitry Andric   // passes since it emits those kinds of intrinsics.
872344a3780SDimitry Andric   addPass(createExpandVectorPredicationPass());
8736b3f41edSDimitry Andric 
874ac9a064cSDimitry Andric   // Instrument function entry after all inlining.
875ac9a064cSDimitry Andric   addPass(createPostInlineEntryExitInstrumenterPass());
876ac9a064cSDimitry Andric 
8776b3f41edSDimitry Andric   // Add scalarization of target's unsupported masked memory intrinsics pass.
8786b3f41edSDimitry Andric   // the unsupported intrinsic will be replaced with a chain of basic blocks,
8796b3f41edSDimitry Andric   // that stores/loads element one-by-one if the appropriate mask bit is set.
880b60736ecSDimitry Andric   addPass(createScalarizeMaskedMemIntrinLegacyPass());
8816b3f41edSDimitry Andric 
8826b3f41edSDimitry Andric   // Expand reduction intrinsics into shuffle sequences if the target wants to.
883b60736ecSDimitry Andric   // Allow disabling it for testing purposes.
884b60736ecSDimitry Andric   if (!DisableExpandReductions)
8856b3f41edSDimitry Andric     addPass(createExpandReductionsPass());
886145449b1SDimitry Andric 
887b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None)
888145449b1SDimitry Andric     addPass(createTLSVariableHoistPass());
889145449b1SDimitry Andric 
890145449b1SDimitry Andric   // Convert conditional moves to conditional jumps when profitable.
891b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None && !DisableSelectOptimize)
892145449b1SDimitry Andric     addPass(createSelectOptimizePass());
89301095a5dSDimitry Andric }
89401095a5dSDimitry Andric 
89501095a5dSDimitry Andric /// Turn exception handling constructs into something the code generators can
89601095a5dSDimitry Andric /// handle.
addPassesToHandleExceptions()89701095a5dSDimitry Andric void TargetPassConfig::addPassesToHandleExceptions() {
898b915e9e0SDimitry Andric   const MCAsmInfo *MCAI = TM->getMCAsmInfo();
899b915e9e0SDimitry Andric   assert(MCAI && "No MCAsmInfo");
900b915e9e0SDimitry Andric   switch (MCAI->getExceptionHandlingType()) {
90101095a5dSDimitry Andric   case ExceptionHandling::SjLj:
90201095a5dSDimitry Andric     // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
90301095a5dSDimitry Andric     // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
90401095a5dSDimitry Andric     // catch info can get misplaced when a selector ends up more than one block
90501095a5dSDimitry Andric     // removed from the parent invoke(s). This could happen when a landing
90601095a5dSDimitry Andric     // pad is shared by multiple invokes and is also a target of a normal
90701095a5dSDimitry Andric     // edge from elsewhere.
908cfca06d7SDimitry Andric     addPass(createSjLjEHPreparePass(TM));
909e3b55780SDimitry Andric     [[fallthrough]];
91001095a5dSDimitry Andric   case ExceptionHandling::DwarfCFI:
91101095a5dSDimitry Andric   case ExceptionHandling::ARM:
912b60736ecSDimitry Andric   case ExceptionHandling::AIX:
91399aabd70SDimitry Andric   case ExceptionHandling::ZOS:
914cfca06d7SDimitry Andric     addPass(createDwarfEHPass(getOptLevel()));
91501095a5dSDimitry Andric     break;
91601095a5dSDimitry Andric   case ExceptionHandling::WinEH:
91701095a5dSDimitry Andric     // We support using both GCC-style and MSVC-style exceptions on Windows, so
91801095a5dSDimitry Andric     // add both preparation passes. Each pass will only actually run if it
91901095a5dSDimitry Andric     // recognizes the personality function.
920b5630dbaSDimitry Andric     addPass(createWinEHPass());
921cfca06d7SDimitry Andric     addPass(createDwarfEHPass(getOptLevel()));
92201095a5dSDimitry Andric     break;
923eb11fae6SDimitry Andric   case ExceptionHandling::Wasm:
924eb11fae6SDimitry Andric     // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
925eb11fae6SDimitry Andric     // on catchpads and cleanuppads because it does not outline them into
926eb11fae6SDimitry Andric     // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
927eb11fae6SDimitry Andric     // should remove PHIs there.
928ac9a064cSDimitry Andric     addPass(createWinEHPass(/*DemoteCatchSwitchPHIOnly=*/true));
929eb11fae6SDimitry Andric     addPass(createWasmEHPass());
930eb11fae6SDimitry Andric     break;
93101095a5dSDimitry Andric   case ExceptionHandling::None:
93201095a5dSDimitry Andric     addPass(createLowerInvokePass());
93301095a5dSDimitry Andric 
93401095a5dSDimitry Andric     // The lower invoke pass may create unreachable code. Remove it.
93501095a5dSDimitry Andric     addPass(createUnreachableBlockEliminationPass());
93601095a5dSDimitry Andric     break;
93701095a5dSDimitry Andric   }
93801095a5dSDimitry Andric }
93901095a5dSDimitry Andric 
94001095a5dSDimitry Andric /// Add pass to prepare the LLVM IR for code generation. This should be done
94101095a5dSDimitry Andric /// before exception handling preparation passes.
addCodeGenPrepare()94201095a5dSDimitry Andric void TargetPassConfig::addCodeGenPrepare() {
943b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None && !DisableCGP)
944aca2e42cSDimitry Andric     addPass(createCodeGenPrepareLegacyPass());
94501095a5dSDimitry Andric }
94601095a5dSDimitry Andric 
94701095a5dSDimitry Andric /// Add common passes that perform LLVM IR to IR transforms in preparation for
94801095a5dSDimitry Andric /// instruction selection.
addISelPrepare()94901095a5dSDimitry Andric void TargetPassConfig::addISelPrepare() {
95001095a5dSDimitry Andric   addPreISel();
95101095a5dSDimitry Andric 
95201095a5dSDimitry Andric   // Force codegen to run according to the callgraph.
95371d5a254SDimitry Andric   if (requiresCodeGenSCCOrder())
95401095a5dSDimitry Andric     addPass(new DummyCGSCCPass);
95501095a5dSDimitry Andric 
9567fa27ce4SDimitry Andric   addPass(createCallBrPass());
9577fa27ce4SDimitry Andric 
95801095a5dSDimitry Andric   // Add both the safe stack and the stack protection passes: each of them will
95901095a5dSDimitry Andric   // only protect functions that have corresponding attributes.
960b5630dbaSDimitry Andric   addPass(createSafeStackPass());
961b5630dbaSDimitry Andric   addPass(createStackProtectorPass());
96201095a5dSDimitry Andric 
96301095a5dSDimitry Andric   if (PrintISelInput)
96401095a5dSDimitry Andric     addPass(createPrintFunctionPass(
96501095a5dSDimitry Andric         dbgs(), "\n\n*** Final LLVM Code input to ISel ***\n"));
96601095a5dSDimitry Andric 
96701095a5dSDimitry Andric   // All passes which modify the LLVM IR are now complete; run the verifier
96801095a5dSDimitry Andric   // to ensure that the IR is valid.
96901095a5dSDimitry Andric   if (!DisableVerify)
97001095a5dSDimitry Andric     addPass(createVerifierPass());
97101095a5dSDimitry Andric }
97201095a5dSDimitry Andric 
addCoreISelPasses()9737ab83427SDimitry Andric bool TargetPassConfig::addCoreISelPasses() {
974eb11fae6SDimitry Andric   // Enable FastISel with -fast-isel, but allow that to be overridden.
9757ab83427SDimitry Andric   TM->setO0WantsFastISel(EnableFastISelOption != cl::BOU_FALSE);
976d8e91e46SDimitry Andric 
977d8e91e46SDimitry Andric   // Determine an instruction selector.
978d8e91e46SDimitry Andric   enum class SelectorType { SelectionDAG, FastISel, GlobalISel };
979d8e91e46SDimitry Andric   SelectorType Selector;
980d8e91e46SDimitry Andric 
981d8e91e46SDimitry Andric   if (EnableFastISelOption == cl::BOU_TRUE)
982d8e91e46SDimitry Andric     Selector = SelectorType::FastISel;
983d8e91e46SDimitry Andric   else if (EnableGlobalISelOption == cl::BOU_TRUE ||
984d8e91e46SDimitry Andric            (TM->Options.EnableGlobalISel &&
985d8e91e46SDimitry Andric             EnableGlobalISelOption != cl::BOU_FALSE))
986d8e91e46SDimitry Andric     Selector = SelectorType::GlobalISel;
987b1c73532SDimitry Andric   else if (TM->getOptLevel() == CodeGenOptLevel::None &&
988b1c73532SDimitry Andric            TM->getO0WantsFastISel())
989d8e91e46SDimitry Andric     Selector = SelectorType::FastISel;
990d8e91e46SDimitry Andric   else
991d8e91e46SDimitry Andric     Selector = SelectorType::SelectionDAG;
992d8e91e46SDimitry Andric 
993d8e91e46SDimitry Andric   // Set consistently TM->Options.EnableFastISel and EnableGlobalISel.
994d8e91e46SDimitry Andric   if (Selector == SelectorType::FastISel) {
9957ab83427SDimitry Andric     TM->setFastISel(true);
996d8e91e46SDimitry Andric     TM->setGlobalISel(false);
997d8e91e46SDimitry Andric   } else if (Selector == SelectorType::GlobalISel) {
998eb11fae6SDimitry Andric     TM->setFastISel(false);
999d8e91e46SDimitry Andric     TM->setGlobalISel(true);
1000d8e91e46SDimitry Andric   }
1001eb11fae6SDimitry Andric 
1002cfca06d7SDimitry Andric   // FIXME: Injecting into the DAGISel pipeline seems to cause issues with
1003cfca06d7SDimitry Andric   //        analyses needing to be re-run. This can result in being unable to
1004cfca06d7SDimitry Andric   //        schedule passes (particularly with 'Function Alias Analysis
1005cfca06d7SDimitry Andric   //        Results'). It's not entirely clear why but AFAICT this seems to be
1006cfca06d7SDimitry Andric   //        due to one FunctionPassManager not being able to use analyses from a
1007cfca06d7SDimitry Andric   //        previous one. As we're injecting a ModulePass we break the usual
1008cfca06d7SDimitry Andric   //        pass manager into two. GlobalISel with the fallback path disabled
1009cfca06d7SDimitry Andric   //        and -run-pass seem to be unaffected. The majority of GlobalISel
1010cfca06d7SDimitry Andric   //        testing uses -run-pass so this probably isn't too bad.
1011e3b55780SDimitry Andric   SaveAndRestore SavedDebugifyIsSafe(DebugifyIsSafe);
1012cfca06d7SDimitry Andric   if (Selector != SelectorType::GlobalISel || !isGlobalISelAbortEnabled())
1013cfca06d7SDimitry Andric     DebugifyIsSafe = false;
1014cfca06d7SDimitry Andric 
1015d8e91e46SDimitry Andric   // Add instruction selector passes.
1016d8e91e46SDimitry Andric   if (Selector == SelectorType::GlobalISel) {
1017e3b55780SDimitry Andric     SaveAndRestore SavedAddingMachinePasses(AddingMachinePasses, true);
10187ab83427SDimitry Andric     if (addIRTranslator())
10197ab83427SDimitry Andric       return true;
10207ab83427SDimitry Andric 
10217ab83427SDimitry Andric     addPreLegalizeMachineIR();
10227ab83427SDimitry Andric 
10237ab83427SDimitry Andric     if (addLegalizeMachineIR())
10247ab83427SDimitry Andric       return true;
10257ab83427SDimitry Andric 
10267ab83427SDimitry Andric     // Before running the register bank selector, ask the target if it
10277ab83427SDimitry Andric     // wants to run some passes.
10287ab83427SDimitry Andric     addPreRegBankSelect();
10297ab83427SDimitry Andric 
10307ab83427SDimitry Andric     if (addRegBankSelect())
10317ab83427SDimitry Andric       return true;
10327ab83427SDimitry Andric 
10337ab83427SDimitry Andric     addPreGlobalInstructionSelect();
10347ab83427SDimitry Andric 
10357ab83427SDimitry Andric     if (addGlobalInstructionSelect())
10367ab83427SDimitry Andric       return true;
10377ab83427SDimitry Andric 
10387ab83427SDimitry Andric     // Pass to reset the MachineFunction if the ISel failed.
10397ab83427SDimitry Andric     addPass(createResetMachineFunctionPass(
10407ab83427SDimitry Andric         reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled()));
10417ab83427SDimitry Andric 
10427ab83427SDimitry Andric     // Provide a fallback path when we do not want to abort on
10437ab83427SDimitry Andric     // not-yet-supported input.
10447ab83427SDimitry Andric     if (!isGlobalISelAbortEnabled() && addInstSelector())
10457ab83427SDimitry Andric       return true;
10467ab83427SDimitry Andric 
10477ab83427SDimitry Andric   } else if (addInstSelector())
10487ab83427SDimitry Andric     return true;
10497ab83427SDimitry Andric 
1050e6d15924SDimitry Andric   // Expand pseudo-instructions emitted by ISel. Don't run the verifier before
1051e6d15924SDimitry Andric   // FinalizeISel.
1052e6d15924SDimitry Andric   addPass(&FinalizeISelID);
1053e6d15924SDimitry Andric 
1054e6d15924SDimitry Andric   // Print the instruction selected machine code...
1055e6d15924SDimitry Andric   printAndVerify("After Instruction Selection");
1056e6d15924SDimitry Andric 
10577ab83427SDimitry Andric   return false;
10587ab83427SDimitry Andric }
10597ab83427SDimitry Andric 
addISelPasses()10607ab83427SDimitry Andric bool TargetPassConfig::addISelPasses() {
1061eb11fae6SDimitry Andric   if (TM->useEmulatedTLS())
10627ab83427SDimitry Andric     addPass(createLowerEmuTLSPass());
10637ab83427SDimitry Andric 
1064b60736ecSDimitry Andric   PM->add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
10657fa27ce4SDimitry Andric   addPass(createPreISelIntrinsicLoweringPass());
1066e3b55780SDimitry Andric   addPass(createExpandLargeDivRemPass());
1067e3b55780SDimitry Andric   addPass(createExpandLargeFpConvertPass());
10687ab83427SDimitry Andric   addIRPasses();
10697ab83427SDimitry Andric   addCodeGenPrepare();
10707ab83427SDimitry Andric   addPassesToHandleExceptions();
10717ab83427SDimitry Andric   addISelPrepare();
10727ab83427SDimitry Andric 
10737ab83427SDimitry Andric   return addCoreISelPasses();
10747ab83427SDimitry Andric }
10757ab83427SDimitry Andric 
10767af96fb3SDimitry Andric /// -regalloc=... command line option.
useDefaultRegisterAllocator()10777af96fb3SDimitry Andric static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
10787af96fb3SDimitry Andric static cl::opt<RegisterRegAlloc::FunctionPassCtor, false,
10797af96fb3SDimitry Andric                RegisterPassParser<RegisterRegAlloc>>
1080044eb2f6SDimitry Andric     RegAlloc("regalloc", cl::Hidden, cl::init(&useDefaultRegisterAllocator),
10817af96fb3SDimitry Andric              cl::desc("Register allocator to use"));
10827af96fb3SDimitry Andric 
108301095a5dSDimitry Andric /// Add the complete set of target-independent postISel code generator passes.
108401095a5dSDimitry Andric ///
108501095a5dSDimitry Andric /// This can be read as the standard order of major LLVM CodeGen stages. Stages
108601095a5dSDimitry Andric /// with nontrivial configuration or multiple passes are broken out below in
108701095a5dSDimitry Andric /// add%Stage routines.
108801095a5dSDimitry Andric ///
108901095a5dSDimitry Andric /// Any TargetPassConfig::addXX routine may be overriden by the Target. The
109001095a5dSDimitry Andric /// addPre/Post methods with empty header implementations allow injecting
109101095a5dSDimitry Andric /// target-specific fixups just before or after major stages. Additionally,
109201095a5dSDimitry Andric /// targets have the flexibility to change pass order within a stage by
109301095a5dSDimitry Andric /// overriding default implementation of add%Stage routines below. Each
109401095a5dSDimitry Andric /// technique has maintainability tradeoffs because alternate pass orders are
109501095a5dSDimitry Andric /// not well supported. addPre/Post works better if the target pass is easily
109601095a5dSDimitry Andric /// tied to a common pass. But if it has subtle dependencies on multiple passes,
109701095a5dSDimitry Andric /// the target should override the stage instead.
109801095a5dSDimitry Andric ///
109901095a5dSDimitry Andric /// TODO: We could use a single addPre/Post(ID) hook to allow pass injection
110001095a5dSDimitry Andric /// before/after any target-independent pass. But it's currently overkill.
addMachinePasses()110101095a5dSDimitry Andric void TargetPassConfig::addMachinePasses() {
110201095a5dSDimitry Andric   AddingMachinePasses = true;
110301095a5dSDimitry Andric 
110401095a5dSDimitry Andric   // Add passes that optimize machine instructions in SSA form.
1105b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None) {
110601095a5dSDimitry Andric     addMachineSSAOptimization();
110701095a5dSDimitry Andric   } else {
110801095a5dSDimitry Andric     // If the target requests it, assign local variables to stack slots relative
110901095a5dSDimitry Andric     // to one another and simplify frame index references where possible.
1110cfca06d7SDimitry Andric     addPass(&LocalStackSlotAllocationID);
111101095a5dSDimitry Andric   }
111201095a5dSDimitry Andric 
1113044eb2f6SDimitry Andric   if (TM->Options.EnableIPRA)
1114044eb2f6SDimitry Andric     addPass(createRegUsageInfoPropPass());
1115044eb2f6SDimitry Andric 
111601095a5dSDimitry Andric   // Run pre-ra passes.
111701095a5dSDimitry Andric   addPreRegAlloc();
111801095a5dSDimitry Andric 
1119cfca06d7SDimitry Andric   // Debugifying the register allocator passes seems to provoke some
1120cfca06d7SDimitry Andric   // non-determinism that affects CodeGen and there doesn't seem to be a point
1121cfca06d7SDimitry Andric   // where it becomes safe again so stop debugifying here.
1122cfca06d7SDimitry Andric   DebugifyIsSafe = false;
1123cfca06d7SDimitry Andric 
1124c0981da4SDimitry Andric   // Add a FSDiscriminator pass right before RA, so that we could get
1125c0981da4SDimitry Andric   // more precise SampleFDO profile for RA.
1126c0981da4SDimitry Andric   if (EnableFSDiscriminator) {
1127c0981da4SDimitry Andric     addPass(createMIRAddFSDiscriminatorsPass(
1128c0981da4SDimitry Andric         sampleprof::FSDiscriminatorPass::Pass1));
1129c0981da4SDimitry Andric     const std::string ProfileFile = getFSProfileFile(TM);
1130c0981da4SDimitry Andric     if (!ProfileFile.empty() && !DisableRAFSProfileLoader)
11317fa27ce4SDimitry Andric       addPass(createMIRProfileLoaderPass(ProfileFile, getFSRemappingFile(TM),
11327fa27ce4SDimitry Andric                                          sampleprof::FSDiscriminatorPass::Pass1,
11337fa27ce4SDimitry Andric                                          nullptr));
1134c0981da4SDimitry Andric   }
1135c0981da4SDimitry Andric 
113601095a5dSDimitry Andric   // Run register allocation and passes that are tightly coupled with it,
113701095a5dSDimitry Andric   // including phi elimination and scheduling.
113801095a5dSDimitry Andric   if (getOptimizeRegAlloc())
1139e6d15924SDimitry Andric     addOptimizedRegAlloc();
1140e6d15924SDimitry Andric   else
1141e6d15924SDimitry Andric     addFastRegAlloc();
114201095a5dSDimitry Andric 
114301095a5dSDimitry Andric   // Run post-ra passes.
114401095a5dSDimitry Andric   addPostRegAlloc();
114501095a5dSDimitry Andric 
1146c0981da4SDimitry Andric   addPass(&RemoveRedundantDebugValuesID);
1147344a3780SDimitry Andric 
1148cfca06d7SDimitry Andric   addPass(&FixupStatepointCallerSavedID);
1149cfca06d7SDimitry Andric 
115001095a5dSDimitry Andric   // Insert prolog/epilog code.  Eliminate abstract frame index references...
1151b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None) {
1152eb11fae6SDimitry Andric     addPass(&PostRAMachineSinkingID);
115301095a5dSDimitry Andric     addPass(&ShrinkWrapID);
1154eb11fae6SDimitry Andric   }
115501095a5dSDimitry Andric 
115601095a5dSDimitry Andric   // Prolog/Epilog inserter needs a TargetMachine to instantiate. But only
115701095a5dSDimitry Andric   // do so if it hasn't been disabled, substituted, or overridden.
115801095a5dSDimitry Andric   if (!isPassSubstitutedOrOverridden(&PrologEpilogCodeInserterID))
1159b5630dbaSDimitry Andric       addPass(createPrologEpilogInserterPass());
116001095a5dSDimitry Andric 
116101095a5dSDimitry Andric   /// Add passes that optimize machine instructions after register allocation.
1162b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None)
116301095a5dSDimitry Andric       addMachineLateOptimization();
116401095a5dSDimitry Andric 
116501095a5dSDimitry Andric   // Expand pseudo instructions before second scheduling pass.
116601095a5dSDimitry Andric   addPass(&ExpandPostRAPseudosID);
116701095a5dSDimitry Andric 
116801095a5dSDimitry Andric   // Run pre-sched2 passes.
116901095a5dSDimitry Andric   addPreSched2();
117001095a5dSDimitry Andric 
117101095a5dSDimitry Andric   if (EnableImplicitNullChecks)
117201095a5dSDimitry Andric     addPass(&ImplicitNullChecksID);
117301095a5dSDimitry Andric 
117401095a5dSDimitry Andric   // Second pass scheduler.
117501095a5dSDimitry Andric   // Let Target optionally insert this pass by itself at some other
117601095a5dSDimitry Andric   // point.
1177b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None &&
117801095a5dSDimitry Andric       !TM->targetSchedulesPostRAScheduling()) {
117901095a5dSDimitry Andric     if (MISchedPostRA)
118001095a5dSDimitry Andric       addPass(&PostMachineSchedulerID);
118101095a5dSDimitry Andric     else
118201095a5dSDimitry Andric       addPass(&PostRASchedulerID);
118301095a5dSDimitry Andric   }
118401095a5dSDimitry Andric 
118501095a5dSDimitry Andric   // GC
1186312c0ed1SDimitry Andric   addGCPasses();
118701095a5dSDimitry Andric 
118801095a5dSDimitry Andric   // Basic block placement.
1189b1c73532SDimitry Andric   if (getOptLevel() != CodeGenOptLevel::None)
119001095a5dSDimitry Andric     addBlockPlacement();
119101095a5dSDimitry Andric 
1192cfca06d7SDimitry Andric   // Insert before XRay Instrumentation.
1193cfca06d7SDimitry Andric   addPass(&FEntryInserterID);
1194cfca06d7SDimitry Andric 
1195cfca06d7SDimitry Andric   addPass(&XRayInstrumentationID);
1196cfca06d7SDimitry Andric   addPass(&PatchableFunctionID);
1197cfca06d7SDimitry Andric 
119801095a5dSDimitry Andric   addPreEmitPass();
119901095a5dSDimitry Andric 
120001095a5dSDimitry Andric   if (TM->Options.EnableIPRA)
120101095a5dSDimitry Andric     // Collect register usage information and produce a register mask of
120201095a5dSDimitry Andric     // clobbered registers, to be used to optimize call sites.
120301095a5dSDimitry Andric     addPass(createRegUsageInfoCollector());
120401095a5dSDimitry Andric 
1205cfca06d7SDimitry Andric   // FIXME: Some backends are incompatible with running the verifier after
1206cfca06d7SDimitry Andric   // addPreEmitPass.  Maybe only pass "false" here for those targets?
1207c0981da4SDimitry Andric   addPass(&FuncletLayoutID);
120801095a5dSDimitry Andric 
1209c0981da4SDimitry Andric   addPass(&StackMapLivenessID);
1210c0981da4SDimitry Andric   addPass(&LiveDebugValuesID);
1211e3b55780SDimitry Andric   addPass(&MachineSanitizerBinaryMetadataID);
121201095a5dSDimitry Andric 
1213b1c73532SDimitry Andric   if (TM->Options.EnableMachineOutliner &&
1214b1c73532SDimitry Andric       getOptLevel() != CodeGenOptLevel::None &&
1215b60736ecSDimitry Andric       EnableMachineOutliner != RunOutliner::NeverOutline) {
1216b60736ecSDimitry Andric     bool RunOnAllFunctions =
1217b60736ecSDimitry Andric         (EnableMachineOutliner == RunOutliner::AlwaysOutline);
1218b60736ecSDimitry Andric     bool AddOutliner =
1219b60736ecSDimitry Andric         RunOnAllFunctions || TM->Options.SupportsDefaultOutlining;
1220eb11fae6SDimitry Andric     if (AddOutliner)
1221eb11fae6SDimitry Andric       addPass(createMachineOutlinerPass(RunOnAllFunctions));
1222eb11fae6SDimitry Andric   }
1223eb11fae6SDimitry Andric 
1224b1c73532SDimitry Andric   if (GCEmptyBlocks)
1225b1c73532SDimitry Andric     addPass(llvm::createGCEmptyBasicBlocksPass());
1226b1c73532SDimitry Andric 
12277fa27ce4SDimitry Andric   if (EnableFSDiscriminator)
12287fa27ce4SDimitry Andric     addPass(createMIRAddFSDiscriminatorsPass(
12297fa27ce4SDimitry Andric         sampleprof::FSDiscriminatorPass::PassLast));
12307fa27ce4SDimitry Andric 
1231ac9a064cSDimitry Andric   bool NeedsBBSections =
1232ac9a064cSDimitry Andric       TM->getBBSectionsType() != llvm::BasicBlockSection::None;
1233b60736ecSDimitry Andric   // Machine function splitter uses the basic block sections feature. Both
1234ac9a064cSDimitry Andric   // cannot be enabled at the same time. We do not apply machine function
1235ac9a064cSDimitry Andric   // splitter if -basic-block-sections is requested.
1236ac9a064cSDimitry Andric   if (!NeedsBBSections && (TM->Options.EnableMachineFunctionSplitter ||
1237ac9a064cSDimitry Andric                            EnableMachineFunctionSplitter)) {
12387fa27ce4SDimitry Andric     const std::string ProfileFile = getFSProfileFile(TM);
12397fa27ce4SDimitry Andric     if (!ProfileFile.empty()) {
12407fa27ce4SDimitry Andric       if (EnableFSDiscriminator) {
12417fa27ce4SDimitry Andric         addPass(createMIRProfileLoaderPass(
12427fa27ce4SDimitry Andric             ProfileFile, getFSRemappingFile(TM),
12437fa27ce4SDimitry Andric             sampleprof::FSDiscriminatorPass::PassLast, nullptr));
12447fa27ce4SDimitry Andric       } else {
12457fa27ce4SDimitry Andric         // Sample profile is given, but FSDiscriminator is not
12467fa27ce4SDimitry Andric         // enabled, this may result in performance regression.
12477fa27ce4SDimitry Andric         WithColor::warning()
12487fa27ce4SDimitry Andric             << "Using AutoFDO without FSDiscriminator for MFS may regress "
12494df029ccSDimitry Andric                "performance.\n";
12507fa27ce4SDimitry Andric       }
12517fa27ce4SDimitry Andric     }
1252b60736ecSDimitry Andric     addPass(createMachineFunctionSplitterPass());
1253b60736ecSDimitry Andric   }
1254ac9a064cSDimitry Andric   // We run the BasicBlockSections pass if either we need BB sections or BB
1255ac9a064cSDimitry Andric   // address map (or both).
1256ac9a064cSDimitry Andric   if (NeedsBBSections || TM->Options.BBAddrMap) {
1257ac9a064cSDimitry Andric     if (TM->getBBSectionsType() == llvm::BasicBlockSection::List) {
1258ac9a064cSDimitry Andric       addPass(llvm::createBasicBlockSectionsProfileReaderWrapperPass(
1259ac9a064cSDimitry Andric           TM->getBBSectionsFuncListBuf()));
1260ac9a064cSDimitry Andric       addPass(llvm::createBasicBlockPathCloningPass());
1261ac9a064cSDimitry Andric     }
1262ac9a064cSDimitry Andric     addPass(llvm::createBasicBlockSectionsPass());
1263ac9a064cSDimitry Andric   }
1264cfca06d7SDimitry Andric 
12657fa27ce4SDimitry Andric   addPostBBSections();
12667fa27ce4SDimitry Andric 
1267145449b1SDimitry Andric   if (!DisableCFIFixup && TM->Options.EnableCFIFixup)
1268145449b1SDimitry Andric     addPass(createCFIFixup());
1269145449b1SDimitry Andric 
1270e3b55780SDimitry Andric   PM->add(createStackFrameLayoutAnalysisPass());
1271e3b55780SDimitry Andric 
1272eb11fae6SDimitry Andric   // Add passes that directly emit MI after all other MI passes.
1273eb11fae6SDimitry Andric   addPreEmitPass2();
127471d5a254SDimitry Andric 
127501095a5dSDimitry Andric   AddingMachinePasses = false;
127601095a5dSDimitry Andric }
127701095a5dSDimitry Andric 
127801095a5dSDimitry Andric /// Add passes that optimize machine instructions in SSA form.
addMachineSSAOptimization()127901095a5dSDimitry Andric void TargetPassConfig::addMachineSSAOptimization() {
128001095a5dSDimitry Andric   // Pre-ra tail duplication.
128101095a5dSDimitry Andric   addPass(&EarlyTailDuplicateID);
128201095a5dSDimitry Andric 
128301095a5dSDimitry Andric   // Optimize PHIs before DCE: removing dead PHI cycles may make more
128401095a5dSDimitry Andric   // instructions dead.
1285cfca06d7SDimitry Andric   addPass(&OptimizePHIsID);
128601095a5dSDimitry Andric 
128701095a5dSDimitry Andric   // This pass merges large allocas. StackSlotColoring is a different pass
128801095a5dSDimitry Andric   // which merges spill slots.
1289cfca06d7SDimitry Andric   addPass(&StackColoringID);
129001095a5dSDimitry Andric 
129101095a5dSDimitry Andric   // If the target requests it, assign local variables to stack slots relative
129201095a5dSDimitry Andric   // to one another and simplify frame index references where possible.
1293cfca06d7SDimitry Andric   addPass(&LocalStackSlotAllocationID);
129401095a5dSDimitry Andric 
129501095a5dSDimitry Andric   // With optimization, dead code should already be eliminated. However
129601095a5dSDimitry Andric   // there is one known exception: lowered code for arguments that are only
129701095a5dSDimitry Andric   // used by tail calls, where the tail calls reuse the incoming stack
129801095a5dSDimitry Andric   // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
129901095a5dSDimitry Andric   addPass(&DeadMachineInstructionElimID);
130001095a5dSDimitry Andric 
130101095a5dSDimitry Andric   // Allow targets to insert passes that improve instruction level parallelism,
130201095a5dSDimitry Andric   // like if-conversion. Such passes will typically need dominator trees and
130301095a5dSDimitry Andric   // loop info, just like LICM and CSE below.
130401095a5dSDimitry Andric   addILPOpts();
130501095a5dSDimitry Andric 
1306cfca06d7SDimitry Andric   addPass(&EarlyMachineLICMID);
1307cfca06d7SDimitry Andric   addPass(&MachineCSEID);
130871d5a254SDimitry Andric 
130901095a5dSDimitry Andric   addPass(&MachineSinkingID);
131001095a5dSDimitry Andric 
131101095a5dSDimitry Andric   addPass(&PeepholeOptimizerID);
131201095a5dSDimitry Andric   // Clean-up the dead code that may have been generated by peephole
131301095a5dSDimitry Andric   // rewriting.
131401095a5dSDimitry Andric   addPass(&DeadMachineInstructionElimID);
131501095a5dSDimitry Andric }
131601095a5dSDimitry Andric 
131701095a5dSDimitry Andric //===---------------------------------------------------------------------===//
131801095a5dSDimitry Andric /// Register Allocation Pass Configuration
131901095a5dSDimitry Andric //===---------------------------------------------------------------------===//
132001095a5dSDimitry Andric 
getOptimizeRegAlloc() const132101095a5dSDimitry Andric bool TargetPassConfig::getOptimizeRegAlloc() const {
132201095a5dSDimitry Andric   switch (OptimizeRegAlloc) {
1323b1c73532SDimitry Andric   case cl::BOU_UNSET:
1324b1c73532SDimitry Andric     return getOptLevel() != CodeGenOptLevel::None;
132501095a5dSDimitry Andric   case cl::BOU_TRUE:  return true;
132601095a5dSDimitry Andric   case cl::BOU_FALSE: return false;
132701095a5dSDimitry Andric   }
132801095a5dSDimitry Andric   llvm_unreachable("Invalid optimize-regalloc state");
132901095a5dSDimitry Andric }
133001095a5dSDimitry Andric 
133101095a5dSDimitry Andric /// A dummy default pass factory indicates whether the register allocator is
133201095a5dSDimitry Andric /// overridden on the command line.
133371d5a254SDimitry Andric static llvm::once_flag InitializeDefaultRegisterAllocatorFlag;
13347af96fb3SDimitry Andric 
133501095a5dSDimitry Andric static RegisterRegAlloc
133601095a5dSDimitry Andric defaultRegAlloc("default",
133701095a5dSDimitry Andric                 "pick register allocator based on -O option",
133801095a5dSDimitry Andric                 useDefaultRegisterAllocator);
133901095a5dSDimitry Andric 
initializeDefaultRegisterAllocatorOnce()134001095a5dSDimitry Andric static void initializeDefaultRegisterAllocatorOnce() {
1341e6d15924SDimitry Andric   if (!RegisterRegAlloc::getDefault())
134201095a5dSDimitry Andric     RegisterRegAlloc::setDefault(RegAlloc);
134301095a5dSDimitry Andric }
134401095a5dSDimitry Andric 
134501095a5dSDimitry Andric /// Instantiate the default register allocator pass for this target for either
134601095a5dSDimitry Andric /// the optimized or unoptimized allocation path. This will be added to the pass
134701095a5dSDimitry Andric /// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc
134801095a5dSDimitry Andric /// in the optimized case.
134901095a5dSDimitry Andric ///
135001095a5dSDimitry Andric /// A target that uses the standard regalloc pass order for fast or optimized
135101095a5dSDimitry Andric /// allocation may still override this for per-target regalloc
135201095a5dSDimitry Andric /// selection. But -regalloc=... always takes precedence.
createTargetRegisterAllocator(bool Optimized)135301095a5dSDimitry Andric FunctionPass *TargetPassConfig::createTargetRegisterAllocator(bool Optimized) {
135401095a5dSDimitry Andric   if (Optimized)
135501095a5dSDimitry Andric     return createGreedyRegisterAllocator();
135601095a5dSDimitry Andric   else
135701095a5dSDimitry Andric     return createFastRegisterAllocator();
135801095a5dSDimitry Andric }
135901095a5dSDimitry Andric 
136001095a5dSDimitry Andric /// Find and instantiate the register allocation pass requested by this target
136101095a5dSDimitry Andric /// at the current optimization level.  Different register allocators are
136201095a5dSDimitry Andric /// defined as separate passes because they may require different analysis.
136301095a5dSDimitry Andric ///
136401095a5dSDimitry Andric /// This helper ensures that the regalloc= option is always available,
136501095a5dSDimitry Andric /// even for targets that override the default allocator.
136601095a5dSDimitry Andric ///
136701095a5dSDimitry Andric /// FIXME: When MachinePassRegistry register pass IDs instead of function ptrs,
136801095a5dSDimitry Andric /// this can be folded into addPass.
createRegAllocPass(bool Optimized)136901095a5dSDimitry Andric FunctionPass *TargetPassConfig::createRegAllocPass(bool Optimized) {
137001095a5dSDimitry Andric   // Initialize the global default.
137101095a5dSDimitry Andric   llvm::call_once(InitializeDefaultRegisterAllocatorFlag,
137201095a5dSDimitry Andric                   initializeDefaultRegisterAllocatorOnce);
137301095a5dSDimitry Andric 
137401095a5dSDimitry Andric   RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault();
137501095a5dSDimitry Andric   if (Ctor != useDefaultRegisterAllocator)
137601095a5dSDimitry Andric     return Ctor();
137701095a5dSDimitry Andric 
137801095a5dSDimitry Andric   // With no -regalloc= override, ask the target for a regalloc pass.
137901095a5dSDimitry Andric   return createTargetRegisterAllocator(Optimized);
138001095a5dSDimitry Andric }
138101095a5dSDimitry Andric 
isCustomizedRegAlloc()1382145449b1SDimitry Andric bool TargetPassConfig::isCustomizedRegAlloc() {
1383145449b1SDimitry Andric   return RegAlloc !=
1384145449b1SDimitry Andric          (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator;
1385145449b1SDimitry Andric }
1386145449b1SDimitry Andric 
addRegAssignAndRewriteFast()1387b60736ecSDimitry Andric bool TargetPassConfig::addRegAssignAndRewriteFast() {
1388344a3780SDimitry Andric   if (RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator &&
1389344a3780SDimitry Andric       RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&createFastRegisterAllocator)
1390e6d15924SDimitry Andric     report_fatal_error("Must use fast (default) register allocator for unoptimized regalloc.");
1391e6d15924SDimitry Andric 
1392e6d15924SDimitry Andric   addPass(createRegAllocPass(false));
1393344a3780SDimitry Andric 
1394344a3780SDimitry Andric   // Allow targets to change the register assignments after
1395344a3780SDimitry Andric   // fast register allocation.
1396344a3780SDimitry Andric   addPostFastRegAllocRewrite();
1397e6d15924SDimitry Andric   return true;
1398e6d15924SDimitry Andric }
1399e6d15924SDimitry Andric 
addRegAssignAndRewriteOptimized()1400b60736ecSDimitry Andric bool TargetPassConfig::addRegAssignAndRewriteOptimized() {
1401e6d15924SDimitry Andric   // Add the selected register allocation pass.
1402e6d15924SDimitry Andric   addPass(createRegAllocPass(true));
1403e6d15924SDimitry Andric 
1404e6d15924SDimitry Andric   // Allow targets to change the register assignments before rewriting.
1405e6d15924SDimitry Andric   addPreRewrite();
1406e6d15924SDimitry Andric 
1407e6d15924SDimitry Andric   // Finally rewrite virtual registers.
1408e6d15924SDimitry Andric   addPass(&VirtRegRewriterID);
1409cfca06d7SDimitry Andric 
14106f8fc217SDimitry Andric   // Regalloc scoring for ML-driven eviction - noop except when learning a new
14116f8fc217SDimitry Andric   // eviction policy.
14126f8fc217SDimitry Andric   addPass(createRegAllocScoringPass());
1413e6d15924SDimitry Andric   return true;
1414e6d15924SDimitry Andric }
1415e6d15924SDimitry Andric 
141601095a5dSDimitry Andric /// Return true if the default global register allocator is in use and
141701095a5dSDimitry Andric /// has not be overriden on the command line with '-regalloc=...'
usingDefaultRegAlloc() const141801095a5dSDimitry Andric bool TargetPassConfig::usingDefaultRegAlloc() const {
141901095a5dSDimitry Andric   return RegAlloc.getNumOccurrences() == 0;
142001095a5dSDimitry Andric }
142101095a5dSDimitry Andric 
142201095a5dSDimitry Andric /// Add the minimum set of target-independent passes that are required for
142301095a5dSDimitry Andric /// register allocation. No coalescing or scheduling.
addFastRegAlloc()1424e6d15924SDimitry Andric void TargetPassConfig::addFastRegAlloc() {
1425c0981da4SDimitry Andric   addPass(&PHIEliminationID);
1426c0981da4SDimitry Andric   addPass(&TwoAddressInstructionPassID);
142701095a5dSDimitry Andric 
1428b60736ecSDimitry Andric   addRegAssignAndRewriteFast();
142901095a5dSDimitry Andric }
143001095a5dSDimitry Andric 
143101095a5dSDimitry Andric /// Add standard target-independent passes that are tightly coupled with
143201095a5dSDimitry Andric /// optimized register allocation, including coalescing, machine instruction
143301095a5dSDimitry Andric /// scheduling, and register allocation itself.
addOptimizedRegAlloc()1434e6d15924SDimitry Andric void TargetPassConfig::addOptimizedRegAlloc() {
1435c0981da4SDimitry Andric   addPass(&DetectDeadLanesID);
143601095a5dSDimitry Andric 
1437ac9a064cSDimitry Andric   addPass(&InitUndefID);
1438ac9a064cSDimitry Andric 
1439c0981da4SDimitry Andric   addPass(&ProcessImplicitDefsID);
144001095a5dSDimitry Andric 
144101095a5dSDimitry Andric   // LiveVariables currently requires pure SSA form.
144201095a5dSDimitry Andric   //
144301095a5dSDimitry Andric   // FIXME: Once TwoAddressInstruction pass no longer uses kill flags,
144401095a5dSDimitry Andric   // LiveVariables can be removed completely, and LiveIntervals can be directly
144501095a5dSDimitry Andric   // computed. (We still either need to regenerate kill flags after regalloc, or
144601095a5dSDimitry Andric   // preferably fix the scavenger to not depend on them).
1447b60736ecSDimitry Andric   // FIXME: UnreachableMachineBlockElim is a dependant pass of LiveVariables.
1448b60736ecSDimitry Andric   // When LiveVariables is removed this has to be removed/moved either.
1449b60736ecSDimitry Andric   // Explicit addition of UnreachableMachineBlockElim allows stopping before or
1450b60736ecSDimitry Andric   // after it with -stop-before/-stop-after.
1451c0981da4SDimitry Andric   addPass(&UnreachableMachineBlockElimID);
1452c0981da4SDimitry Andric   addPass(&LiveVariablesID);
145301095a5dSDimitry Andric 
145401095a5dSDimitry Andric   // Edge splitting is smarter with machine loop info.
1455c0981da4SDimitry Andric   addPass(&MachineLoopInfoID);
1456c0981da4SDimitry Andric   addPass(&PHIEliminationID);
145701095a5dSDimitry Andric 
145801095a5dSDimitry Andric   // Eventually, we want to run LiveIntervals before PHI elimination.
145901095a5dSDimitry Andric   if (EarlyLiveIntervals)
1460c0981da4SDimitry Andric     addPass(&LiveIntervalsID);
146101095a5dSDimitry Andric 
1462c0981da4SDimitry Andric   addPass(&TwoAddressInstructionPassID);
146301095a5dSDimitry Andric   addPass(&RegisterCoalescerID);
146401095a5dSDimitry Andric 
146501095a5dSDimitry Andric   // The machine scheduler may accidentally create disconnected components
146601095a5dSDimitry Andric   // when moving subregister definitions around, avoid this by splitting them to
146701095a5dSDimitry Andric   // separate vregs before. Splitting can also improve reg. allocation quality.
146801095a5dSDimitry Andric   addPass(&RenameIndependentSubregsID);
146901095a5dSDimitry Andric 
147001095a5dSDimitry Andric   // PreRA instruction scheduling.
147101095a5dSDimitry Andric   addPass(&MachineSchedulerID);
147201095a5dSDimitry Andric 
1473b60736ecSDimitry Andric   if (addRegAssignAndRewriteOptimized()) {
1474b60736ecSDimitry Andric     // Perform stack slot coloring and post-ra machine LICM.
1475b60736ecSDimitry Andric     addPass(&StackSlotColoringID);
1476b60736ecSDimitry Andric 
1477e6d15924SDimitry Andric     // Allow targets to expand pseudo instructions depending on the choice of
1478e6d15924SDimitry Andric     // registers before MachineCopyPropagation.
1479e6d15924SDimitry Andric     addPostRewrite();
148001095a5dSDimitry Andric 
1481eb11fae6SDimitry Andric     // Copy propagate to forward register uses and try to eliminate COPYs that
1482eb11fae6SDimitry Andric     // were not coalesced.
1483eb11fae6SDimitry Andric     addPass(&MachineCopyPropagationID);
1484eb11fae6SDimitry Andric 
148501095a5dSDimitry Andric     // Run post-ra machine LICM to hoist reloads / remats.
148601095a5dSDimitry Andric     //
148701095a5dSDimitry Andric     // FIXME: can this move into MachineLateOptimization?
1488eb11fae6SDimitry Andric     addPass(&MachineLICMID);
148901095a5dSDimitry Andric   }
149001095a5dSDimitry Andric }
149101095a5dSDimitry Andric 
149201095a5dSDimitry Andric //===---------------------------------------------------------------------===//
149301095a5dSDimitry Andric /// Post RegAlloc Pass Configuration
149401095a5dSDimitry Andric //===---------------------------------------------------------------------===//
149501095a5dSDimitry Andric 
149601095a5dSDimitry Andric /// Add passes that optimize machine instructions after register allocation.
addMachineLateOptimization()149701095a5dSDimitry Andric void TargetPassConfig::addMachineLateOptimization() {
1498e3b55780SDimitry Andric   // Cleanup of redundant immediate/address loads.
1499e3b55780SDimitry Andric   addPass(&MachineLateInstrsCleanupID);
1500e3b55780SDimitry Andric 
150101095a5dSDimitry Andric   // Branch folding must be run after regalloc and prolog/epilog insertion.
150201095a5dSDimitry Andric   addPass(&BranchFolderPassID);
150301095a5dSDimitry Andric 
150401095a5dSDimitry Andric   // Tail duplication.
150501095a5dSDimitry Andric   // Note that duplicating tail just increases code size and degrades
150601095a5dSDimitry Andric   // performance for targets that require Structured Control Flow.
150701095a5dSDimitry Andric   // In addition it can also make CFG irreducible. Thus we disable it.
150801095a5dSDimitry Andric   if (!TM->requiresStructuredCFG())
150901095a5dSDimitry Andric     addPass(&TailDuplicateID);
151001095a5dSDimitry Andric 
151101095a5dSDimitry Andric   // Copy propagation.
151201095a5dSDimitry Andric   addPass(&MachineCopyPropagationID);
151301095a5dSDimitry Andric }
151401095a5dSDimitry Andric 
151501095a5dSDimitry Andric /// Add standard GC passes.
addGCPasses()151601095a5dSDimitry Andric bool TargetPassConfig::addGCPasses() {
1517c0981da4SDimitry Andric   addPass(&GCMachineCodeAnalysisID);
151801095a5dSDimitry Andric   return true;
151901095a5dSDimitry Andric }
152001095a5dSDimitry Andric 
152101095a5dSDimitry Andric /// Add standard basic block placement passes.
addBlockPlacement()152201095a5dSDimitry Andric void TargetPassConfig::addBlockPlacement() {
1523c0981da4SDimitry Andric   if (EnableFSDiscriminator) {
1524c0981da4SDimitry Andric     addPass(createMIRAddFSDiscriminatorsPass(
1525c0981da4SDimitry Andric         sampleprof::FSDiscriminatorPass::Pass2));
1526c0981da4SDimitry Andric     const std::string ProfileFile = getFSProfileFile(TM);
1527c0981da4SDimitry Andric     if (!ProfileFile.empty() && !DisableLayoutFSProfileLoader)
15287fa27ce4SDimitry Andric       addPass(createMIRProfileLoaderPass(ProfileFile, getFSRemappingFile(TM),
15297fa27ce4SDimitry Andric                                          sampleprof::FSDiscriminatorPass::Pass2,
15307fa27ce4SDimitry Andric                                          nullptr));
1531c0981da4SDimitry Andric   }
153201095a5dSDimitry Andric   if (addPass(&MachineBlockPlacementID)) {
153301095a5dSDimitry Andric     // Run a separate pass to collect block placement statistics.
153401095a5dSDimitry Andric     if (EnableBlockPlacementStats)
153501095a5dSDimitry Andric       addPass(&MachineBlockPlacementStatsID);
153601095a5dSDimitry Andric   }
153701095a5dSDimitry Andric }
1538b915e9e0SDimitry Andric 
1539b915e9e0SDimitry Andric //===---------------------------------------------------------------------===//
1540b915e9e0SDimitry Andric /// GlobalISel Configuration
1541b915e9e0SDimitry Andric //===---------------------------------------------------------------------===//
isGlobalISelAbortEnabled() const1542b915e9e0SDimitry Andric bool TargetPassConfig::isGlobalISelAbortEnabled() const {
1543d8e91e46SDimitry Andric   return TM->Options.GlobalISelAbort == GlobalISelAbortMode::Enable;
1544b915e9e0SDimitry Andric }
1545b915e9e0SDimitry Andric 
reportDiagnosticWhenGlobalISelFallback() const1546b915e9e0SDimitry Andric bool TargetPassConfig::reportDiagnosticWhenGlobalISelFallback() const {
1547d8e91e46SDimitry Andric   return TM->Options.GlobalISelAbort == GlobalISelAbortMode::DisableWithDiag;
1548b915e9e0SDimitry Andric }
1549e6d15924SDimitry Andric 
isGISelCSEEnabled() const1550e6d15924SDimitry Andric bool TargetPassConfig::isGISelCSEEnabled() const {
1551e6d15924SDimitry Andric   return true;
1552e6d15924SDimitry Andric }
1553e6d15924SDimitry Andric 
getCSEConfig() const1554e6d15924SDimitry Andric std::unique_ptr<CSEConfigBase> TargetPassConfig::getCSEConfig() const {
15551d5ae102SDimitry Andric   return std::make_unique<CSEConfigBase>();
1556e6d15924SDimitry Andric }
1557