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