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