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