xref: /llvm-project/bolt/lib/Rewrite/BinaryPassManager.cpp (revision 08f56926c2d27e033f114415cabe6b7880143892)
1a34c753fSRafael Auler //===--- BinaryPassManager.cpp - Binary-level analysis/optimization passes ===//
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 //===----------------------------------------------------------------------===//
10a34c753fSRafael Auler 
11a34c753fSRafael Auler #include "bolt/Rewrite/BinaryPassManager.h"
12a34c753fSRafael Auler #include "bolt/Passes/ADRRelaxationPass.h"
13a34c753fSRafael Auler #include "bolt/Passes/Aligner.h"
14a34c753fSRafael Auler #include "bolt/Passes/AllocCombiner.h"
15443f1b4fSRafael Auler #include "bolt/Passes/AsmDump.h"
16a34c753fSRafael Auler #include "bolt/Passes/FrameOptimizer.h"
17a34c753fSRafael Auler #include "bolt/Passes/IdenticalCodeFolding.h"
18a34c753fSRafael Auler #include "bolt/Passes/IndirectCallPromotion.h"
19a34c753fSRafael Auler #include "bolt/Passes/Inliner.h"
20a34c753fSRafael Auler #include "bolt/Passes/Instrumentation.h"
21a34c753fSRafael Auler #include "bolt/Passes/JTFootprintReduction.h"
22a34c753fSRafael Auler #include "bolt/Passes/LongJmp.h"
23a34c753fSRafael Auler #include "bolt/Passes/LoopInversionPass.h"
24a34c753fSRafael Auler #include "bolt/Passes/PLTCall.h"
25a34c753fSRafael Auler #include "bolt/Passes/PatchEntries.h"
26a34c753fSRafael Auler #include "bolt/Passes/RegReAssign.h"
27a34c753fSRafael Auler #include "bolt/Passes/ReorderData.h"
28a34c753fSRafael Auler #include "bolt/Passes/ReorderFunctions.h"
29a34c753fSRafael Auler #include "bolt/Passes/RetpolineInsertion.h"
30a34c753fSRafael Auler #include "bolt/Passes/SplitFunctions.h"
31a34c753fSRafael Auler #include "bolt/Passes/StokeInfo.h"
32a34c753fSRafael Auler #include "bolt/Passes/TailDuplication.h"
33a34c753fSRafael Auler #include "bolt/Passes/ThreeWayBranch.h"
34a34c753fSRafael Auler #include "bolt/Passes/ValidateInternalCalls.h"
35a34c753fSRafael Auler #include "bolt/Passes/VeneerElimination.h"
36a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
37a34c753fSRafael Auler #include "llvm/Support/FormatVariadic.h"
38a34c753fSRafael Auler #include "llvm/Support/Timer.h"
39a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h"
40443f1b4fSRafael Auler #include <memory>
41a34c753fSRafael Auler #include <numeric>
42a34c753fSRafael Auler 
43a34c753fSRafael Auler using namespace llvm;
44a34c753fSRafael Auler 
45a34c753fSRafael Auler namespace opts {
46a34c753fSRafael Auler 
47a34c753fSRafael Auler extern cl::opt<bool> PrintAll;
48a34c753fSRafael Auler extern cl::opt<bool> PrintDynoStats;
49a34c753fSRafael Auler extern cl::opt<bool> DumpDotAll;
50443f1b4fSRafael Auler extern cl::opt<std::string> AsmDump;
51a34c753fSRafael Auler extern cl::opt<bolt::PLTCall::OptType> PLT;
52a34c753fSRafael Auler 
53a34c753fSRafael Auler static cl::opt<bool>
54a34c753fSRafael Auler DynoStatsAll("dyno-stats-all",
55a34c753fSRafael Auler   cl::desc("print dyno stats after each stage"),
56a34c753fSRafael Auler   cl::ZeroOrMore,
57a34c753fSRafael Auler   cl::Hidden,
58a34c753fSRafael Auler   cl::cat(BoltCategory));
59a34c753fSRafael Auler 
60a34c753fSRafael Auler static cl::opt<bool>
61a34c753fSRafael Auler EliminateUnreachable("eliminate-unreachable",
62a34c753fSRafael Auler   cl::desc("eliminate unreachable code"),
63a34c753fSRafael Auler   cl::init(true),
64a34c753fSRafael Auler   cl::ZeroOrMore,
65a34c753fSRafael Auler   cl::cat(BoltOptCategory));
66a34c753fSRafael Auler 
67a34c753fSRafael Auler cl::opt<bool>
68a34c753fSRafael Auler ICF("icf",
69a34c753fSRafael Auler   cl::desc("fold functions with identical code"),
70a34c753fSRafael Auler   cl::ZeroOrMore,
71a34c753fSRafael Auler   cl::cat(BoltOptCategory));
72a34c753fSRafael Auler 
73a34c753fSRafael Auler static cl::opt<bool>
74a34c753fSRafael Auler JTFootprintReductionFlag("jt-footprint-reduction",
75a34c753fSRafael Auler   cl::desc("make jump tables size smaller at the cost of using more "
76a34c753fSRafael Auler            "instructions at jump sites"),
77a34c753fSRafael Auler   cl::ZeroOrMore,
78a34c753fSRafael Auler   cl::cat(BoltOptCategory));
79a34c753fSRafael Auler 
80a34c753fSRafael Auler static cl::opt<bool> TailDuplicationFlag(
81a34c753fSRafael Auler     "tail-duplication",
82a34c753fSRafael Auler     cl::desc("duplicate unconditional branches that cross a cache line"),
83a34c753fSRafael Auler     cl::ZeroOrMore, cl::ReallyHidden, cl::cat(BoltOptCategory));
84a34c753fSRafael Auler 
85a34c753fSRafael Auler static cl::opt<bool> ThreeWayBranchFlag("three-way-branch",
86a34c753fSRafael Auler                                         cl::desc("reorder three way branches"),
87a34c753fSRafael Auler                                         cl::ZeroOrMore, cl::ReallyHidden,
88a34c753fSRafael Auler                                         cl::cat(BoltOptCategory));
89a34c753fSRafael Auler 
90a34c753fSRafael Auler static cl::opt<bool>
91a34c753fSRafael Auler PrintJTFootprintReduction("print-after-jt-footprint-reduction",
92a34c753fSRafael Auler   cl::desc("print function after jt-footprint-reduction pass"),
93a34c753fSRafael Auler   cl::ZeroOrMore,
94a34c753fSRafael Auler   cl::cat(BoltOptCategory));
95a34c753fSRafael Auler 
96a34c753fSRafael Auler cl::opt<bool>
97a34c753fSRafael Auler NeverPrint("never-print",
98a34c753fSRafael Auler   cl::desc("never print"),
99a34c753fSRafael Auler   cl::init(false),
100a34c753fSRafael Auler   cl::ZeroOrMore,
101a34c753fSRafael Auler   cl::ReallyHidden,
102a34c753fSRafael Auler   cl::cat(BoltOptCategory));
103a34c753fSRafael Auler 
104a34c753fSRafael Auler cl::opt<bool>
105a34c753fSRafael Auler PrintAfterBranchFixup("print-after-branch-fixup",
106a34c753fSRafael Auler   cl::desc("print function after fixing local branches"),
107a34c753fSRafael Auler   cl::Hidden,
108a34c753fSRafael Auler   cl::cat(BoltOptCategory));
109a34c753fSRafael Auler 
110a34c753fSRafael Auler static cl::opt<bool>
111a34c753fSRafael Auler PrintAfterLowering("print-after-lowering",
112a34c753fSRafael Auler   cl::desc("print function after instruction lowering"),
113a34c753fSRafael Auler   cl::Hidden,
114a34c753fSRafael Auler   cl::cat(BoltOptCategory));
115a34c753fSRafael Auler 
116a34c753fSRafael Auler static cl::opt<bool>
117a34c753fSRafael Auler PrintFOP("print-fop",
118a34c753fSRafael Auler   cl::desc("print functions after frame optimizer pass"),
119a34c753fSRafael Auler   cl::ZeroOrMore,
120a34c753fSRafael Auler   cl::Hidden,
121a34c753fSRafael Auler   cl::cat(BoltOptCategory));
122a34c753fSRafael Auler 
123a34c753fSRafael Auler cl::opt<bool>
124a34c753fSRafael Auler PrintFinalized("print-finalized",
125a34c753fSRafael Auler   cl::desc("print function after CFG is finalized"),
126a34c753fSRafael Auler   cl::Hidden,
127a34c753fSRafael Auler   cl::cat(BoltOptCategory));
128a34c753fSRafael Auler 
129a34c753fSRafael Auler static cl::opt<bool>
130a34c753fSRafael Auler PrintLongJmp("print-longjmp",
131a34c753fSRafael Auler   cl::desc("print functions after longjmp pass"),
132a34c753fSRafael Auler   cl::ZeroOrMore,
133a34c753fSRafael Auler   cl::Hidden,
134a34c753fSRafael Auler   cl::cat(BoltOptCategory));
135a34c753fSRafael Auler 
136a34c753fSRafael Auler static cl::opt<bool>
137a34c753fSRafael Auler PrintICF("print-icf",
138a34c753fSRafael Auler   cl::desc("print functions after ICF optimization"),
139a34c753fSRafael Auler   cl::ZeroOrMore,
140a34c753fSRafael Auler   cl::Hidden,
141a34c753fSRafael Auler   cl::cat(BoltOptCategory));
142a34c753fSRafael Auler 
143a34c753fSRafael Auler static cl::opt<bool>
144a34c753fSRafael Auler PrintICP("print-icp",
145a34c753fSRafael Auler   cl::desc("print functions after indirect call promotion"),
146a34c753fSRafael Auler   cl::ZeroOrMore,
147a34c753fSRafael Auler   cl::Hidden,
148a34c753fSRafael Auler   cl::cat(BoltOptCategory));
149a34c753fSRafael Auler 
150a34c753fSRafael Auler static cl::opt<bool>
151cbf530bfSMaksim Panchenko PrintNormalized("print-normalized",
152cbf530bfSMaksim Panchenko   cl::desc("print functions after CFG is normalized"),
153cbf530bfSMaksim Panchenko   cl::ZeroOrMore,
154cbf530bfSMaksim Panchenko   cl::Hidden,
155cbf530bfSMaksim Panchenko   cl::cat(BoltCategory));
156cbf530bfSMaksim Panchenko 
157cbf530bfSMaksim Panchenko static cl::opt<bool>
158a34c753fSRafael Auler PrintRegReAssign("print-regreassign",
159a34c753fSRafael Auler   cl::desc("print functions after regreassign pass"),
160a34c753fSRafael Auler   cl::ZeroOrMore,
161a34c753fSRafael Auler   cl::Hidden,
162a34c753fSRafael Auler   cl::cat(BoltOptCategory));
163a34c753fSRafael Auler 
164a34c753fSRafael Auler static cl::opt<bool>
165a34c753fSRafael Auler PrintInline("print-inline",
166a34c753fSRafael Auler   cl::desc("print functions after inlining optimization"),
167a34c753fSRafael Auler   cl::ZeroOrMore,
168a34c753fSRafael Auler   cl::Hidden,
169a34c753fSRafael Auler   cl::cat(BoltOptCategory));
170a34c753fSRafael Auler 
171a34c753fSRafael Auler static cl::opt<bool>
172a34c753fSRafael Auler PrintOptimizeBodyless("print-optimize-bodyless",
173a34c753fSRafael Auler   cl::desc("print functions after bodyless optimization"),
174a34c753fSRafael Auler   cl::ZeroOrMore,
175a34c753fSRafael Auler   cl::Hidden,
176a34c753fSRafael Auler   cl::cat(BoltOptCategory));
177a34c753fSRafael Auler 
178a34c753fSRafael Auler static cl::opt<bool>
179a34c753fSRafael Auler PrintPLT("print-plt",
180a34c753fSRafael Auler   cl::desc("print functions after PLT optimization"),
181a34c753fSRafael Auler   cl::ZeroOrMore,
182a34c753fSRafael Auler   cl::Hidden,
183a34c753fSRafael Auler   cl::cat(BoltOptCategory));
184a34c753fSRafael Auler 
185a34c753fSRafael Auler static cl::opt<bool>
186a34c753fSRafael Auler PrintPeepholes("print-peepholes",
187a34c753fSRafael Auler   cl::desc("print functions after peephole optimization"),
188a34c753fSRafael Auler   cl::ZeroOrMore,
189a34c753fSRafael Auler   cl::Hidden,
190a34c753fSRafael Auler   cl::cat(BoltOptCategory));
191a34c753fSRafael Auler 
192a34c753fSRafael Auler cl::opt<bool>
193a34c753fSRafael Auler PrintReordered("print-reordered",
194a34c753fSRafael Auler   cl::desc("print functions after layout optimization"),
195a34c753fSRafael Auler   cl::ZeroOrMore,
196a34c753fSRafael Auler   cl::Hidden,
197a34c753fSRafael Auler   cl::cat(BoltOptCategory));
198a34c753fSRafael Auler 
199a34c753fSRafael Auler static cl::opt<bool>
200a34c753fSRafael Auler PrintReorderedFunctions("print-reordered-functions",
201a34c753fSRafael Auler   cl::desc("print functions after clustering"),
202a34c753fSRafael Auler   cl::ZeroOrMore,
203a34c753fSRafael Auler   cl::Hidden,
204a34c753fSRafael Auler   cl::cat(BoltOptCategory));
205a34c753fSRafael Auler 
206a34c753fSRafael Auler static cl::opt<bool>
207a34c753fSRafael Auler PrintSCTC("print-sctc",
208a34c753fSRafael Auler   cl::desc("print functions after conditional tail call simplification"),
209a34c753fSRafael Auler   cl::ZeroOrMore,
210a34c753fSRafael Auler   cl::Hidden,
211a34c753fSRafael Auler   cl::cat(BoltOptCategory));
212a34c753fSRafael Auler 
213a34c753fSRafael Auler static cl::opt<bool>
214a34c753fSRafael Auler PrintSimplifyROLoads("print-simplify-rodata-loads",
215a34c753fSRafael Auler   cl::desc("print functions after simplification of RO data loads"),
216a34c753fSRafael Auler   cl::ZeroOrMore,
217a34c753fSRafael Auler   cl::Hidden,
218a34c753fSRafael Auler   cl::cat(BoltOptCategory));
219a34c753fSRafael Auler 
220a34c753fSRafael Auler static cl::opt<bool>
221a34c753fSRafael Auler PrintSplit("print-split",
222a34c753fSRafael Auler   cl::desc("print functions after code splitting"),
223a34c753fSRafael Auler   cl::ZeroOrMore,
224a34c753fSRafael Auler   cl::Hidden,
225a34c753fSRafael Auler   cl::cat(BoltOptCategory));
226a34c753fSRafael Auler 
227a34c753fSRafael Auler static cl::opt<bool>
228a34c753fSRafael Auler PrintUCE("print-uce",
229a34c753fSRafael Auler   cl::desc("print functions after unreachable code elimination"),
230a34c753fSRafael Auler   cl::ZeroOrMore,
231a34c753fSRafael Auler   cl::Hidden,
232a34c753fSRafael Auler   cl::cat(BoltOptCategory));
233a34c753fSRafael Auler 
234a34c753fSRafael Auler static cl::opt<bool>
235a34c753fSRafael Auler PrintProfileStats("print-profile-stats",
236a34c753fSRafael Auler   cl::desc("print profile quality/bias analysis"),
237a34c753fSRafael Auler   cl::ZeroOrMore,
238a34c753fSRafael Auler   cl::init(false),
239a34c753fSRafael Auler   cl::cat(BoltCategory));
240a34c753fSRafael Auler 
241a34c753fSRafael Auler static cl::opt<bool>
242a34c753fSRafael Auler SimplifyConditionalTailCalls("simplify-conditional-tail-calls",
243a34c753fSRafael Auler   cl::desc("simplify conditional tail calls by removing unnecessary jumps"),
244a34c753fSRafael Auler   cl::init(true),
245a34c753fSRafael Auler   cl::ZeroOrMore,
246a34c753fSRafael Auler   cl::cat(BoltOptCategory));
247a34c753fSRafael Auler 
248a34c753fSRafael Auler static cl::opt<bool>
249a34c753fSRafael Auler SimplifyRODataLoads("simplify-rodata-loads",
250a34c753fSRafael Auler   cl::desc("simplify loads from read-only sections by replacing the memory "
251a34c753fSRafael Auler            "operand with the constant found in the corresponding section"),
252a34c753fSRafael Auler   cl::ZeroOrMore,
253a34c753fSRafael Auler   cl::cat(BoltOptCategory));
254a34c753fSRafael Auler 
255a34c753fSRafael Auler static cl::opt<bool>
256a34c753fSRafael Auler RegReAssign("reg-reassign",
257a34c753fSRafael Auler   cl::desc("reassign registers so as to avoid using REX prefixes in hot code"),
258a34c753fSRafael Auler   cl::init(false),
259a34c753fSRafael Auler   cl::ZeroOrMore,
260a34c753fSRafael Auler   cl::cat(BoltOptCategory));
261a34c753fSRafael Auler 
262a34c753fSRafael Auler static cl::opt<bool>
263a34c753fSRafael Auler StringOps("inline-memcpy",
264a34c753fSRafael Auler   cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"),
265a34c753fSRafael Auler   cl::init(false),
266a34c753fSRafael Auler   cl::ZeroOrMore,
267a34c753fSRafael Auler   cl::cat(BoltOptCategory));
268a34c753fSRafael Auler 
269a34c753fSRafael Auler static cl::list<std::string>
270a34c753fSRafael Auler SpecializeMemcpy1("memcpy1-spec",
271a34c753fSRafael Auler   cl::desc("list of functions with call sites for which to specialize memcpy() "
272a34c753fSRafael Auler            "for size 1"),
273a34c753fSRafael Auler   cl::value_desc("func1,func2:cs1:cs2,func3:cs1,..."),
274a34c753fSRafael Auler   cl::ZeroOrMore,
275a34c753fSRafael Auler   cl::cat(BoltOptCategory));
276a34c753fSRafael Auler 
277a34c753fSRafael Auler static cl::opt<bool>
278a34c753fSRafael Auler StripRepRet("strip-rep-ret",
279a34c753fSRafael Auler   cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
280a34c753fSRafael Auler   cl::init(true),
281a34c753fSRafael Auler   cl::ZeroOrMore,
282a34c753fSRafael Auler   cl::cat(BoltOptCategory));
283a34c753fSRafael Auler 
284a34c753fSRafael Auler static llvm::cl::opt<bool>
285a34c753fSRafael Auler VerifyCFG("verify-cfg",
286a34c753fSRafael Auler   cl::desc("verify the CFG after every pass"),
287a34c753fSRafael Auler   cl::init(false),
288a34c753fSRafael Auler   cl::Hidden,
289a34c753fSRafael Auler   cl::ZeroOrMore,
290a34c753fSRafael Auler   cl::cat(BoltOptCategory));
291a34c753fSRafael Auler 
292a34c753fSRafael Auler static llvm::cl::opt<bool>
293a34c753fSRafael Auler Stoke("stoke",
294a34c753fSRafael Auler   cl::desc("turn on the stoke analysis"),
295a34c753fSRafael Auler   cl::init(false),
296a34c753fSRafael Auler   cl::ZeroOrMore,
297a34c753fSRafael Auler   cl::cat(BoltOptCategory));
298a34c753fSRafael Auler 
299a34c753fSRafael Auler static llvm::cl::opt<bool>
300a34c753fSRafael Auler PrintStoke("print-stoke",
301a34c753fSRafael Auler   cl::desc("print functions after stoke analysis"),
302a34c753fSRafael Auler   cl::init(false),
303a34c753fSRafael Auler   cl::ZeroOrMore,
304a34c753fSRafael Auler   cl::cat(BoltOptCategory));
305a34c753fSRafael Auler 
306a34c753fSRafael Auler static llvm::cl::opt<bool>
307a34c753fSRafael Auler   PrintVeneerElimination("print-veneer-elimination",
308a34c753fSRafael Auler     cl::desc("print functions after veneer elimination pass"),
309a34c753fSRafael Auler     cl::init(false),
310a34c753fSRafael Auler     cl::ZeroOrMore,
311a34c753fSRafael Auler     cl::cat(BoltOptCategory));
312a34c753fSRafael Auler 
313a34c753fSRafael Auler static llvm::cl::opt<bool>
314a34c753fSRafael Auler   PrintRetpolineInsertion("print-retpoline-insertion",
315a34c753fSRafael Auler     cl::desc("print functions after retpoline insertion pass"),
316a34c753fSRafael Auler     cl::init(false),
317a34c753fSRafael Auler     cl::ZeroOrMore,
318a34c753fSRafael Auler     cl::cat(BoltCategory));
319a34c753fSRafael Auler 
320a34c753fSRafael Auler } // namespace opts
321a34c753fSRafael Auler 
322a34c753fSRafael Auler namespace llvm {
323a34c753fSRafael Auler namespace bolt {
324a34c753fSRafael Auler 
325a34c753fSRafael Auler using namespace opts;
326a34c753fSRafael Auler 
32740c2e0faSMaksim Panchenko const char BinaryFunctionPassManager::TimerGroupName[] = "passman";
328a34c753fSRafael Auler const char BinaryFunctionPassManager::TimerGroupDesc[] =
329a34c753fSRafael Auler     "Binary Function Pass Manager";
330a34c753fSRafael Auler 
331a34c753fSRafael Auler void BinaryFunctionPassManager::runPasses() {
332a34c753fSRafael Auler   auto &BFs = BC.getBinaryFunctions();
333a34c753fSRafael Auler   for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) {
334a34c753fSRafael Auler     const std::pair<const bool, std::unique_ptr<BinaryFunctionPass>>
335a34c753fSRafael Auler         &OptPassPair = Passes[PassIdx];
336a34c753fSRafael Auler     if (!OptPassPair.first)
337a34c753fSRafael Auler       continue;
338a34c753fSRafael Auler 
339a34c753fSRafael Auler     const std::unique_ptr<BinaryFunctionPass> &Pass = OptPassPair.second;
340a34c753fSRafael Auler     std::string PassIdName =
341a34c753fSRafael Auler         formatv("{0:2}_{1}", PassIdx, Pass->getName()).str();
342a34c753fSRafael Auler 
343a34c753fSRafael Auler     if (opts::Verbosity > 0) {
344a34c753fSRafael Auler       outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
345a34c753fSRafael Auler     }
346a34c753fSRafael Auler 
347a34c753fSRafael Auler     NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
348a34c753fSRafael Auler                        TimerGroupDesc, TimeOpts);
349a34c753fSRafael Auler 
35040c2e0faSMaksim Panchenko     callWithDynoStats([this, &Pass] { Pass->runOnFunctions(BC); }, BFs,
35140c2e0faSMaksim Panchenko                       Pass->getName(), opts::DynoStatsAll);
352a34c753fSRafael Auler 
353a34c753fSRafael Auler     if (opts::VerifyCFG &&
354a34c753fSRafael Auler         !std::accumulate(
35540c2e0faSMaksim Panchenko             BFs.begin(), BFs.end(), true,
356a34c753fSRafael Auler             [](const bool Valid,
357a34c753fSRafael Auler                const std::pair<const uint64_t, BinaryFunction> &It) {
358a34c753fSRafael Auler               return Valid && It.second.validateCFG();
359a34c753fSRafael Auler             })) {
360a34c753fSRafael Auler       errs() << "BOLT-ERROR: Invalid CFG detected after pass "
361a34c753fSRafael Auler              << Pass->getName() << "\n";
362a34c753fSRafael Auler       exit(1);
363a34c753fSRafael Auler     }
364a34c753fSRafael Auler 
365a34c753fSRafael Auler     if (opts::Verbosity > 0) {
366a34c753fSRafael Auler       outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
367a34c753fSRafael Auler     }
368a34c753fSRafael Auler 
369a34c753fSRafael Auler     if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass())
370a34c753fSRafael Auler       continue;
371a34c753fSRafael Auler 
372a34c753fSRafael Auler     const std::string Message = std::string("after ") + Pass->getName();
373a34c753fSRafael Auler 
374a34c753fSRafael Auler     for (auto &It : BFs) {
375a34c753fSRafael Auler       auto &Function = It.second;
376a34c753fSRafael Auler 
377a34c753fSRafael Auler       if (!Pass->shouldPrint(Function))
378a34c753fSRafael Auler         continue;
379a34c753fSRafael Auler 
380a34c753fSRafael Auler       Function.print(outs(), Message, true);
381a34c753fSRafael Auler 
382a34c753fSRafael Auler       if (opts::DumpDotAll)
383a34c753fSRafael Auler         Function.dumpGraphForPass(PassIdName);
384a34c753fSRafael Auler     }
385a34c753fSRafael Auler   }
386a34c753fSRafael Auler }
387a34c753fSRafael Auler 
388a34c753fSRafael Auler void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
389a34c753fSRafael Auler   BinaryFunctionPassManager Manager(BC);
390a34c753fSRafael Auler 
391a34c753fSRafael Auler   const DynoStats InitialDynoStats = getDynoStats(BC.getBinaryFunctions());
392a34c753fSRafael Auler 
393443f1b4fSRafael Auler   Manager.registerPass(std::make_unique<AsmDumpPass>(),
394443f1b4fSRafael Auler                        opts::AsmDump.getNumOccurrences());
395443f1b4fSRafael Auler 
396a34c753fSRafael Auler   if (opts::Instrument) {
397a34c753fSRafael Auler     Manager.registerPass(std::make_unique<Instrumentation>(NeverPrint));
398a34c753fSRafael Auler   }
399a34c753fSRafael Auler 
400a34c753fSRafael Auler   // Here we manage dependencies/order manually, since passes are run in the
401a34c753fSRafael Auler   // order they're registered.
402a34c753fSRafael Auler 
403a34c753fSRafael Auler   // Run this pass first to use stats for the original functions.
404a34c753fSRafael Auler   Manager.registerPass(std::make_unique<PrintProgramStats>(NeverPrint));
405a34c753fSRafael Auler 
406a34c753fSRafael Auler   if (opts::PrintProfileStats)
407a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint));
408a34c753fSRafael Auler 
409a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ValidateInternalCalls>(NeverPrint));
410a34c753fSRafael Auler 
411*08f56926SVladislav Khmelevsky   Manager.registerPass(std::make_unique<ShortenInstructions>(NeverPrint));
412*08f56926SVladislav Khmelevsky 
413*08f56926SVladislav Khmelevsky   Manager.registerPass(std::make_unique<RemoveNops>(NeverPrint));
414*08f56926SVladislav Khmelevsky 
415cbf530bfSMaksim Panchenko   Manager.registerPass(std::make_unique<NormalizeCFG>(PrintNormalized));
416cbf530bfSMaksim Panchenko 
417a34c753fSRafael Auler   Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
418a34c753fSRafael Auler                        opts::StripRepRet);
419a34c753fSRafael Auler 
420a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
421a34c753fSRafael Auler                        opts::ICF);
422a34c753fSRafael Auler 
423a34c753fSRafael Auler   if (BC.isAArch64())
424a34c753fSRafael Auler     Manager.registerPass(
425a34c753fSRafael Auler         std::make_unique<VeneerElimination>(PrintVeneerElimination));
426a34c753fSRafael Auler 
427a34c753fSRafael Auler   Manager.registerPass(
428a34c753fSRafael Auler       std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
429a34c753fSRafael Auler       !opts::SpecializeMemcpy1.empty());
430a34c753fSRafael Auler 
431a34c753fSRafael Auler   Manager.registerPass(std::make_unique<InlineMemcpy>(NeverPrint),
432a34c753fSRafael Auler                        opts::StringOps);
433a34c753fSRafael Auler 
434a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IndirectCallPromotion>(PrintICP));
435a34c753fSRafael Auler 
436a34c753fSRafael Auler   Manager.registerPass(
437a34c753fSRafael Auler       std::make_unique<JTFootprintReduction>(PrintJTFootprintReduction),
438a34c753fSRafael Auler       opts::JTFootprintReductionFlag);
439a34c753fSRafael Auler 
440a34c753fSRafael Auler   Manager.registerPass(
441a34c753fSRafael Auler       std::make_unique<SimplifyRODataLoads>(PrintSimplifyROLoads),
442a34c753fSRafael Auler       opts::SimplifyRODataLoads);
443a34c753fSRafael Auler 
444a34c753fSRafael Auler   Manager.registerPass(std::make_unique<RegReAssign>(PrintRegReAssign),
445a34c753fSRafael Auler                        opts::RegReAssign);
446a34c753fSRafael Auler 
447a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Inliner>(PrintInline));
448a34c753fSRafael Auler 
449a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
450a34c753fSRafael Auler                        opts::ICF);
451a34c753fSRafael Auler 
452a34c753fSRafael Auler   Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
453a34c753fSRafael Auler 
454a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ThreeWayBranch>(),
455a34c753fSRafael Auler                        opts::ThreeWayBranchFlag);
456a34c753fSRafael Auler 
457a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderBasicBlocks>(PrintReordered));
458a34c753fSRafael Auler 
45940c2e0faSMaksim Panchenko   Manager.registerPass(std::make_unique<EliminateUnreachableBlocks>(PrintUCE),
460a34c753fSRafael Auler                        opts::EliminateUnreachable);
461a34c753fSRafael Auler 
462a34c753fSRafael Auler   Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
463a34c753fSRafael Auler 
464a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LoopInversionPass>());
465a34c753fSRafael Auler 
466a34c753fSRafael Auler   Manager.registerPass(std::make_unique<TailDuplication>(),
467a34c753fSRafael Auler                        opts::TailDuplicationFlag);
468a34c753fSRafael Auler 
469a34c753fSRafael Auler   // This pass syncs local branches with CFG. If any of the following
470a34c753fSRafael Auler   // passes breaks the sync - they either need to re-run the pass or
471a34c753fSRafael Auler   // fix branches consistency internally.
472a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FixupBranches>(PrintAfterBranchFixup));
473a34c753fSRafael Auler 
474a34c753fSRafael Auler   // This pass should come close to last since it uses the estimated hot
475a34c753fSRafael Auler   // size of a function to determine the order.  It should definitely
476a34c753fSRafael Auler   // also happen after any changes to the call graph are made, e.g. inlining.
477a34c753fSRafael Auler   Manager.registerPass(
478a34c753fSRafael Auler       std::make_unique<ReorderFunctions>(PrintReorderedFunctions));
479a34c753fSRafael Auler 
480a34c753fSRafael Auler   // Print final dyno stats right while CFG and instruction analysis are intact.
481a34c753fSRafael Auler   Manager.registerPass(
482a34c753fSRafael Auler       std::make_unique<DynoStatsPrintPass>(
483a34c753fSRafael Auler           InitialDynoStats, "after all optimizations before SCTC and FOP"),
484a34c753fSRafael Auler       opts::PrintDynoStats | opts::DynoStatsAll);
485a34c753fSRafael Auler 
486a34c753fSRafael Auler   // Add the StokeInfo pass, which extract functions for stoke optimization and
487a34c753fSRafael Auler   // get the liveness information for them
488a34c753fSRafael Auler   Manager.registerPass(std::make_unique<StokeInfo>(PrintStoke), opts::Stoke);
489a34c753fSRafael Auler 
490a34c753fSRafael Auler   // This pass introduces conditional jumps into external functions.
491a34c753fSRafael Auler   // Between extending CFG to support this and isolating this pass we chose
492a34c753fSRafael Auler   // the latter. Thus this pass will do double jump removal and unreachable
493a34c753fSRafael Auler   // code elimination if necessary and won't rely on peepholes/UCE for these
494a34c753fSRafael Auler   // optimizations.
495a34c753fSRafael Auler   // More generally this pass should be the last optimization pass that
496a34c753fSRafael Auler   // modifies branches/control flow.  This pass is run after function
497a34c753fSRafael Auler   // reordering so that it can tell whether calls are forward/backward
498a34c753fSRafael Auler   // accurately.
499a34c753fSRafael Auler   Manager.registerPass(
500a34c753fSRafael Auler       std::make_unique<SimplifyConditionalTailCalls>(PrintSCTC),
501a34c753fSRafael Auler       opts::SimplifyConditionalTailCalls);
502a34c753fSRafael Auler 
503a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Peepholes>(PrintPeepholes));
504a34c753fSRafael Auler 
505a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AlignerPass>());
506a34c753fSRafael Auler 
507a34c753fSRafael Auler   // Perform reordering on data contained in one or more sections using
508a34c753fSRafael Auler   // memory profiling data.
509a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderData>());
510a34c753fSRafael Auler 
511a34c753fSRafael Auler   if (BC.isAArch64()) {
512a34c753fSRafael Auler     Manager.registerPass(std::make_unique<ADRRelaxationPass>());
513a34c753fSRafael Auler 
514a34c753fSRafael Auler     // Tighten branches according to offset differences between branch and
515a34c753fSRafael Auler     // targets. No extra instructions after this pass, otherwise we may have
516a34c753fSRafael Auler     // relocations out of range and crash during linking.
517a34c753fSRafael Auler     Manager.registerPass(std::make_unique<LongJmpPass>(PrintLongJmp));
518a34c753fSRafael Auler   }
519a34c753fSRafael Auler 
520a34c753fSRafael Auler   // This pass should always run last.*
521a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FinalizeFunctions>(PrintFinalized));
522a34c753fSRafael Auler 
523a34c753fSRafael Auler   // FrameOptimizer has an implicit dependency on FinalizeFunctions.
524a34c753fSRafael Auler   // FrameOptimizer move values around and needs to update CFIs. To do this, it
525a34c753fSRafael Auler   // must read CFI, interpret it and rewrite it, so CFIs need to be correctly
526a34c753fSRafael Auler   // placed according to the final layout.
527a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FrameOptimizerPass>(PrintFOP));
528a34c753fSRafael Auler 
529a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AllocCombinerPass>(PrintFOP));
530a34c753fSRafael Auler 
531a34c753fSRafael Auler   Manager.registerPass(
532a34c753fSRafael Auler       std::make_unique<RetpolineInsertion>(PrintRetpolineInsertion));
533a34c753fSRafael Auler 
534a34c753fSRafael Auler   // Assign each function an output section.
535a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AssignSections>());
536a34c753fSRafael Auler 
537a34c753fSRafael Auler   // Patch original function entries
538a34c753fSRafael Auler   if (BC.HasRelocations)
539a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PatchEntries>());
540a34c753fSRafael Auler 
541a34c753fSRafael Auler   // This pass turns tail calls into jumps which makes them invisible to
542a34c753fSRafael Auler   // function reordering. It's unsafe to use any CFG or instruction analysis
543a34c753fSRafael Auler   // after this point.
544a34c753fSRafael Auler   Manager.registerPass(
545a34c753fSRafael Auler       std::make_unique<InstructionLowering>(PrintAfterLowering));
546a34c753fSRafael Auler 
547a34c753fSRafael Auler   // In non-relocation mode, mark functions that do not fit into their original
548a34c753fSRafael Auler   // space as non-simple if we have to (e.g. for correct debug info update).
549a34c753fSRafael Auler   // NOTE: this pass depends on finalized code.
550a34c753fSRafael Auler   if (!BC.HasRelocations)
551a34c753fSRafael Auler     Manager.registerPass(std::make_unique<CheckLargeFunctions>(NeverPrint));
552a34c753fSRafael Auler 
553a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LowerAnnotations>(NeverPrint));
554a34c753fSRafael Auler 
555a34c753fSRafael Auler   Manager.runPasses();
556a34c753fSRafael Auler }
557a34c753fSRafael Auler 
558a34c753fSRafael Auler } // namespace bolt
559a34c753fSRafael Auler } // namespace llvm
560