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