xref: /llvm-project/bolt/lib/Rewrite/BinaryPassManager.cpp (revision 17ed8f29287b1c0495d25025a28f065c0f53bbc7)
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"
15*17ed8f29SVladislav Khmelevsky #include "bolt/Passes/FixRelaxationPass.h"
16a34c753fSRafael Auler #include "bolt/Passes/FrameOptimizer.h"
171fb18619SAlexey Moksyakov #include "bolt/Passes/Hugify.h"
18a34c753fSRafael Auler #include "bolt/Passes/IdenticalCodeFolding.h"
19a34c753fSRafael Auler #include "bolt/Passes/IndirectCallPromotion.h"
20a34c753fSRafael Auler #include "bolt/Passes/Inliner.h"
21a34c753fSRafael Auler #include "bolt/Passes/Instrumentation.h"
22a34c753fSRafael Auler #include "bolt/Passes/JTFootprintReduction.h"
23a34c753fSRafael Auler #include "bolt/Passes/LongJmp.h"
24a34c753fSRafael Auler #include "bolt/Passes/LoopInversionPass.h"
25a34c753fSRafael Auler #include "bolt/Passes/PLTCall.h"
26a34c753fSRafael Auler #include "bolt/Passes/PatchEntries.h"
27a34c753fSRafael Auler #include "bolt/Passes/RegReAssign.h"
28a34c753fSRafael Auler #include "bolt/Passes/ReorderData.h"
29a34c753fSRafael Auler #include "bolt/Passes/ReorderFunctions.h"
30a34c753fSRafael Auler #include "bolt/Passes/RetpolineInsertion.h"
31a34c753fSRafael Auler #include "bolt/Passes/SplitFunctions.h"
32a34c753fSRafael Auler #include "bolt/Passes/StokeInfo.h"
33a34c753fSRafael Auler #include "bolt/Passes/TailDuplication.h"
34a34c753fSRafael Auler #include "bolt/Passes/ThreeWayBranch.h"
35a34c753fSRafael Auler #include "bolt/Passes/ValidateInternalCalls.h"
364f158995SRafael Auler #include "bolt/Passes/ValidateMemRefs.h"
37a34c753fSRafael Auler #include "bolt/Passes/VeneerElimination.h"
38a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
39a34c753fSRafael Auler #include "llvm/Support/FormatVariadic.h"
40a34c753fSRafael Auler #include "llvm/Support/Timer.h"
41a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h"
42443f1b4fSRafael Auler #include <memory>
43a34c753fSRafael Auler #include <numeric>
44a34c753fSRafael Auler 
45a34c753fSRafael Auler using namespace llvm;
46a34c753fSRafael Auler 
47a34c753fSRafael Auler namespace opts {
48a34c753fSRafael Auler 
49a34c753fSRafael Auler extern cl::opt<bool> PrintAll;
50a34c753fSRafael Auler extern cl::opt<bool> PrintDynoStats;
51a34c753fSRafael Auler extern cl::opt<bool> DumpDotAll;
52443f1b4fSRafael Auler extern cl::opt<std::string> AsmDump;
53a34c753fSRafael Auler extern cl::opt<bolt::PLTCall::OptType> PLT;
54a34c753fSRafael Auler 
55a34c753fSRafael Auler static cl::opt<bool>
56a34c753fSRafael Auler DynoStatsAll("dyno-stats-all",
57a34c753fSRafael Auler   cl::desc("print dyno stats after each stage"),
58330c8e42SMaksim Panchenko   cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory));
59a34c753fSRafael Auler 
60a34c753fSRafael Auler static cl::opt<bool>
61a34c753fSRafael Auler     EliminateUnreachable("eliminate-unreachable",
6236c7d79dSFangrui Song                          cl::desc("eliminate unreachable code"), cl::init(true),
6336c7d79dSFangrui Song                          cl::cat(BoltOptCategory));
64a34c753fSRafael Auler 
65b92436efSFangrui Song cl::opt<bool> ICF("icf", cl::desc("fold functions with identical code"),
66b92436efSFangrui Song                   cl::cat(BoltOptCategory));
67a34c753fSRafael Auler 
68b92436efSFangrui Song static cl::opt<bool> JTFootprintReductionFlag(
69b92436efSFangrui Song     "jt-footprint-reduction",
70a34c753fSRafael Auler     cl::desc("make jump tables size smaller at the cost of using more "
71a34c753fSRafael Auler              "instructions at jump sites"),
72b92436efSFangrui Song     cl::cat(BoltOptCategory));
73a34c753fSRafael Auler 
7436c7d79dSFangrui Song cl::opt<bool> NeverPrint("never-print", cl::desc("never print"),
7536c7d79dSFangrui Song                          cl::ReallyHidden, cl::cat(BoltOptCategory));
76a34c753fSRafael Auler 
77a34c753fSRafael Auler cl::opt<bool>
78a34c753fSRafael Auler PrintAfterBranchFixup("print-after-branch-fixup",
79a34c753fSRafael Auler   cl::desc("print function after fixing local branches"),
80330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
81a34c753fSRafael Auler 
82a34c753fSRafael Auler static cl::opt<bool>
83a34c753fSRafael Auler PrintAfterLowering("print-after-lowering",
84a34c753fSRafael Auler   cl::desc("print function after instruction lowering"),
85330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
86a34c753fSRafael Auler 
87a34c753fSRafael Auler cl::opt<bool>
88a34c753fSRafael Auler PrintFinalized("print-finalized",
89a34c753fSRafael Auler   cl::desc("print function after CFG is finalized"),
90330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
91a34c753fSRafael Auler 
92a34c753fSRafael Auler static cl::opt<bool>
93330c8e42SMaksim Panchenko     PrintFOP("print-fop",
94b92436efSFangrui Song              cl::desc("print functions after frame optimizer pass"), cl::Hidden,
95b92436efSFangrui Song              cl::cat(BoltOptCategory));
96a34c753fSRafael Auler 
97a34c753fSRafael Auler static cl::opt<bool>
98b92436efSFangrui Song     PrintICF("print-icf", cl::desc("print functions after ICF optimization"),
99b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
100a34c753fSRafael Auler 
101a34c753fSRafael Auler static cl::opt<bool>
102a34c753fSRafael Auler     PrintICP("print-icp",
103a34c753fSRafael Auler              cl::desc("print functions after indirect call promotion"),
104b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
105a34c753fSRafael Auler 
106a34c753fSRafael Auler static cl::opt<bool>
107a34c753fSRafael Auler     PrintInline("print-inline",
108a34c753fSRafael Auler                 cl::desc("print functions after inlining optimization"),
109b92436efSFangrui Song                 cl::Hidden, cl::cat(BoltOptCategory));
110330c8e42SMaksim Panchenko 
111b92436efSFangrui Song static cl::opt<bool> PrintJTFootprintReduction(
112b92436efSFangrui Song     "print-after-jt-footprint-reduction",
113330c8e42SMaksim Panchenko     cl::desc("print function after jt-footprint-reduction pass"),
114b92436efSFangrui Song     cl::cat(BoltOptCategory));
115330c8e42SMaksim Panchenko 
116330c8e42SMaksim Panchenko static cl::opt<bool>
117330c8e42SMaksim Panchenko     PrintLongJmp("print-longjmp",
118b92436efSFangrui Song                  cl::desc("print functions after longjmp pass"), cl::Hidden,
119b92436efSFangrui Song                  cl::cat(BoltOptCategory));
120330c8e42SMaksim Panchenko 
121330c8e42SMaksim Panchenko cl::opt<bool>
122330c8e42SMaksim Panchenko     PrintNormalized("print-normalized",
123330c8e42SMaksim Panchenko                     cl::desc("print functions after CFG is normalized"),
124b92436efSFangrui Song                     cl::Hidden, cl::cat(BoltCategory));
125a34c753fSRafael Auler 
126b92436efSFangrui Song static cl::opt<bool> PrintOptimizeBodyless(
127b92436efSFangrui Song     "print-optimize-bodyless",
128b92436efSFangrui Song     cl::desc("print functions after bodyless optimization"), cl::Hidden,
129b92436efSFangrui Song     cl::cat(BoltOptCategory));
130a34c753fSRafael Auler 
131a34c753fSRafael Auler static cl::opt<bool>
132a34c753fSRafael Auler     PrintPeepholes("print-peepholes",
133a34c753fSRafael Auler                    cl::desc("print functions after peephole optimization"),
134b92436efSFangrui Song                    cl::Hidden, cl::cat(BoltOptCategory));
135a34c753fSRafael Auler 
136a34c753fSRafael Auler static cl::opt<bool>
137b92436efSFangrui Song     PrintPLT("print-plt", cl::desc("print functions after PLT optimization"),
138b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
139a34c753fSRafael Auler 
140a34c753fSRafael Auler static cl::opt<bool>
141a34c753fSRafael Auler     PrintProfileStats("print-profile-stats",
142a34c753fSRafael Auler                       cl::desc("print profile quality/bias analysis"),
143b92436efSFangrui Song                       cl::cat(BoltCategory));
144330c8e42SMaksim Panchenko 
145330c8e42SMaksim Panchenko static cl::opt<bool>
146330c8e42SMaksim Panchenko     PrintRegReAssign("print-regreassign",
147330c8e42SMaksim Panchenko                      cl::desc("print functions after regreassign pass"),
148b92436efSFangrui Song                      cl::Hidden, cl::cat(BoltOptCategory));
149330c8e42SMaksim Panchenko 
150330c8e42SMaksim Panchenko cl::opt<bool>
151330c8e42SMaksim Panchenko     PrintReordered("print-reordered",
152330c8e42SMaksim Panchenko                    cl::desc("print functions after layout optimization"),
153b92436efSFangrui Song                    cl::Hidden, cl::cat(BoltOptCategory));
154330c8e42SMaksim Panchenko 
155330c8e42SMaksim Panchenko static cl::opt<bool>
156330c8e42SMaksim Panchenko     PrintReorderedFunctions("print-reordered-functions",
157330c8e42SMaksim Panchenko                             cl::desc("print functions after clustering"),
158b92436efSFangrui Song                             cl::Hidden, cl::cat(BoltOptCategory));
159330c8e42SMaksim Panchenko 
16036c7d79dSFangrui Song static cl::opt<bool> PrintRetpolineInsertion(
16136c7d79dSFangrui Song     "print-retpoline-insertion",
162330c8e42SMaksim Panchenko     cl::desc("print functions after retpoline insertion pass"),
16336c7d79dSFangrui Song     cl::cat(BoltCategory));
164330c8e42SMaksim Panchenko 
165b92436efSFangrui Song static cl::opt<bool> PrintSCTC(
166b92436efSFangrui Song     "print-sctc",
167330c8e42SMaksim Panchenko     cl::desc("print functions after conditional tail call simplification"),
168b92436efSFangrui Song     cl::Hidden, cl::cat(BoltOptCategory));
169330c8e42SMaksim Panchenko 
170b92436efSFangrui Song static cl::opt<bool> PrintSimplifyROLoads(
171b92436efSFangrui Song     "print-simplify-rodata-loads",
172330c8e42SMaksim Panchenko     cl::desc("print functions after simplification of RO data loads"),
173b92436efSFangrui Song     cl::Hidden, cl::cat(BoltOptCategory));
174330c8e42SMaksim Panchenko 
175330c8e42SMaksim Panchenko static cl::opt<bool>
176b92436efSFangrui Song     PrintSplit("print-split", cl::desc("print functions after code splitting"),
177b92436efSFangrui Song                cl::Hidden, cl::cat(BoltOptCategory));
178330c8e42SMaksim Panchenko 
179330c8e42SMaksim Panchenko static cl::opt<bool>
18036c7d79dSFangrui Song     PrintStoke("print-stoke", cl::desc("print functions after stoke analysis"),
18136c7d79dSFangrui Song                cl::cat(BoltOptCategory));
182330c8e42SMaksim Panchenko 
183*17ed8f29SVladislav Khmelevsky static cl::opt<bool>
184*17ed8f29SVladislav Khmelevsky     PrintFixRelaxations("print-fix-relaxations",
185*17ed8f29SVladislav Khmelevsky                         cl::desc("print functions after fix relaxations pass"),
186*17ed8f29SVladislav Khmelevsky                         cl::cat(BoltOptCategory));
187*17ed8f29SVladislav Khmelevsky 
18836c7d79dSFangrui Song static cl::opt<bool> PrintVeneerElimination(
18936c7d79dSFangrui Song     "print-veneer-elimination",
190330c8e42SMaksim Panchenko     cl::desc("print functions after veneer elimination pass"),
19136c7d79dSFangrui Song     cl::cat(BoltOptCategory));
192330c8e42SMaksim Panchenko 
193330c8e42SMaksim Panchenko static cl::opt<bool>
194330c8e42SMaksim Panchenko     PrintUCE("print-uce",
195330c8e42SMaksim Panchenko              cl::desc("print functions after unreachable code elimination"),
196b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
197330c8e42SMaksim Panchenko 
19836c7d79dSFangrui Song static cl::opt<bool> RegReAssign(
19936c7d79dSFangrui Song     "reg-reassign",
20036c7d79dSFangrui Song     cl::desc(
20136c7d79dSFangrui Song         "reassign registers so as to avoid using REX prefixes in hot code"),
20236c7d79dSFangrui Song     cl::cat(BoltOptCategory));
203a34c753fSRafael Auler 
20436c7d79dSFangrui Song static cl::opt<bool> SimplifyConditionalTailCalls(
20536c7d79dSFangrui Song     "simplify-conditional-tail-calls",
206a34c753fSRafael Auler     cl::desc("simplify conditional tail calls by removing unnecessary jumps"),
20736c7d79dSFangrui Song     cl::init(true), cl::cat(BoltOptCategory));
208a34c753fSRafael Auler 
209b92436efSFangrui Song static cl::opt<bool> SimplifyRODataLoads(
210b92436efSFangrui Song     "simplify-rodata-loads",
211a34c753fSRafael Auler     cl::desc("simplify loads from read-only sections by replacing the memory "
212a34c753fSRafael Auler              "operand with the constant found in the corresponding section"),
213b92436efSFangrui Song     cl::cat(BoltOptCategory));
214a34c753fSRafael Auler 
215a34c753fSRafael Auler static cl::list<std::string>
216a34c753fSRafael Auler SpecializeMemcpy1("memcpy1-spec",
217a34c753fSRafael Auler   cl::desc("list of functions with call sites for which to specialize memcpy() "
218a34c753fSRafael Auler            "for size 1"),
219a34c753fSRafael Auler   cl::value_desc("func1,func2:cs1:cs2,func3:cs1,..."),
220330c8e42SMaksim Panchenko   cl::ZeroOrMore, cl::cat(BoltOptCategory));
221330c8e42SMaksim Panchenko 
22236c7d79dSFangrui Song static cl::opt<bool> Stoke("stoke", cl::desc("turn on the stoke analysis"),
22336c7d79dSFangrui Song                            cl::cat(BoltOptCategory));
224330c8e42SMaksim Panchenko 
22536c7d79dSFangrui Song static cl::opt<bool> StringOps(
22636c7d79dSFangrui Song     "inline-memcpy",
227330c8e42SMaksim Panchenko     cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"),
22836c7d79dSFangrui Song     cl::cat(BoltOptCategory));
229a34c753fSRafael Auler 
23036c7d79dSFangrui Song static cl::opt<bool> StripRepRet(
23136c7d79dSFangrui Song     "strip-rep-ret",
232a34c753fSRafael Auler     cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
23336c7d79dSFangrui Song     cl::init(true), cl::cat(BoltOptCategory));
234a34c753fSRafael Auler 
23536c7d79dSFangrui Song static cl::opt<bool> VerifyCFG("verify-cfg",
236a34c753fSRafael Auler                                cl::desc("verify the CFG after every pass"),
23736c7d79dSFangrui Song                                cl::Hidden, cl::cat(BoltOptCategory));
238a34c753fSRafael Auler 
239b92436efSFangrui Song static cl::opt<bool> ThreeWayBranchFlag("three-way-branch",
240330c8e42SMaksim Panchenko                                         cl::desc("reorder three way branches"),
241b92436efSFangrui Song                                         cl::ReallyHidden,
242b92436efSFangrui Song                                         cl::cat(BoltOptCategory));
243a34c753fSRafael Auler 
244687e4af1SAmir Ayupov static cl::opt<bool> CMOVConversionFlag("cmov-conversion",
245687e4af1SAmir Ayupov                                         cl::desc("fold jcc+mov into cmov"),
246b92436efSFangrui Song                                         cl::ReallyHidden,
247687e4af1SAmir Ayupov                                         cl::cat(BoltOptCategory));
248687e4af1SAmir Ayupov 
249a34c753fSRafael Auler } // namespace opts
250a34c753fSRafael Auler 
251a34c753fSRafael Auler namespace llvm {
252a34c753fSRafael Auler namespace bolt {
253a34c753fSRafael Auler 
254a34c753fSRafael Auler using namespace opts;
255a34c753fSRafael Auler 
25640c2e0faSMaksim Panchenko const char BinaryFunctionPassManager::TimerGroupName[] = "passman";
257a34c753fSRafael Auler const char BinaryFunctionPassManager::TimerGroupDesc[] =
258a34c753fSRafael Auler     "Binary Function Pass Manager";
259a34c753fSRafael Auler 
260a34c753fSRafael Auler void BinaryFunctionPassManager::runPasses() {
261a34c753fSRafael Auler   auto &BFs = BC.getBinaryFunctions();
262a34c753fSRafael Auler   for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) {
263a34c753fSRafael Auler     const std::pair<const bool, std::unique_ptr<BinaryFunctionPass>>
264a34c753fSRafael Auler         &OptPassPair = Passes[PassIdx];
265a34c753fSRafael Auler     if (!OptPassPair.first)
266a34c753fSRafael Auler       continue;
267a34c753fSRafael Auler 
268a34c753fSRafael Auler     const std::unique_ptr<BinaryFunctionPass> &Pass = OptPassPair.second;
269a34c753fSRafael Auler     std::string PassIdName =
270a34c753fSRafael Auler         formatv("{0:2}_{1}", PassIdx, Pass->getName()).str();
271a34c753fSRafael Auler 
272ee0e9ccbSMaksim Panchenko     if (opts::Verbosity > 0)
273a34c753fSRafael Auler       outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
274a34c753fSRafael Auler 
275a34c753fSRafael Auler     NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
276a34c753fSRafael Auler                        TimerGroupDesc, TimeOpts);
277a34c753fSRafael Auler 
27840c2e0faSMaksim Panchenko     callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs,
27966b01a89SAmir Ayupov                       Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
280a34c753fSRafael Auler 
281a34c753fSRafael Auler     if (opts::VerifyCFG &&
282a34c753fSRafael Auler         !std::accumulate(
28340c2e0faSMaksim Panchenko             BFs.begin(), BFs.end(), true,
284a34c753fSRafael Auler             [](const bool Valid,
285a34c753fSRafael Auler                const std::pair<const uint64_t, BinaryFunction> &It) {
286a34c753fSRafael Auler               return Valid && It.second.validateCFG();
287a34c753fSRafael Auler             })) {
288a34c753fSRafael Auler       errs() << "BOLT-ERROR: Invalid CFG detected after pass "
289a34c753fSRafael Auler              << Pass->getName() << "\n";
290a34c753fSRafael Auler       exit(1);
291a34c753fSRafael Auler     }
292a34c753fSRafael Auler 
293ee0e9ccbSMaksim Panchenko     if (opts::Verbosity > 0)
294a34c753fSRafael Auler       outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
295a34c753fSRafael Auler 
296a34c753fSRafael Auler     if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass())
297a34c753fSRafael Auler       continue;
298a34c753fSRafael Auler 
299a34c753fSRafael Auler     const std::string Message = std::string("after ") + Pass->getName();
300a34c753fSRafael Auler 
301a34c753fSRafael Auler     for (auto &It : BFs) {
302ee0e9ccbSMaksim Panchenko       BinaryFunction &Function = It.second;
303a34c753fSRafael Auler 
304a34c753fSRafael Auler       if (!Pass->shouldPrint(Function))
305a34c753fSRafael Auler         continue;
306a34c753fSRafael Auler 
307be9d3edeSMaksim Panchenko       Function.print(outs(), Message);
308a34c753fSRafael Auler 
309a34c753fSRafael Auler       if (opts::DumpDotAll)
310a34c753fSRafael Auler         Function.dumpGraphForPass(PassIdName);
311a34c753fSRafael Auler     }
312a34c753fSRafael Auler   }
313a34c753fSRafael Auler }
314a34c753fSRafael Auler 
315a34c753fSRafael Auler void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
316a34c753fSRafael Auler   BinaryFunctionPassManager Manager(BC);
317a34c753fSRafael Auler 
31866b01a89SAmir Ayupov   const DynoStats InitialDynoStats =
31966b01a89SAmir Ayupov       getDynoStats(BC.getBinaryFunctions(), BC.isAArch64());
320a34c753fSRafael Auler 
321443f1b4fSRafael Auler   Manager.registerPass(std::make_unique<AsmDumpPass>(),
322443f1b4fSRafael Auler                        opts::AsmDump.getNumOccurrences());
323443f1b4fSRafael Auler 
324*17ed8f29SVladislav Khmelevsky   if (BC.isAArch64()) {
325*17ed8f29SVladislav Khmelevsky     Manager.registerPass(std::make_unique<FixRelaxations>(PrintFixRelaxations));
326*17ed8f29SVladislav Khmelevsky 
32735efe1d8SVladislav Khmelevsky     Manager.registerPass(
32835efe1d8SVladislav Khmelevsky         std::make_unique<VeneerElimination>(PrintVeneerElimination));
329*17ed8f29SVladislav Khmelevsky   }
33035efe1d8SVladislav Khmelevsky 
331a34c753fSRafael Auler   // Here we manage dependencies/order manually, since passes are run in the
332a34c753fSRafael Auler   // order they're registered.
333a34c753fSRafael Auler 
334a34c753fSRafael Auler   // Run this pass first to use stats for the original functions.
335a34c753fSRafael Auler   Manager.registerPass(std::make_unique<PrintProgramStats>(NeverPrint));
336a34c753fSRafael Auler 
337a34c753fSRafael Auler   if (opts::PrintProfileStats)
338a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint));
339a34c753fSRafael Auler 
340a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ValidateInternalCalls>(NeverPrint));
341a34c753fSRafael Auler 
3424f158995SRafael Auler   Manager.registerPass(std::make_unique<ValidateMemRefs>(NeverPrint));
3434f158995SRafael Auler 
3444f158995SRafael Auler   if (opts::Instrument)
3454f158995SRafael Auler     Manager.registerPass(std::make_unique<Instrumentation>(NeverPrint));
3461fb18619SAlexey Moksyakov   else if (opts::Hugify)
3471fb18619SAlexey Moksyakov     Manager.registerPass(std::make_unique<HugePage>(NeverPrint));
3484f158995SRafael Auler 
34908f56926SVladislav Khmelevsky   Manager.registerPass(std::make_unique<ShortenInstructions>(NeverPrint));
35008f56926SVladislav Khmelevsky 
35108f56926SVladislav Khmelevsky   Manager.registerPass(std::make_unique<RemoveNops>(NeverPrint));
35208f56926SVladislav Khmelevsky 
353cbf530bfSMaksim Panchenko   Manager.registerPass(std::make_unique<NormalizeCFG>(PrintNormalized));
354cbf530bfSMaksim Panchenko 
355a34c753fSRafael Auler   Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
356a34c753fSRafael Auler                        opts::StripRepRet);
357a34c753fSRafael Auler 
358a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
359a34c753fSRafael Auler                        opts::ICF);
360a34c753fSRafael Auler 
361a34c753fSRafael Auler   Manager.registerPass(
362a34c753fSRafael Auler       std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
363a34c753fSRafael Auler       !opts::SpecializeMemcpy1.empty());
364a34c753fSRafael Auler 
365a34c753fSRafael Auler   Manager.registerPass(std::make_unique<InlineMemcpy>(NeverPrint),
366a34c753fSRafael Auler                        opts::StringOps);
367a34c753fSRafael Auler 
368a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IndirectCallPromotion>(PrintICP));
369a34c753fSRafael Auler 
370a34c753fSRafael Auler   Manager.registerPass(
371a34c753fSRafael Auler       std::make_unique<JTFootprintReduction>(PrintJTFootprintReduction),
372a34c753fSRafael Auler       opts::JTFootprintReductionFlag);
373a34c753fSRafael Auler 
374a34c753fSRafael Auler   Manager.registerPass(
375a34c753fSRafael Auler       std::make_unique<SimplifyRODataLoads>(PrintSimplifyROLoads),
376a34c753fSRafael Auler       opts::SimplifyRODataLoads);
377a34c753fSRafael Auler 
378a34c753fSRafael Auler   Manager.registerPass(std::make_unique<RegReAssign>(PrintRegReAssign),
379a34c753fSRafael Auler                        opts::RegReAssign);
380a34c753fSRafael Auler 
381a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Inliner>(PrintInline));
382a34c753fSRafael Auler 
383a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
384a34c753fSRafael Auler                        opts::ICF);
385a34c753fSRafael Auler 
386a34c753fSRafael Auler   Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
387a34c753fSRafael Auler 
388a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ThreeWayBranch>(),
389a34c753fSRafael Auler                        opts::ThreeWayBranchFlag);
390a34c753fSRafael Auler 
391a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderBasicBlocks>(PrintReordered));
392a34c753fSRafael Auler 
39340c2e0faSMaksim Panchenko   Manager.registerPass(std::make_unique<EliminateUnreachableBlocks>(PrintUCE),
394a34c753fSRafael Auler                        opts::EliminateUnreachable);
395a34c753fSRafael Auler 
396a34c753fSRafael Auler   Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
397a34c753fSRafael Auler 
398a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LoopInversionPass>());
399a34c753fSRafael Auler 
4005904836bSspupyrev   Manager.registerPass(std::make_unique<TailDuplication>());
401a34c753fSRafael Auler 
402687e4af1SAmir Ayupov   Manager.registerPass(std::make_unique<CMOVConversion>(),
403687e4af1SAmir Ayupov                        opts::CMOVConversionFlag);
404687e4af1SAmir Ayupov 
405a34c753fSRafael Auler   // This pass syncs local branches with CFG. If any of the following
406a34c753fSRafael Auler   // passes breaks the sync - they either need to re-run the pass or
407a34c753fSRafael Auler   // fix branches consistency internally.
408a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FixupBranches>(PrintAfterBranchFixup));
409a34c753fSRafael Auler 
410a34c753fSRafael Auler   // This pass should come close to last since it uses the estimated hot
411a34c753fSRafael Auler   // size of a function to determine the order.  It should definitely
412a34c753fSRafael Auler   // also happen after any changes to the call graph are made, e.g. inlining.
413a34c753fSRafael Auler   Manager.registerPass(
414a34c753fSRafael Auler       std::make_unique<ReorderFunctions>(PrintReorderedFunctions));
415a34c753fSRafael Auler 
416a34c753fSRafael Auler   // Print final dyno stats right while CFG and instruction analysis are intact.
417a34c753fSRafael Auler   Manager.registerPass(
418a34c753fSRafael Auler       std::make_unique<DynoStatsPrintPass>(
419a34c753fSRafael Auler           InitialDynoStats, "after all optimizations before SCTC and FOP"),
420194b164eSAmir Ayupov       opts::PrintDynoStats || opts::DynoStatsAll);
421a34c753fSRafael Auler 
422a34c753fSRafael Auler   // Add the StokeInfo pass, which extract functions for stoke optimization and
423a34c753fSRafael Auler   // get the liveness information for them
424a34c753fSRafael Auler   Manager.registerPass(std::make_unique<StokeInfo>(PrintStoke), opts::Stoke);
425a34c753fSRafael Auler 
426a34c753fSRafael Auler   // This pass introduces conditional jumps into external functions.
427a34c753fSRafael Auler   // Between extending CFG to support this and isolating this pass we chose
428a34c753fSRafael Auler   // the latter. Thus this pass will do double jump removal and unreachable
429a34c753fSRafael Auler   // code elimination if necessary and won't rely on peepholes/UCE for these
430a34c753fSRafael Auler   // optimizations.
431a34c753fSRafael Auler   // More generally this pass should be the last optimization pass that
432a34c753fSRafael Auler   // modifies branches/control flow.  This pass is run after function
433a34c753fSRafael Auler   // reordering so that it can tell whether calls are forward/backward
434a34c753fSRafael Auler   // accurately.
435a34c753fSRafael Auler   Manager.registerPass(
436a34c753fSRafael Auler       std::make_unique<SimplifyConditionalTailCalls>(PrintSCTC),
437a34c753fSRafael Auler       opts::SimplifyConditionalTailCalls);
438a34c753fSRafael Auler 
439a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Peepholes>(PrintPeepholes));
440a34c753fSRafael Auler 
441a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AlignerPass>());
442a34c753fSRafael Auler 
443a34c753fSRafael Auler   // Perform reordering on data contained in one or more sections using
444a34c753fSRafael Auler   // memory profiling data.
445a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderData>());
446a34c753fSRafael Auler 
447a34c753fSRafael Auler   if (BC.isAArch64()) {
448a34c753fSRafael Auler     Manager.registerPass(std::make_unique<ADRRelaxationPass>());
449a34c753fSRafael Auler 
450a34c753fSRafael Auler     // Tighten branches according to offset differences between branch and
451a34c753fSRafael Auler     // targets. No extra instructions after this pass, otherwise we may have
452a34c753fSRafael Auler     // relocations out of range and crash during linking.
453a34c753fSRafael Auler     Manager.registerPass(std::make_unique<LongJmpPass>(PrintLongJmp));
454a34c753fSRafael Auler   }
455a34c753fSRafael Auler 
456a34c753fSRafael Auler   // This pass should always run last.*
457a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FinalizeFunctions>(PrintFinalized));
458a34c753fSRafael Auler 
459a34c753fSRafael Auler   // FrameOptimizer has an implicit dependency on FinalizeFunctions.
460a34c753fSRafael Auler   // FrameOptimizer move values around and needs to update CFIs. To do this, it
461a34c753fSRafael Auler   // must read CFI, interpret it and rewrite it, so CFIs need to be correctly
462a34c753fSRafael Auler   // placed according to the final layout.
463a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FrameOptimizerPass>(PrintFOP));
464a34c753fSRafael Auler 
465a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AllocCombinerPass>(PrintFOP));
466a34c753fSRafael Auler 
467a34c753fSRafael Auler   Manager.registerPass(
468a34c753fSRafael Auler       std::make_unique<RetpolineInsertion>(PrintRetpolineInsertion));
469a34c753fSRafael Auler 
470a34c753fSRafael Auler   // Assign each function an output section.
471a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AssignSections>());
472a34c753fSRafael Auler 
473a34c753fSRafael Auler   // Patch original function entries
474a34c753fSRafael Auler   if (BC.HasRelocations)
475a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PatchEntries>());
476a34c753fSRafael Auler 
477a34c753fSRafael Auler   // This pass turns tail calls into jumps which makes them invisible to
478a34c753fSRafael Auler   // function reordering. It's unsafe to use any CFG or instruction analysis
479a34c753fSRafael Auler   // after this point.
480a34c753fSRafael Auler   Manager.registerPass(
481a34c753fSRafael Auler       std::make_unique<InstructionLowering>(PrintAfterLowering));
482a34c753fSRafael Auler 
483a34c753fSRafael Auler   // In non-relocation mode, mark functions that do not fit into their original
484a34c753fSRafael Auler   // space as non-simple if we have to (e.g. for correct debug info update).
485a34c753fSRafael Auler   // NOTE: this pass depends on finalized code.
486a34c753fSRafael Auler   if (!BC.HasRelocations)
487a34c753fSRafael Auler     Manager.registerPass(std::make_unique<CheckLargeFunctions>(NeverPrint));
488a34c753fSRafael Auler 
489a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LowerAnnotations>(NeverPrint));
490a34c753fSRafael Auler 
491a34c753fSRafael Auler   Manager.runPasses();
492a34c753fSRafael Auler }
493a34c753fSRafael Auler 
494a34c753fSRafael Auler } // namespace bolt
495a34c753fSRafael Auler } // namespace llvm
496