xref: /llvm-project/bolt/lib/Rewrite/BinaryPassManager.cpp (revision 3c357a49d61e4c81a1ac016502ee504521bc8dda)
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"
154cab01f0SShatianWang #include "bolt/Passes/ContinuityStats.h"
16f8730293SJob Noorman #include "bolt/Passes/FixRISCVCallsPass.h"
1717ed8f29SVladislav Khmelevsky #include "bolt/Passes/FixRelaxationPass.h"
18a34c753fSRafael Auler #include "bolt/Passes/FrameOptimizer.h"
191fb18619SAlexey Moksyakov #include "bolt/Passes/Hugify.h"
20a34c753fSRafael Auler #include "bolt/Passes/IdenticalCodeFolding.h"
21a34c753fSRafael Auler #include "bolt/Passes/IndirectCallPromotion.h"
22a34c753fSRafael Auler #include "bolt/Passes/Inliner.h"
23a34c753fSRafael Auler #include "bolt/Passes/Instrumentation.h"
24a34c753fSRafael Auler #include "bolt/Passes/JTFootprintReduction.h"
25a34c753fSRafael Auler #include "bolt/Passes/LongJmp.h"
26a34c753fSRafael Auler #include "bolt/Passes/LoopInversionPass.h"
27f3dc732bSAmir Ayupov #include "bolt/Passes/MCF.h"
28a34c753fSRafael Auler #include "bolt/Passes/PLTCall.h"
29a34c753fSRafael Auler #include "bolt/Passes/PatchEntries.h"
30a34c753fSRafael Auler #include "bolt/Passes/RegReAssign.h"
31a34c753fSRafael Auler #include "bolt/Passes/ReorderData.h"
32a34c753fSRafael Auler #include "bolt/Passes/ReorderFunctions.h"
33a34c753fSRafael Auler #include "bolt/Passes/RetpolineInsertion.h"
34a34c753fSRafael Auler #include "bolt/Passes/SplitFunctions.h"
35a34c753fSRafael Auler #include "bolt/Passes/StokeInfo.h"
36a34c753fSRafael Auler #include "bolt/Passes/TailDuplication.h"
37a34c753fSRafael Auler #include "bolt/Passes/ThreeWayBranch.h"
38a34c753fSRafael Auler #include "bolt/Passes/ValidateInternalCalls.h"
394f158995SRafael Auler #include "bolt/Passes/ValidateMemRefs.h"
40a34c753fSRafael Auler #include "bolt/Passes/VeneerElimination.h"
41a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
42a34c753fSRafael Auler #include "llvm/Support/FormatVariadic.h"
43a34c753fSRafael Auler #include "llvm/Support/Timer.h"
44a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h"
45443f1b4fSRafael Auler #include <memory>
46a34c753fSRafael Auler #include <numeric>
47a34c753fSRafael Auler 
48a34c753fSRafael Auler using namespace llvm;
49a34c753fSRafael Auler 
50a34c753fSRafael Auler namespace opts {
51a34c753fSRafael Auler 
52a34c753fSRafael Auler extern cl::opt<bool> PrintAll;
53a34c753fSRafael Auler extern cl::opt<bool> PrintDynoStats;
54a34c753fSRafael Auler extern cl::opt<bool> DumpDotAll;
55443f1b4fSRafael Auler extern cl::opt<std::string> AsmDump;
56a34c753fSRafael Auler extern cl::opt<bolt::PLTCall::OptType> PLT;
57*3c357a49SAlexander Yermolovich extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
58*3c357a49SAlexander Yermolovich                llvm::bolt::DeprecatedICFNumericOptionParser>
59*3c357a49SAlexander Yermolovich     ICF;
60a34c753fSRafael Auler 
61a34c753fSRafael Auler static cl::opt<bool>
62a34c753fSRafael Auler DynoStatsAll("dyno-stats-all",
63a34c753fSRafael Auler   cl::desc("print dyno stats after each stage"),
64330c8e42SMaksim Panchenko   cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory));
65a34c753fSRafael Auler 
66a34c753fSRafael Auler static cl::opt<bool>
67a34c753fSRafael Auler     EliminateUnreachable("eliminate-unreachable",
6836c7d79dSFangrui Song                          cl::desc("eliminate unreachable code"), cl::init(true),
6936c7d79dSFangrui Song                          cl::cat(BoltOptCategory));
70a34c753fSRafael Auler 
71b92436efSFangrui Song static cl::opt<bool> JTFootprintReductionFlag(
72b92436efSFangrui Song     "jt-footprint-reduction",
73a34c753fSRafael Auler     cl::desc("make jump tables size smaller at the cost of using more "
74a34c753fSRafael Auler              "instructions at jump sites"),
75b92436efSFangrui Song     cl::cat(BoltOptCategory));
76a34c753fSRafael Auler 
7751268a57SMaksim Panchenko cl::opt<bool>
78e823136dSMaksim Panchenko     KeepNops("keep-nops",
79e823136dSMaksim Panchenko              cl::desc("keep no-op instructions. By default they are removed."),
80e823136dSMaksim Panchenko              cl::Hidden, cl::cat(BoltOptCategory));
81e823136dSMaksim Panchenko 
8236c7d79dSFangrui Song cl::opt<bool> NeverPrint("never-print", cl::desc("never print"),
8336c7d79dSFangrui Song                          cl::ReallyHidden, cl::cat(BoltOptCategory));
84a34c753fSRafael Auler 
85a34c753fSRafael Auler cl::opt<bool>
86a34c753fSRafael Auler PrintAfterBranchFixup("print-after-branch-fixup",
87a34c753fSRafael Auler   cl::desc("print function after fixing local branches"),
88330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
89a34c753fSRafael Auler 
90a34c753fSRafael Auler static cl::opt<bool>
91a34c753fSRafael Auler PrintAfterLowering("print-after-lowering",
92a34c753fSRafael Auler   cl::desc("print function after instruction lowering"),
93330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
94a34c753fSRafael Auler 
95f3dc732bSAmir Ayupov static cl::opt<bool> PrintEstimateEdgeCounts(
96f3dc732bSAmir Ayupov     "print-estimate-edge-counts",
97f3dc732bSAmir Ayupov     cl::desc("print function after edge counts are set for no-LBR profile"),
98f3dc732bSAmir Ayupov     cl::Hidden, cl::cat(BoltOptCategory));
99f3dc732bSAmir Ayupov 
100a34c753fSRafael Auler cl::opt<bool>
101a34c753fSRafael Auler PrintFinalized("print-finalized",
102a34c753fSRafael Auler   cl::desc("print function after CFG is finalized"),
103330c8e42SMaksim Panchenko   cl::Hidden, cl::cat(BoltOptCategory));
104a34c753fSRafael Auler 
105a34c753fSRafael Auler static cl::opt<bool>
106330c8e42SMaksim Panchenko     PrintFOP("print-fop",
107b92436efSFangrui Song              cl::desc("print functions after frame optimizer pass"), cl::Hidden,
108b92436efSFangrui Song              cl::cat(BoltOptCategory));
109a34c753fSRafael Auler 
110a34c753fSRafael Auler static cl::opt<bool>
111b92436efSFangrui Song     PrintICF("print-icf", cl::desc("print functions after ICF optimization"),
112b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
113a34c753fSRafael Auler 
114a34c753fSRafael Auler static cl::opt<bool>
115a34c753fSRafael Auler     PrintICP("print-icp",
116a34c753fSRafael Auler              cl::desc("print functions after indirect call promotion"),
117b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
118a34c753fSRafael Auler 
119a34c753fSRafael Auler static cl::opt<bool>
120a34c753fSRafael Auler     PrintInline("print-inline",
121a34c753fSRafael Auler                 cl::desc("print functions after inlining optimization"),
122b92436efSFangrui Song                 cl::Hidden, cl::cat(BoltOptCategory));
123330c8e42SMaksim Panchenko 
124b92436efSFangrui Song static cl::opt<bool> PrintJTFootprintReduction(
125b92436efSFangrui Song     "print-after-jt-footprint-reduction",
126061adc18SVladislav Khmelevsky     cl::desc("print function after jt-footprint-reduction pass"), cl::Hidden,
127b92436efSFangrui Song     cl::cat(BoltOptCategory));
128330c8e42SMaksim Panchenko 
129330c8e42SMaksim Panchenko static cl::opt<bool>
1302df48fa7SPaschalis Mpeis     PrintAdrRelaxation("print-adr-relaxation",
1312df48fa7SPaschalis Mpeis                        cl::desc("print functions after ADR Relaxation pass"),
1322df48fa7SPaschalis Mpeis                        cl::Hidden, cl::cat(BoltOptCategory));
1332df48fa7SPaschalis Mpeis 
1342df48fa7SPaschalis Mpeis static cl::opt<bool>
135330c8e42SMaksim Panchenko     PrintLongJmp("print-longjmp",
136b92436efSFangrui Song                  cl::desc("print functions after longjmp pass"), cl::Hidden,
137b92436efSFangrui Song                  cl::cat(BoltOptCategory));
138330c8e42SMaksim Panchenko 
139330c8e42SMaksim Panchenko cl::opt<bool>
140330c8e42SMaksim Panchenko     PrintNormalized("print-normalized",
141330c8e42SMaksim Panchenko                     cl::desc("print functions after CFG is normalized"),
142b92436efSFangrui Song                     cl::Hidden, cl::cat(BoltCategory));
143a34c753fSRafael Auler 
144b92436efSFangrui Song static cl::opt<bool> PrintOptimizeBodyless(
145b92436efSFangrui Song     "print-optimize-bodyless",
146b92436efSFangrui Song     cl::desc("print functions after bodyless optimization"), cl::Hidden,
147b92436efSFangrui Song     cl::cat(BoltOptCategory));
148a34c753fSRafael Auler 
149a34c753fSRafael Auler static cl::opt<bool>
150a34c753fSRafael Auler     PrintPeepholes("print-peepholes",
151a34c753fSRafael Auler                    cl::desc("print functions after peephole optimization"),
152b92436efSFangrui Song                    cl::Hidden, cl::cat(BoltOptCategory));
153a34c753fSRafael Auler 
154a34c753fSRafael Auler static cl::opt<bool>
155b92436efSFangrui Song     PrintPLT("print-plt", cl::desc("print functions after PLT optimization"),
156b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
157a34c753fSRafael Auler 
158a34c753fSRafael Auler static cl::opt<bool>
159a34c753fSRafael Auler     PrintProfileStats("print-profile-stats",
160a34c753fSRafael Auler                       cl::desc("print profile quality/bias analysis"),
161b92436efSFangrui Song                       cl::cat(BoltCategory));
162330c8e42SMaksim Panchenko 
163330c8e42SMaksim Panchenko static cl::opt<bool>
164330c8e42SMaksim Panchenko     PrintRegReAssign("print-regreassign",
165330c8e42SMaksim Panchenko                      cl::desc("print functions after regreassign pass"),
166b92436efSFangrui Song                      cl::Hidden, cl::cat(BoltOptCategory));
167330c8e42SMaksim Panchenko 
168330c8e42SMaksim Panchenko cl::opt<bool>
169330c8e42SMaksim Panchenko     PrintReordered("print-reordered",
170330c8e42SMaksim Panchenko                    cl::desc("print functions after layout optimization"),
171b92436efSFangrui Song                    cl::Hidden, cl::cat(BoltOptCategory));
172330c8e42SMaksim Panchenko 
173330c8e42SMaksim Panchenko static cl::opt<bool>
174330c8e42SMaksim Panchenko     PrintReorderedFunctions("print-reordered-functions",
175330c8e42SMaksim Panchenko                             cl::desc("print functions after clustering"),
176b92436efSFangrui Song                             cl::Hidden, cl::cat(BoltOptCategory));
177330c8e42SMaksim Panchenko 
17836c7d79dSFangrui Song static cl::opt<bool> PrintRetpolineInsertion(
17936c7d79dSFangrui Song     "print-retpoline-insertion",
180061adc18SVladislav Khmelevsky     cl::desc("print functions after retpoline insertion pass"), cl::Hidden,
18136c7d79dSFangrui Song     cl::cat(BoltCategory));
182330c8e42SMaksim Panchenko 
183b92436efSFangrui Song static cl::opt<bool> PrintSCTC(
184b92436efSFangrui Song     "print-sctc",
185330c8e42SMaksim Panchenko     cl::desc("print functions after conditional tail call simplification"),
186b92436efSFangrui Song     cl::Hidden, cl::cat(BoltOptCategory));
187330c8e42SMaksim Panchenko 
188b92436efSFangrui Song static cl::opt<bool> PrintSimplifyROLoads(
189b92436efSFangrui Song     "print-simplify-rodata-loads",
190330c8e42SMaksim Panchenko     cl::desc("print functions after simplification of RO data loads"),
191b92436efSFangrui Song     cl::Hidden, cl::cat(BoltOptCategory));
192330c8e42SMaksim Panchenko 
193330c8e42SMaksim Panchenko static cl::opt<bool>
194b92436efSFangrui Song     PrintSplit("print-split", cl::desc("print functions after code splitting"),
195b92436efSFangrui Song                cl::Hidden, cl::cat(BoltOptCategory));
196330c8e42SMaksim Panchenko 
197330c8e42SMaksim Panchenko static cl::opt<bool>
19836c7d79dSFangrui Song     PrintStoke("print-stoke", cl::desc("print functions after stoke analysis"),
199061adc18SVladislav Khmelevsky                cl::Hidden, cl::cat(BoltOptCategory));
200330c8e42SMaksim Panchenko 
20117ed8f29SVladislav Khmelevsky static cl::opt<bool>
20217ed8f29SVladislav Khmelevsky     PrintFixRelaxations("print-fix-relaxations",
20317ed8f29SVladislav Khmelevsky                         cl::desc("print functions after fix relaxations pass"),
204061adc18SVladislav Khmelevsky                         cl::Hidden, cl::cat(BoltOptCategory));
20517ed8f29SVladislav Khmelevsky 
206f8730293SJob Noorman static cl::opt<bool>
207f8730293SJob Noorman     PrintFixRISCVCalls("print-fix-riscv-calls",
208f8730293SJob Noorman                        cl::desc("print functions after fix RISCV calls pass"),
209061adc18SVladislav Khmelevsky                        cl::Hidden, cl::cat(BoltOptCategory));
210f8730293SJob Noorman 
21136c7d79dSFangrui Song static cl::opt<bool> PrintVeneerElimination(
21236c7d79dSFangrui Song     "print-veneer-elimination",
213061adc18SVladislav Khmelevsky     cl::desc("print functions after veneer elimination pass"), cl::Hidden,
21436c7d79dSFangrui Song     cl::cat(BoltOptCategory));
215330c8e42SMaksim Panchenko 
216330c8e42SMaksim Panchenko static cl::opt<bool>
217330c8e42SMaksim Panchenko     PrintUCE("print-uce",
218330c8e42SMaksim Panchenko              cl::desc("print functions after unreachable code elimination"),
219b92436efSFangrui Song              cl::Hidden, cl::cat(BoltOptCategory));
220330c8e42SMaksim Panchenko 
22136c7d79dSFangrui Song static cl::opt<bool> RegReAssign(
22236c7d79dSFangrui Song     "reg-reassign",
22336c7d79dSFangrui Song     cl::desc(
22436c7d79dSFangrui Song         "reassign registers so as to avoid using REX prefixes in hot code"),
22536c7d79dSFangrui Song     cl::cat(BoltOptCategory));
226a34c753fSRafael Auler 
22736c7d79dSFangrui Song static cl::opt<bool> SimplifyConditionalTailCalls(
22836c7d79dSFangrui Song     "simplify-conditional-tail-calls",
229a34c753fSRafael Auler     cl::desc("simplify conditional tail calls by removing unnecessary jumps"),
23036c7d79dSFangrui Song     cl::init(true), cl::cat(BoltOptCategory));
231a34c753fSRafael Auler 
232b92436efSFangrui Song static cl::opt<bool> SimplifyRODataLoads(
233b92436efSFangrui Song     "simplify-rodata-loads",
234a34c753fSRafael Auler     cl::desc("simplify loads from read-only sections by replacing the memory "
235a34c753fSRafael Auler              "operand with the constant found in the corresponding section"),
236b92436efSFangrui Song     cl::cat(BoltOptCategory));
237a34c753fSRafael Auler 
238a34c753fSRafael Auler static cl::list<std::string>
239a34c753fSRafael Auler SpecializeMemcpy1("memcpy1-spec",
240a34c753fSRafael Auler   cl::desc("list of functions with call sites for which to specialize memcpy() "
241a34c753fSRafael Auler            "for size 1"),
242a34c753fSRafael Auler   cl::value_desc("func1,func2:cs1:cs2,func3:cs1,..."),
243330c8e42SMaksim Panchenko   cl::ZeroOrMore, cl::cat(BoltOptCategory));
244330c8e42SMaksim Panchenko 
24536c7d79dSFangrui Song static cl::opt<bool> Stoke("stoke", cl::desc("turn on the stoke analysis"),
24636c7d79dSFangrui Song                            cl::cat(BoltOptCategory));
247330c8e42SMaksim Panchenko 
24836c7d79dSFangrui Song static cl::opt<bool> StringOps(
24936c7d79dSFangrui Song     "inline-memcpy",
250330c8e42SMaksim Panchenko     cl::desc("inline memcpy using 'rep movsb' instruction (X86-only)"),
25136c7d79dSFangrui Song     cl::cat(BoltOptCategory));
252a34c753fSRafael Auler 
25336c7d79dSFangrui Song static cl::opt<bool> StripRepRet(
25436c7d79dSFangrui Song     "strip-rep-ret",
255a34c753fSRafael Auler     cl::desc("strip 'repz' prefix from 'repz retq' sequence (on by default)"),
25636c7d79dSFangrui Song     cl::init(true), cl::cat(BoltOptCategory));
257a34c753fSRafael Auler 
25836c7d79dSFangrui Song static cl::opt<bool> VerifyCFG("verify-cfg",
259a34c753fSRafael Auler                                cl::desc("verify the CFG after every pass"),
26036c7d79dSFangrui Song                                cl::Hidden, cl::cat(BoltOptCategory));
261a34c753fSRafael Auler 
262b92436efSFangrui Song static cl::opt<bool> ThreeWayBranchFlag("three-way-branch",
263330c8e42SMaksim Panchenko                                         cl::desc("reorder three way branches"),
264b92436efSFangrui Song                                         cl::ReallyHidden,
265b92436efSFangrui Song                                         cl::cat(BoltOptCategory));
266a34c753fSRafael Auler 
267687e4af1SAmir Ayupov static cl::opt<bool> CMOVConversionFlag("cmov-conversion",
268687e4af1SAmir Ayupov                                         cl::desc("fold jcc+mov into cmov"),
269b92436efSFangrui Song                                         cl::ReallyHidden,
270687e4af1SAmir Ayupov                                         cl::cat(BoltOptCategory));
271687e4af1SAmir Ayupov 
272b686600aSDaniel Hill static cl::opt<bool> ShortenInstructions("shorten-instructions",
273b686600aSDaniel Hill                                          cl::desc("shorten instructions"),
274b686600aSDaniel Hill                                          cl::init(true),
275b686600aSDaniel Hill                                          cl::cat(BoltOptCategory));
276a34c753fSRafael Auler } // namespace opts
277a34c753fSRafael Auler 
278a34c753fSRafael Auler namespace llvm {
279a34c753fSRafael Auler namespace bolt {
280a34c753fSRafael Auler 
281a34c753fSRafael Auler using namespace opts;
282a34c753fSRafael Auler 
28340c2e0faSMaksim Panchenko const char BinaryFunctionPassManager::TimerGroupName[] = "passman";
284a34c753fSRafael Auler const char BinaryFunctionPassManager::TimerGroupDesc[] =
285a34c753fSRafael Auler     "Binary Function Pass Manager";
286a34c753fSRafael Auler 
28713d60ce2SAmir Ayupov Error BinaryFunctionPassManager::runPasses() {
288a34c753fSRafael Auler   auto &BFs = BC.getBinaryFunctions();
289a34c753fSRafael Auler   for (size_t PassIdx = 0; PassIdx < Passes.size(); PassIdx++) {
290a34c753fSRafael Auler     const std::pair<const bool, std::unique_ptr<BinaryFunctionPass>>
291a34c753fSRafael Auler         &OptPassPair = Passes[PassIdx];
292a34c753fSRafael Auler     if (!OptPassPair.first)
293a34c753fSRafael Auler       continue;
294a34c753fSRafael Auler 
295a34c753fSRafael Auler     const std::unique_ptr<BinaryFunctionPass> &Pass = OptPassPair.second;
296a34c753fSRafael Auler     std::string PassIdName =
297a34c753fSRafael Auler         formatv("{0:2}_{1}", PassIdx, Pass->getName()).str();
298a34c753fSRafael Auler 
299ee0e9ccbSMaksim Panchenko     if (opts::Verbosity > 0)
30052cf0711SAmir Ayupov       BC.outs() << "BOLT-INFO: Starting pass: " << Pass->getName() << "\n";
301a34c753fSRafael Auler 
302a34c753fSRafael Auler     NamedRegionTimer T(Pass->getName(), Pass->getName(), TimerGroupName,
303a34c753fSRafael Auler                        TimerGroupDesc, TimeOpts);
304a34c753fSRafael Auler 
30513d60ce2SAmir Ayupov     Error E = Error::success();
30613d60ce2SAmir Ayupov     callWithDynoStats(
30752cf0711SAmir Ayupov         BC.outs(),
30813d60ce2SAmir Ayupov         [this, &E, &Pass] {
30913d60ce2SAmir Ayupov           E = joinErrors(std::move(E), Pass->runOnFunctions(BC));
31013d60ce2SAmir Ayupov         },
311a5f3d1a8SAmir Ayupov         BFs, Pass->getName(), opts::DynoStatsAll, BC.isAArch64());
31213d60ce2SAmir Ayupov     if (E)
31313d60ce2SAmir Ayupov       return Error(std::move(E));
314a34c753fSRafael Auler 
315a34c753fSRafael Auler     if (opts::VerifyCFG &&
316a34c753fSRafael Auler         !std::accumulate(
31740c2e0faSMaksim Panchenko             BFs.begin(), BFs.end(), true,
318a34c753fSRafael Auler             [](const bool Valid,
319a34c753fSRafael Auler                const std::pair<const uint64_t, BinaryFunction> &It) {
320a34c753fSRafael Auler               return Valid && It.second.validateCFG();
321a34c753fSRafael Auler             })) {
32213d60ce2SAmir Ayupov       return createFatalBOLTError(
32313d60ce2SAmir Ayupov           Twine("BOLT-ERROR: Invalid CFG detected after pass ") +
32413d60ce2SAmir Ayupov           Twine(Pass->getName()) + Twine("\n"));
325a34c753fSRafael Auler     }
326a34c753fSRafael Auler 
327ee0e9ccbSMaksim Panchenko     if (opts::Verbosity > 0)
32852cf0711SAmir Ayupov       BC.outs() << "BOLT-INFO: Finished pass: " << Pass->getName() << "\n";
329a34c753fSRafael Auler 
330a34c753fSRafael Auler     if (!opts::PrintAll && !opts::DumpDotAll && !Pass->printPass())
331a34c753fSRafael Auler       continue;
332a34c753fSRafael Auler 
333a34c753fSRafael Auler     const std::string Message = std::string("after ") + Pass->getName();
334a34c753fSRafael Auler 
335a34c753fSRafael Auler     for (auto &It : BFs) {
336ee0e9ccbSMaksim Panchenko       BinaryFunction &Function = It.second;
337a34c753fSRafael Auler 
338a34c753fSRafael Auler       if (!Pass->shouldPrint(Function))
339a34c753fSRafael Auler         continue;
340a34c753fSRafael Auler 
34152cf0711SAmir Ayupov       Function.print(BC.outs(), Message);
342a34c753fSRafael Auler 
343a34c753fSRafael Auler       if (opts::DumpDotAll)
344a34c753fSRafael Auler         Function.dumpGraphForPass(PassIdName);
345a34c753fSRafael Auler     }
346a34c753fSRafael Auler   }
34713d60ce2SAmir Ayupov   return Error::success();
348a34c753fSRafael Auler }
349a34c753fSRafael Auler 
35013d60ce2SAmir Ayupov Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
351a34c753fSRafael Auler   BinaryFunctionPassManager Manager(BC);
352a34c753fSRafael Auler 
353f3dc732bSAmir Ayupov   Manager.registerPass(
354f3dc732bSAmir Ayupov       std::make_unique<EstimateEdgeCounts>(PrintEstimateEdgeCounts));
355f3dc732bSAmir Ayupov 
356a38f0157SAmir Ayupov   Manager.registerPass(std::make_unique<DynoStatsSetPass>());
357a34c753fSRafael Auler 
358443f1b4fSRafael Auler   Manager.registerPass(std::make_unique<AsmDumpPass>(),
359443f1b4fSRafael Auler                        opts::AsmDump.getNumOccurrences());
360443f1b4fSRafael Auler 
36117ed8f29SVladislav Khmelevsky   if (BC.isAArch64()) {
36217ed8f29SVladislav Khmelevsky     Manager.registerPass(std::make_unique<FixRelaxations>(PrintFixRelaxations));
36317ed8f29SVladislav Khmelevsky 
36435efe1d8SVladislav Khmelevsky     Manager.registerPass(
36535efe1d8SVladislav Khmelevsky         std::make_unique<VeneerElimination>(PrintVeneerElimination));
36617ed8f29SVladislav Khmelevsky   }
36735efe1d8SVladislav Khmelevsky 
368f8730293SJob Noorman   if (BC.isRISCV()) {
369f8730293SJob Noorman     Manager.registerPass(
370f8730293SJob Noorman         std::make_unique<FixRISCVCallsPass>(PrintFixRISCVCalls));
371f8730293SJob Noorman   }
372f8730293SJob Noorman 
373a34c753fSRafael Auler   // Here we manage dependencies/order manually, since passes are run in the
374a34c753fSRafael Auler   // order they're registered.
375a34c753fSRafael Auler 
376a34c753fSRafael Auler   // Run this pass first to use stats for the original functions.
3775fb59e74SAmir Ayupov   Manager.registerPass(std::make_unique<PrintProgramStats>());
378a34c753fSRafael Auler 
379a34c753fSRafael Auler   if (opts::PrintProfileStats)
380a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint));
381a34c753fSRafael Auler 
3824cab01f0SShatianWang   Manager.registerPass(std::make_unique<PrintContinuityStats>(NeverPrint));
3834cab01f0SShatianWang 
384a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ValidateInternalCalls>(NeverPrint));
385a34c753fSRafael Auler 
3864f158995SRafael Auler   Manager.registerPass(std::make_unique<ValidateMemRefs>(NeverPrint));
3874f158995SRafael Auler 
3884f158995SRafael Auler   if (opts::Instrument)
3894f158995SRafael Auler     Manager.registerPass(std::make_unique<Instrumentation>(NeverPrint));
3901fb18619SAlexey Moksyakov   else if (opts::Hugify)
3911fb18619SAlexey Moksyakov     Manager.registerPass(std::make_unique<HugePage>(NeverPrint));
3924f158995SRafael Auler 
393b686600aSDaniel Hill   Manager.registerPass(std::make_unique<ShortenInstructions>(NeverPrint),
394b686600aSDaniel Hill                        opts::ShortenInstructions);
39508f56926SVladislav Khmelevsky 
396e823136dSMaksim Panchenko   Manager.registerPass(std::make_unique<RemoveNops>(NeverPrint),
397e823136dSMaksim Panchenko                        !opts::KeepNops);
39808f56926SVladislav Khmelevsky 
399cbf530bfSMaksim Panchenko   Manager.registerPass(std::make_unique<NormalizeCFG>(PrintNormalized));
400cbf530bfSMaksim Panchenko 
401e2d48239SNathan Sidwell   if (BC.isX86())
402a34c753fSRafael Auler     Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
403a34c753fSRafael Auler                          opts::StripRepRet);
404a34c753fSRafael Auler 
405a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
406*3c357a49SAlexander Yermolovich                        opts::ICF != IdenticalCodeFolding::ICFLevel::None);
407a34c753fSRafael Auler 
408a34c753fSRafael Auler   Manager.registerPass(
409a34c753fSRafael Auler       std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
410a34c753fSRafael Auler       !opts::SpecializeMemcpy1.empty());
411a34c753fSRafael Auler 
412a34c753fSRafael Auler   Manager.registerPass(std::make_unique<InlineMemcpy>(NeverPrint),
413a34c753fSRafael Auler                        opts::StringOps);
414a34c753fSRafael Auler 
415a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IndirectCallPromotion>(PrintICP));
416a34c753fSRafael Auler 
417a34c753fSRafael Auler   Manager.registerPass(
418a34c753fSRafael Auler       std::make_unique<JTFootprintReduction>(PrintJTFootprintReduction),
419a34c753fSRafael Auler       opts::JTFootprintReductionFlag);
420a34c753fSRafael Auler 
421a34c753fSRafael Auler   Manager.registerPass(
422a34c753fSRafael Auler       std::make_unique<SimplifyRODataLoads>(PrintSimplifyROLoads),
423a34c753fSRafael Auler       opts::SimplifyRODataLoads);
424a34c753fSRafael Auler 
425a34c753fSRafael Auler   Manager.registerPass(std::make_unique<RegReAssign>(PrintRegReAssign),
426a34c753fSRafael Auler                        opts::RegReAssign);
427a34c753fSRafael Auler 
428a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Inliner>(PrintInline));
429a34c753fSRafael Auler 
430a34c753fSRafael Auler   Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
431*3c357a49SAlexander Yermolovich                        opts::ICF != IdenticalCodeFolding::ICFLevel::None);
432a34c753fSRafael Auler 
433a34c753fSRafael Auler   Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
434a34c753fSRafael Auler 
435a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ThreeWayBranch>(),
436a34c753fSRafael Auler                        opts::ThreeWayBranchFlag);
437a34c753fSRafael Auler 
438a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderBasicBlocks>(PrintReordered));
439a34c753fSRafael Auler 
44040c2e0faSMaksim Panchenko   Manager.registerPass(std::make_unique<EliminateUnreachableBlocks>(PrintUCE),
441a34c753fSRafael Auler                        opts::EliminateUnreachable);
442a34c753fSRafael Auler 
443a34c753fSRafael Auler   Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
444a34c753fSRafael Auler 
445a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LoopInversionPass>());
446a34c753fSRafael Auler 
4475904836bSspupyrev   Manager.registerPass(std::make_unique<TailDuplication>());
448a34c753fSRafael Auler 
449687e4af1SAmir Ayupov   Manager.registerPass(std::make_unique<CMOVConversion>(),
450687e4af1SAmir Ayupov                        opts::CMOVConversionFlag);
451687e4af1SAmir Ayupov 
452a34c753fSRafael Auler   // This pass syncs local branches with CFG. If any of the following
453a34c753fSRafael Auler   // passes breaks the sync - they either need to re-run the pass or
454a34c753fSRafael Auler   // fix branches consistency internally.
455a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FixupBranches>(PrintAfterBranchFixup));
456a34c753fSRafael Auler 
457a34c753fSRafael Auler   // This pass should come close to last since it uses the estimated hot
458a34c753fSRafael Auler   // size of a function to determine the order.  It should definitely
459a34c753fSRafael Auler   // also happen after any changes to the call graph are made, e.g. inlining.
460a34c753fSRafael Auler   Manager.registerPass(
461a34c753fSRafael Auler       std::make_unique<ReorderFunctions>(PrintReorderedFunctions));
462a34c753fSRafael Auler 
463076bd22fSShatianWang   // This is the second run of the SplitFunctions pass required by certain
464076bd22fSShatianWang   // splitting strategies (e.g. cdsplit). Running the SplitFunctions pass again
465076bd22fSShatianWang   // after ReorderFunctions allows the finalized function order to be utilized
466076bd22fSShatianWang   // to make more sophisticated splitting decisions, like hot-warm-cold
467076bd22fSShatianWang   // splitting.
468076bd22fSShatianWang   Manager.registerPass(std::make_unique<SplitFunctions>(PrintSplit));
469076bd22fSShatianWang 
470a34c753fSRafael Auler   // Print final dyno stats right while CFG and instruction analysis are intact.
471a38f0157SAmir Ayupov   Manager.registerPass(std::make_unique<DynoStatsPrintPass>(
472a38f0157SAmir Ayupov                            "after all optimizations before SCTC and FOP"),
473194b164eSAmir Ayupov                        opts::PrintDynoStats || opts::DynoStatsAll);
474a34c753fSRafael Auler 
475a34c753fSRafael Auler   // Add the StokeInfo pass, which extract functions for stoke optimization and
476a34c753fSRafael Auler   // get the liveness information for them
477a34c753fSRafael Auler   Manager.registerPass(std::make_unique<StokeInfo>(PrintStoke), opts::Stoke);
478a34c753fSRafael Auler 
479a34c753fSRafael Auler   // This pass introduces conditional jumps into external functions.
480a34c753fSRafael Auler   // Between extending CFG to support this and isolating this pass we chose
481a34c753fSRafael Auler   // the latter. Thus this pass will do double jump removal and unreachable
482a34c753fSRafael Auler   // code elimination if necessary and won't rely on peepholes/UCE for these
483a34c753fSRafael Auler   // optimizations.
484a34c753fSRafael Auler   // More generally this pass should be the last optimization pass that
485a34c753fSRafael Auler   // modifies branches/control flow.  This pass is run after function
486a34c753fSRafael Auler   // reordering so that it can tell whether calls are forward/backward
487a34c753fSRafael Auler   // accurately.
488a34c753fSRafael Auler   Manager.registerPass(
489a34c753fSRafael Auler       std::make_unique<SimplifyConditionalTailCalls>(PrintSCTC),
490a34c753fSRafael Auler       opts::SimplifyConditionalTailCalls);
491a34c753fSRafael Auler 
492a34c753fSRafael Auler   Manager.registerPass(std::make_unique<Peepholes>(PrintPeepholes));
493a34c753fSRafael Auler 
494a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AlignerPass>());
495a34c753fSRafael Auler 
496a34c753fSRafael Auler   // Perform reordering on data contained in one or more sections using
497a34c753fSRafael Auler   // memory profiling data.
498a34c753fSRafael Auler   Manager.registerPass(std::make_unique<ReorderData>());
499a34c753fSRafael Auler 
500a34c753fSRafael Auler   if (BC.isAArch64()) {
5012df48fa7SPaschalis Mpeis     Manager.registerPass(
5022df48fa7SPaschalis Mpeis         std::make_unique<ADRRelaxationPass>(PrintAdrRelaxation));
503445023f1SVladislav Khmelevsky 
504a34c753fSRafael Auler     // Tighten branches according to offset differences between branch and
505a34c753fSRafael Auler     // targets. No extra instructions after this pass, otherwise we may have
506a34c753fSRafael Auler     // relocations out of range and crash during linking.
507a34c753fSRafael Auler     Manager.registerPass(std::make_unique<LongJmpPass>(PrintLongJmp));
508a34c753fSRafael Auler   }
509a34c753fSRafael Auler 
510a34c753fSRafael Auler   // This pass should always run last.*
511a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FinalizeFunctions>(PrintFinalized));
512a34c753fSRafael Auler 
513a34c753fSRafael Auler   // FrameOptimizer has an implicit dependency on FinalizeFunctions.
514a34c753fSRafael Auler   // FrameOptimizer move values around and needs to update CFIs. To do this, it
515a34c753fSRafael Auler   // must read CFI, interpret it and rewrite it, so CFIs need to be correctly
516a34c753fSRafael Auler   // placed according to the final layout.
517a34c753fSRafael Auler   Manager.registerPass(std::make_unique<FrameOptimizerPass>(PrintFOP));
518a34c753fSRafael Auler 
519a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AllocCombinerPass>(PrintFOP));
520a34c753fSRafael Auler 
521a34c753fSRafael Auler   Manager.registerPass(
522a34c753fSRafael Auler       std::make_unique<RetpolineInsertion>(PrintRetpolineInsertion));
523a34c753fSRafael Auler 
524a34c753fSRafael Auler   // Assign each function an output section.
525a34c753fSRafael Auler   Manager.registerPass(std::make_unique<AssignSections>());
526a34c753fSRafael Auler 
527a34c753fSRafael Auler   // Patch original function entries
528a34c753fSRafael Auler   if (BC.HasRelocations)
529a34c753fSRafael Auler     Manager.registerPass(std::make_unique<PatchEntries>());
530a34c753fSRafael Auler 
531a34c753fSRafael Auler   // This pass turns tail calls into jumps which makes them invisible to
532a34c753fSRafael Auler   // function reordering. It's unsafe to use any CFG or instruction analysis
533a34c753fSRafael Auler   // after this point.
534a34c753fSRafael Auler   Manager.registerPass(
535a34c753fSRafael Auler       std::make_unique<InstructionLowering>(PrintAfterLowering));
536a34c753fSRafael Auler 
537a34c753fSRafael Auler   // In non-relocation mode, mark functions that do not fit into their original
538a34c753fSRafael Auler   // space as non-simple if we have to (e.g. for correct debug info update).
539a34c753fSRafael Auler   // NOTE: this pass depends on finalized code.
540a34c753fSRafael Auler   if (!BC.HasRelocations)
541a34c753fSRafael Auler     Manager.registerPass(std::make_unique<CheckLargeFunctions>(NeverPrint));
542a34c753fSRafael Auler 
543a34c753fSRafael Auler   Manager.registerPass(std::make_unique<LowerAnnotations>(NeverPrint));
544a34c753fSRafael Auler 
54562a2feffSRafael Auler   // Check for dirty state of MCSymbols caused by running calculateEmittedSize
54662a2feffSRafael Auler   // in parallel and restore them
54762a2feffSRafael Auler   Manager.registerPass(std::make_unique<CleanMCState>(NeverPrint));
54862a2feffSRafael Auler 
54913d60ce2SAmir Ayupov   return Manager.runPasses();
550a34c753fSRafael Auler }
551a34c753fSRafael Auler 
552a34c753fSRafael Auler } // namespace bolt
553a34c753fSRafael Auler } // namespace llvm
554