12f09f445SMaksim Panchenko //===- bolt/Rewrite/BinaryPassManager.cpp - Binary-level pass manager -----===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler
9a34c753fSRafael Auler #include "bolt/Rewrite/BinaryPassManager.h"
10a34c753fSRafael Auler #include "bolt/Passes/ADRRelaxationPass.h"
11a34c753fSRafael Auler #include "bolt/Passes/Aligner.h"
12a34c753fSRafael Auler #include "bolt/Passes/AllocCombiner.h"
13443f1b4fSRafael Auler #include "bolt/Passes/AsmDump.h"
14687e4af1SAmir Ayupov #include "bolt/Passes/CMOVConversion.h"
15a34c753fSRafael Auler #include "bolt/Passes/FrameOptimizer.h"
16a34c753fSRafael Auler #include "bolt/Passes/IdenticalCodeFolding.h"
17a34c753fSRafael Auler #include "bolt/Passes/IndirectCallPromotion.h"
18a34c753fSRafael Auler #include "bolt/Passes/Inliner.h"
19a34c753fSRafael Auler #include "bolt/Passes/Instrumentation.h"
20a34c753fSRafael Auler #include "bolt/Passes/JTFootprintReduction.h"
21a34c753fSRafael Auler #include "bolt/Passes/LongJmp.h"
22a34c753fSRafael Auler #include "bolt/Passes/LoopInversionPass.h"
23a34c753fSRafael Auler #include "bolt/Passes/PLTCall.h"
24a34c753fSRafael Auler #include "bolt/Passes/PatchEntries.h"
25a34c753fSRafael Auler #include "bolt/Passes/RegReAssign.h"
26a34c753fSRafael Auler #include "bolt/Passes/ReorderData.h"
27a34c753fSRafael Auler #include "bolt/Passes/ReorderFunctions.h"
28a34c753fSRafael Auler #include "bolt/Passes/RetpolineInsertion.h"
29a34c753fSRafael Auler #include "bolt/Passes/SplitFunctions.h"
30a34c753fSRafael Auler #include "bolt/Passes/StokeInfo.h"
31a34c753fSRafael Auler #include "bolt/Passes/TailDuplication.h"
32a34c753fSRafael Auler #include "bolt/Passes/ThreeWayBranch.h"
33a34c753fSRafael Auler #include "bolt/Passes/ValidateInternalCalls.h"
34a34c753fSRafael Auler #include "bolt/Passes/VeneerElimination.h"
35a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
36a34c753fSRafael Auler #include "llvm/Support/FormatVariadic.h"
37a34c753fSRafael Auler #include "llvm/Support/Timer.h"
38a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h"
39443f1b4fSRafael Auler #include <memory>
40a34c753fSRafael Auler #include <numeric>
41a34c753fSRafael Auler
42a34c753fSRafael Auler using namespace llvm;
43a34c753fSRafael Auler
44a34c753fSRafael Auler namespace opts {
45a34c753fSRafael Auler
46a34c753fSRafael Auler extern cl::opt<bool> PrintAll;
47a34c753fSRafael Auler extern cl::opt<bool> PrintDynoStats;
48a34c753fSRafael Auler extern cl::opt<bool> DumpDotAll;
49443f1b4fSRafael Auler extern cl::opt<std::string> AsmDump;
50a34c753fSRafael Auler extern cl::opt<bolt::PLTCall::OptType> PLT;
51a34c753fSRafael Auler
52a34c753fSRafael Auler static cl::opt<bool>
53a34c753fSRafael Auler DynoStatsAll("dyno-stats-all",
54a34c753fSRafael Auler cl::desc("print dyno stats after each stage"),
55330c8e42SMaksim Panchenko cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory));
56a34c753fSRafael Auler
57a34c753fSRafael Auler static cl::opt<bool>
58a34c753fSRafael Auler EliminateUnreachable("eliminate-unreachable",
5936c7d79dSFangrui Song cl::desc("eliminate unreachable code"), cl::init(true),
6036c7d79dSFangrui Song cl::cat(BoltOptCategory));
61a34c753fSRafael Auler
62b92436efSFangrui Song cl::opt<bool> ICF("icf", cl::desc("fold functions with identical code"),
63b92436efSFangrui Song cl::cat(BoltOptCategory));
64a34c753fSRafael Auler
65b92436efSFangrui Song static cl::opt<bool> JTFootprintReductionFlag(
66b92436efSFangrui Song "jt-footprint-reduction",
67a34c753fSRafael Auler cl::desc("make jump tables size smaller at the cost of using more "
68a34c753fSRafael Auler "instructions at jump sites"),
69b92436efSFangrui Song cl::cat(BoltOptCategory));
70a34c753fSRafael Auler
7136c7d79dSFangrui Song cl::opt<bool> NeverPrint("never-print", cl::desc("never print"),
7236c7d79dSFangrui Song cl::ReallyHidden, cl::cat(BoltOptCategory));
73a34c753fSRafael Auler
74a34c753fSRafael Auler cl::opt<bool>
75a34c753fSRafael Auler PrintAfterBranchFixup("print-after-branch-fixup",
76a34c753fSRafael Auler cl::desc("print function after fixing local branches"),
77330c8e42SMaksim Panchenko cl::Hidden, cl::cat(BoltOptCategory));
78a34c753fSRafael Auler
79a34c753fSRafael Auler static cl::opt<bool>
80a34c753fSRafael Auler PrintAfterLowering("print-after-lowering",
81a34c753fSRafael Auler cl::desc("print function after instruction lowering"),
82330c8e42SMaksim Panchenko cl::Hidden, cl::cat(BoltOptCategory));
83a34c753fSRafael Auler
84a34c753fSRafael Auler cl::opt<bool>
85a34c753fSRafael Auler PrintFinalized("print-finalized",
86a34c753fSRafael Auler cl::desc("print function after CFG is finalized"),
87330c8e42SMaksim Panchenko cl::Hidden, cl::cat(BoltOptCategory));
88a34c753fSRafael Auler
89a34c753fSRafael Auler static cl::opt<bool>
90330c8e42SMaksim Panchenko PrintFOP("print-fop",
91b92436efSFangrui Song cl::desc("print functions after frame optimizer pass"), cl::Hidden,
92b92436efSFangrui Song cl::cat(BoltOptCategory));
93a34c753fSRafael Auler
94a34c753fSRafael Auler static cl::opt<bool>
95b92436efSFangrui Song PrintICF("print-icf", cl::desc("print functions after ICF optimization"),
96b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
97a34c753fSRafael Auler
98a34c753fSRafael Auler static cl::opt<bool>
99a34c753fSRafael Auler PrintICP("print-icp",
100a34c753fSRafael Auler cl::desc("print functions after indirect call promotion"),
101b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
102a34c753fSRafael Auler
103a34c753fSRafael Auler static cl::opt<bool>
104a34c753fSRafael Auler PrintInline("print-inline",
105a34c753fSRafael Auler cl::desc("print functions after inlining optimization"),
106b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
107330c8e42SMaksim Panchenko
108b92436efSFangrui Song static cl::opt<bool> PrintJTFootprintReduction(
109b92436efSFangrui Song "print-after-jt-footprint-reduction",
110330c8e42SMaksim Panchenko cl::desc("print function after jt-footprint-reduction pass"),
111b92436efSFangrui Song cl::cat(BoltOptCategory));
112330c8e42SMaksim Panchenko
113330c8e42SMaksim Panchenko static cl::opt<bool>
114330c8e42SMaksim Panchenko PrintLongJmp("print-longjmp",
115b92436efSFangrui Song cl::desc("print functions after longjmp pass"), cl::Hidden,
116b92436efSFangrui Song cl::cat(BoltOptCategory));
117330c8e42SMaksim Panchenko
118330c8e42SMaksim Panchenko cl::opt<bool>
119330c8e42SMaksim Panchenko PrintNormalized("print-normalized",
120330c8e42SMaksim Panchenko cl::desc("print functions after CFG is normalized"),
121b92436efSFangrui Song cl::Hidden, cl::cat(BoltCategory));
122a34c753fSRafael Auler
123b92436efSFangrui Song static cl::opt<bool> PrintOptimizeBodyless(
124b92436efSFangrui Song "print-optimize-bodyless",
125b92436efSFangrui Song cl::desc("print functions after bodyless optimization"), cl::Hidden,
126b92436efSFangrui Song cl::cat(BoltOptCategory));
127a34c753fSRafael Auler
128a34c753fSRafael Auler static cl::opt<bool>
129a34c753fSRafael Auler PrintPeepholes("print-peepholes",
130a34c753fSRafael Auler cl::desc("print functions after peephole optimization"),
131b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
132a34c753fSRafael Auler
133a34c753fSRafael Auler static cl::opt<bool>
134b92436efSFangrui Song PrintPLT("print-plt", cl::desc("print functions after PLT optimization"),
135b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
136a34c753fSRafael Auler
137a34c753fSRafael Auler static cl::opt<bool>
138a34c753fSRafael Auler PrintProfileStats("print-profile-stats",
139a34c753fSRafael Auler cl::desc("print profile quality/bias analysis"),
140b92436efSFangrui Song cl::cat(BoltCategory));
141330c8e42SMaksim Panchenko
142330c8e42SMaksim Panchenko static cl::opt<bool>
143330c8e42SMaksim Panchenko PrintRegReAssign("print-regreassign",
144330c8e42SMaksim Panchenko cl::desc("print functions after regreassign pass"),
145b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
146330c8e42SMaksim Panchenko
147330c8e42SMaksim Panchenko cl::opt<bool>
148330c8e42SMaksim Panchenko PrintReordered("print-reordered",
149330c8e42SMaksim Panchenko cl::desc("print functions after layout optimization"),
150b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
151330c8e42SMaksim Panchenko
152330c8e42SMaksim Panchenko static cl::opt<bool>
153330c8e42SMaksim Panchenko PrintReorderedFunctions("print-reordered-functions",
154330c8e42SMaksim Panchenko cl::desc("print functions after clustering"),
155b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
156330c8e42SMaksim Panchenko
15736c7d79dSFangrui Song static cl::opt<bool> PrintRetpolineInsertion(
15836c7d79dSFangrui Song "print-retpoline-insertion",
159330c8e42SMaksim Panchenko cl::desc("print functions after retpoline insertion pass"),
16036c7d79dSFangrui Song cl::cat(BoltCategory));
161330c8e42SMaksim Panchenko
162b92436efSFangrui Song static cl::opt<bool> PrintSCTC(
163b92436efSFangrui Song "print-sctc",
164330c8e42SMaksim Panchenko cl::desc("print functions after conditional tail call simplification"),
165b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
166330c8e42SMaksim Panchenko
167b92436efSFangrui Song static cl::opt<bool> PrintSimplifyROLoads(
168b92436efSFangrui Song "print-simplify-rodata-loads",
169330c8e42SMaksim Panchenko cl::desc("print functions after simplification of RO data loads"),
170b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
171330c8e42SMaksim Panchenko
172330c8e42SMaksim Panchenko static cl::opt<bool>
173b92436efSFangrui Song PrintSplit("print-split", cl::desc("print functions after code splitting"),
174b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
175330c8e42SMaksim Panchenko
176330c8e42SMaksim Panchenko static cl::opt<bool>
17736c7d79dSFangrui Song PrintStoke("print-stoke", cl::desc("print functions after stoke analysis"),
17836c7d79dSFangrui Song cl::cat(BoltOptCategory));
179330c8e42SMaksim Panchenko
18036c7d79dSFangrui Song static cl::opt<bool> PrintVeneerElimination(
18136c7d79dSFangrui Song "print-veneer-elimination",
182330c8e42SMaksim Panchenko cl::desc("print functions after veneer elimination pass"),
18336c7d79dSFangrui Song cl::cat(BoltOptCategory));
184330c8e42SMaksim Panchenko
185330c8e42SMaksim Panchenko static cl::opt<bool>
186330c8e42SMaksim Panchenko PrintUCE("print-uce",
187330c8e42SMaksim Panchenko cl::desc("print functions after unreachable code elimination"),
188b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
189330c8e42SMaksim Panchenko
19036c7d79dSFangrui Song static cl::opt<bool> RegReAssign(
19136c7d79dSFangrui Song "reg-reassign",
19236c7d79dSFangrui Song cl::desc(
19336c7d79dSFangrui Song "reassign registers so as to avoid using REX prefixes in hot code"),
19436c7d79dSFangrui Song cl::cat(BoltOptCategory));
195a34c753fSRafael Auler
19636c7d79dSFangrui Song static cl::opt<bool> SimplifyConditionalTailCalls(
19736c7d79dSFangrui Song "simplify-conditional-tail-calls",
198a34c753fSRafael Auler cl::desc("simplify conditional tail calls by removing unnecessary jumps"),
19936c7d79dSFangrui Song cl::init(true), cl::cat(BoltOptCategory));
200a34c753fSRafael Auler
201b92436efSFangrui Song static cl::opt<bool> SimplifyRODataLoads(
202b92436efSFangrui Song "simplify-rodata-loads",
203a34c753fSRafael Auler cl::desc("simplify loads from read-only sections by replacing the memory "
204a34c753fSRafael Auler "operand with the constant found in the corresponding section"),
205b92436efSFangrui Song cl::cat(BoltOptCategory));
206a34c753fSRafael Auler
207a34c753fSRafael Auler static cl::list<std::string>
208a34c753fSRafael Auler SpecializeMemcpy1("memcpy1-spec",
209a34c753fSRafael Auler cl::desc("list of functions with call sites for which to specialize memcpy() "
210a34c753fSRafael Auler "for size 1"),
211a34c753fSRafael Auler cl::value_desc("func1,func2:cs1:cs2,func3:cs1,..."),
212330c8e42SMaksim Panchenko cl::ZeroOrMore, cl::cat(BoltOptCategory));
213330c8e42SMaksim Panchenko
21436c7d79dSFangrui Song static cl::opt<bool> Stoke("stoke", cl::desc("turn on the stoke analysis"),
21536c7d79dSFangrui Song cl::cat(BoltOptCategory));
216330c8e42SMaksim Panchenko
21736c7d79dSFangrui Song static cl::opt<bool> StringOps(
21836c7d79dSFangrui Song "inline-memcpy",
219330c8e42SMaksim Panchenko cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"),
22036c7d79dSFangrui Song cl::cat(BoltOptCategory));
221a34c753fSRafael Auler
22236c7d79dSFangrui Song static cl::opt<bool> StripRepRet(
22336c7d79dSFangrui Song "strip-rep-ret",
224a34c753fSRafael Auler cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
22536c7d79dSFangrui Song cl::init(true), cl::cat(BoltOptCategory));
226a34c753fSRafael Auler
22736c7d79dSFangrui Song static cl::opt<bool> VerifyCFG("verify-cfg",
228a34c753fSRafael Auler cl::desc("verify the CFG after every pass"),
22936c7d79dSFangrui Song cl::Hidden, cl::cat(BoltOptCategory));
230a34c753fSRafael Auler
231b92436efSFangrui Song static cl::opt<bool> ThreeWayBranchFlag("three-way-branch",
232330c8e42SMaksim Panchenko cl::desc("reorder three way branches"),
233b92436efSFangrui Song cl::ReallyHidden,
234b92436efSFangrui Song cl::cat(BoltOptCategory));
235a34c753fSRafael Auler
236687e4af1SAmir Ayupov static cl::opt<bool> CMOVConversionFlag("cmov-conversion",
237687e4af1SAmir Ayupov cl::desc("fold jcc+mov into cmov"),
238b92436efSFangrui Song cl::ReallyHidden,
239687e4af1SAmir Ayupov cl::cat(BoltOptCategory));
240687e4af1SAmir Ayupov
241a34c753fSRafael Auler } // namespace opts
242a34c753fSRafael Auler
243a34c753fSRafael Auler namespace llvm {
244a34c753fSRafael Auler namespace bolt {
245a34c753fSRafael Auler
246a34c753fSRafael Auler using namespace opts;
247a34c753fSRafael Auler
24840c2e0faSMaksim Panchenko const char BinaryFunctionPassManager::TimerGroupName[] = "passman";
249a34c753fSRafael Auler const char BinaryFunctionPassManager::TimerGroupDesc[] =
250a34c753fSRafael Auler "Binary Function Pass Manager";
251a34c753fSRafael Auler
runPasses()252a34c753fSRafael Auler void BinaryFunctionPassManager::runPasses() {
253a34c753fSRafael Auler auto &BFs = BC.getBinaryFunctions();
254a34c753fSRafael Auler for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) {
255a34c753fSRafael Auler const std::pair<const bool, std::unique_ptr<BinaryFunctionPass>>
256a34c753fSRafael Auler &OptPassPair = Passes[PassIdx];
257a34c753fSRafael Auler if (!OptPassPair.first)
258a34c753fSRafael Auler continue;
259a34c753fSRafael Auler
260a34c753fSRafael Auler const std::unique_ptr<BinaryFunctionPass> &Pass = OptPassPair.second;
261a34c753fSRafael Auler std::string PassIdName =
262a34c753fSRafael Auler formatv("{0:2}_{1}", PassIdx, Pass->getName()).str();
263a34c753fSRafael Auler
264ee0e9ccbSMaksim Panchenko if (opts::Verbosity > 0)
265a34c753fSRafael Auler outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
266a34c753fSRafael Auler
267a34c753fSRafael Auler NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
268a34c753fSRafael Auler TimerGroupDesc, TimeOpts);
269a34c753fSRafael Auler
27040c2e0faSMaksim Panchenko callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs,
27166b01a89SAmir Ayupov Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
272a34c753fSRafael Auler
273a34c753fSRafael Auler if (opts::VerifyCFG &&
274a34c753fSRafael Auler !std::accumulate(
27540c2e0faSMaksim Panchenko BFs.begin(), BFs.end(), true,
276a34c753fSRafael Auler [](const bool Valid,
277a34c753fSRafael Auler const std::pair<const uint64_t, BinaryFunction> &It) {
278a34c753fSRafael Auler return Valid && It.second.validateCFG();
279a34c753fSRafael Auler })) {
280a34c753fSRafael Auler errs() << "BOLT-ERROR: Invalid CFG detected after pass "
281a34c753fSRafael Auler << Pass->getName() << "\n";
282a34c753fSRafael Auler exit(1);
283a34c753fSRafael Auler }
284a34c753fSRafael Auler
285ee0e9ccbSMaksim Panchenko if (opts::Verbosity > 0)
286a34c753fSRafael Auler outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
287a34c753fSRafael Auler
288a34c753fSRafael Auler if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass())
289a34c753fSRafael Auler continue;
290a34c753fSRafael Auler
291a34c753fSRafael Auler const std::string Message = std::string("after ") + Pass->getName();
292a34c753fSRafael Auler
293a34c753fSRafael Auler for (auto &It : BFs) {
294ee0e9ccbSMaksim Panchenko BinaryFunction &Function = It.second;
295a34c753fSRafael Auler
296a34c753fSRafael Auler if (!Pass->shouldPrint(Function))
297a34c753fSRafael Auler continue;
298a34c753fSRafael Auler
299a34c753fSRafael Auler Function.print(outs(), Message, true);
300a34c753fSRafael Auler
301a34c753fSRafael Auler if (opts::DumpDotAll)
302a34c753fSRafael Auler Function.dumpGraphForPass(PassIdName);
303a34c753fSRafael Auler }
304a34c753fSRafael Auler }
305a34c753fSRafael Auler }
306a34c753fSRafael Auler
runAllPasses(BinaryContext & BC)307a34c753fSRafael Auler void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
308a34c753fSRafael Auler BinaryFunctionPassManager Manager(BC);
309a34c753fSRafael Auler
31066b01a89SAmir Ayupov const DynoStats InitialDynoStats =
31166b01a89SAmir Ayupov getDynoStats(BC.getBinaryFunctions(), BC.isAArch64());
312a34c753fSRafael Auler
313443f1b4fSRafael Auler Manager.registerPass(std::make_unique<AsmDumpPass>(),
314443f1b4fSRafael Auler opts::AsmDump.getNumOccurrences());
315443f1b4fSRafael Auler
316*35efe1d8SVladislav Khmelevsky if (BC.isAArch64())
317*35efe1d8SVladislav Khmelevsky Manager.registerPass(
318*35efe1d8SVladislav Khmelevsky std::make_unique<VeneerElimination>(PrintVeneerElimination));
319*35efe1d8SVladislav Khmelevsky
320ee0e9ccbSMaksim Panchenko if (opts::Instrument)
321a34c753fSRafael Auler Manager.registerPass(std::make_unique<Instrumentation>(NeverPrint));
322a34c753fSRafael Auler
323a34c753fSRafael Auler // Here we manage dependencies/order manually, since passes are run in the
324a34c753fSRafael Auler // order they're registered.
325a34c753fSRafael Auler
326a34c753fSRafael Auler // Run this pass first to use stats for the original functions.
327a34c753fSRafael Auler Manager.registerPass(std::make_unique<PrintProgramStats>(NeverPrint));
328a34c753fSRafael Auler
329a34c753fSRafael Auler if (opts::PrintProfileStats)
330a34c753fSRafael Auler Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint));
331a34c753fSRafael Auler
332a34c753fSRafael Auler Manager.registerPass(std::make_unique<ValidateInternalCalls>(NeverPrint));
333a34c753fSRafael Auler
33408f56926SVladislav Khmelevsky Manager.registerPass(std::make_unique<ShortenInstructions>(NeverPrint));
33508f56926SVladislav Khmelevsky
33608f56926SVladislav Khmelevsky Manager.registerPass(std::make_unique<RemoveNops>(NeverPrint));
33708f56926SVladislav Khmelevsky
338cbf530bfSMaksim Panchenko Manager.registerPass(std::make_unique<NormalizeCFG>(PrintNormalized));
339cbf530bfSMaksim Panchenko
340a34c753fSRafael Auler Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
341a34c753fSRafael Auler opts::StripRepRet);
342a34c753fSRafael Auler
343a34c753fSRafael Auler Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
344a34c753fSRafael Auler opts::ICF);
345a34c753fSRafael Auler
346a34c753fSRafael Auler Manager.registerPass(
347a34c753fSRafael Auler std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
348a34c753fSRafael Auler !opts::SpecializeMemcpy1.empty());
349a34c753fSRafael Auler
350a34c753fSRafael Auler Manager.registerPass(std::make_unique<InlineMemcpy>(NeverPrint),
351a34c753fSRafael Auler opts::StringOps);
352a34c753fSRafael Auler
353a34c753fSRafael Auler Manager.registerPass(std::make_unique<IndirectCallPromotion>(PrintICP));
354a34c753fSRafael Auler
355a34c753fSRafael Auler Manager.registerPass(
356a34c753fSRafael Auler std::make_unique<JTFootprintReduction>(PrintJTFootprintReduction),
357a34c753fSRafael Auler opts::JTFootprintReductionFlag);
358a34c753fSRafael Auler
359a34c753fSRafael Auler Manager.registerPass(
360a34c753fSRafael Auler std::make_unique<SimplifyRODataLoads>(PrintSimplifyROLoads),
361a34c753fSRafael Auler opts::SimplifyRODataLoads);
362a34c753fSRafael Auler
363a34c753fSRafael Auler Manager.registerPass(std::make_unique<RegReAssign>(PrintRegReAssign),
364a34c753fSRafael Auler opts::RegReAssign);
365a34c753fSRafael Auler
366a34c753fSRafael Auler Manager.registerPass(std::make_unique<Inliner>(PrintInline));
367a34c753fSRafael Auler
368a34c753fSRafael Auler Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
369a34c753fSRafael Auler opts::ICF);
370a34c753fSRafael Auler
371a34c753fSRafael Auler Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
372a34c753fSRafael Auler
373a34c753fSRafael Auler Manager.registerPass(std::make_unique<ThreeWayBranch>(),
374a34c753fSRafael Auler opts::ThreeWayBranchFlag);
375a34c753fSRafael Auler
376a34c753fSRafael Auler Manager.registerPass(std::make_unique<ReorderBasicBlocks>(PrintReordered));
377a34c753fSRafael Auler
37840c2e0faSMaksim Panchenko Manager.registerPass(std::make_unique<EliminateUnreachableBlocks>(PrintUCE),
379a34c753fSRafael Auler opts::EliminateUnreachable);
380a34c753fSRafael Auler
381a34c753fSRafael Auler Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
382a34c753fSRafael Auler
383a34c753fSRafael Auler Manager.registerPass(std::make_unique<LoopInversionPass>());
384a34c753fSRafael Auler
3855904836bSspupyrev Manager.registerPass(std::make_unique<TailDuplication>());
386a34c753fSRafael Auler
387687e4af1SAmir Ayupov Manager.registerPass(std::make_unique<CMOVConversion>(),
388687e4af1SAmir Ayupov opts::CMOVConversionFlag);
389687e4af1SAmir Ayupov
390a34c753fSRafael Auler // This pass syncs local branches with CFG. If any of the following
391a34c753fSRafael Auler // passes breaks the sync - they either need to re-run the pass or
392a34c753fSRafael Auler // fix branches consistency internally.
393a34c753fSRafael Auler Manager.registerPass(std::make_unique<FixupBranches>(PrintAfterBranchFixup));
394a34c753fSRafael Auler
395a34c753fSRafael Auler // This pass should come close to last since it uses the estimated hot
396a34c753fSRafael Auler // size of a function to determine the order. It should definitely
397a34c753fSRafael Auler // also happen after any changes to the call graph are made, e.g. inlining.
398a34c753fSRafael Auler Manager.registerPass(
399a34c753fSRafael Auler std::make_unique<ReorderFunctions>(PrintReorderedFunctions));
400a34c753fSRafael Auler
401a34c753fSRafael Auler // Print final dyno stats right while CFG and instruction analysis are intact.
402a34c753fSRafael Auler Manager.registerPass(
403a34c753fSRafael Auler std::make_unique<DynoStatsPrintPass>(
404a34c753fSRafael Auler InitialDynoStats, "after all optimizations before SCTC and FOP"),
405194b164eSAmir Ayupov opts::PrintDynoStats || opts::DynoStatsAll);
406a34c753fSRafael Auler
407a34c753fSRafael Auler // Add the StokeInfo pass, which extract functions for stoke optimization and
408a34c753fSRafael Auler // get the liveness information for them
409a34c753fSRafael Auler Manager.registerPass(std::make_unique<StokeInfo>(PrintStoke), opts::Stoke);
410a34c753fSRafael Auler
411a34c753fSRafael Auler // This pass introduces conditional jumps into external functions.
412a34c753fSRafael Auler // Between extending CFG to support this and isolating this pass we chose
413a34c753fSRafael Auler // the latter. Thus this pass will do double jump removal and unreachable
414a34c753fSRafael Auler // code elimination if necessary and won't rely on peepholes/UCE for these
415a34c753fSRafael Auler // optimizations.
416a34c753fSRafael Auler // More generally this pass should be the last optimization pass that
417a34c753fSRafael Auler // modifies branches/control flow. This pass is run after function
418a34c753fSRafael Auler // reordering so that it can tell whether calls are forward/backward
419a34c753fSRafael Auler // accurately.
420a34c753fSRafael Auler Manager.registerPass(
421a34c753fSRafael Auler std::make_unique<SimplifyConditionalTailCalls>(PrintSCTC),
422a34c753fSRafael Auler opts::SimplifyConditionalTailCalls);
423a34c753fSRafael Auler
424a34c753fSRafael Auler Manager.registerPass(std::make_unique<Peepholes>(PrintPeepholes));
425a34c753fSRafael Auler
426a34c753fSRafael Auler Manager.registerPass(std::make_unique<AlignerPass>());
427a34c753fSRafael Auler
428a34c753fSRafael Auler // Perform reordering on data contained in one or more sections using
429a34c753fSRafael Auler // memory profiling data.
430a34c753fSRafael Auler Manager.registerPass(std::make_unique<ReorderData>());
431a34c753fSRafael Auler
432a34c753fSRafael Auler if (BC.isAArch64()) {
433a34c753fSRafael Auler Manager.registerPass(std::make_unique<ADRRelaxationPass>());
434a34c753fSRafael Auler
435a34c753fSRafael Auler // Tighten branches according to offset differences between branch and
436a34c753fSRafael Auler // targets. No extra instructions after this pass, otherwise we may have
437a34c753fSRafael Auler // relocations out of range and crash during linking.
438a34c753fSRafael Auler Manager.registerPass(std::make_unique<LongJmpPass>(PrintLongJmp));
439a34c753fSRafael Auler }
440a34c753fSRafael Auler
441a34c753fSRafael Auler // This pass should always run last.*
442a34c753fSRafael Auler Manager.registerPass(std::make_unique<FinalizeFunctions>(PrintFinalized));
443a34c753fSRafael Auler
444a34c753fSRafael Auler // FrameOptimizer has an implicit dependency on FinalizeFunctions.
445a34c753fSRafael Auler // FrameOptimizer move values around and needs to update CFIs. To do this, it
446a34c753fSRafael Auler // must read CFI, interpret it and rewrite it, so CFIs need to be correctly
447a34c753fSRafael Auler // placed according to the final layout.
448a34c753fSRafael Auler Manager.registerPass(std::make_unique<FrameOptimizerPass>(PrintFOP));
449a34c753fSRafael Auler
450a34c753fSRafael Auler Manager.registerPass(std::make_unique<AllocCombinerPass>(PrintFOP));
451a34c753fSRafael Auler
452a34c753fSRafael Auler Manager.registerPass(
453a34c753fSRafael Auler std::make_unique<RetpolineInsertion>(PrintRetpolineInsertion));
454a34c753fSRafael Auler
455a34c753fSRafael Auler // Assign each function an output section.
456a34c753fSRafael Auler Manager.registerPass(std::make_unique<AssignSections>());
457a34c753fSRafael Auler
458a34c753fSRafael Auler // Patch original function entries
459a34c753fSRafael Auler if (BC.HasRelocations)
460a34c753fSRafael Auler Manager.registerPass(std::make_unique<PatchEntries>());
461a34c753fSRafael Auler
462a34c753fSRafael Auler // This pass turns tail calls into jumps which makes them invisible to
463a34c753fSRafael Auler // function reordering. It's unsafe to use any CFG or instruction analysis
464a34c753fSRafael Auler // after this point.
465a34c753fSRafael Auler Manager.registerPass(
466a34c753fSRafael Auler std::make_unique<InstructionLowering>(PrintAfterLowering));
467a34c753fSRafael Auler
468a34c753fSRafael Auler // In non-relocation mode, mark functions that do not fit into their original
469a34c753fSRafael Auler // space as non-simple if we have to (e.g. for correct debug info update).
470a34c753fSRafael Auler // NOTE: this pass depends on finalized code.
471a34c753fSRafael Auler if (!BC.HasRelocations)
472a34c753fSRafael Auler Manager.registerPass(std::make_unique<CheckLargeFunctions>(NeverPrint));
473a34c753fSRafael Auler
474a34c753fSRafael Auler Manager.registerPass(std::make_unique<LowerAnnotations>(NeverPrint));
475a34c753fSRafael Auler
476a34c753fSRafael Auler Manager.runPasses();
477a34c753fSRafael Auler }
478a34c753fSRafael Auler
479a34c753fSRafael Auler } // namespace bolt
480a34c753fSRafael Auler } // namespace llvm
481