1 //===- bolt/Passes/BinaryPasses.cpp - Binary-level passes -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements multiple passes for binary optimization and analysis.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "bolt/Passes/BinaryPasses.h"
14 #include "bolt/Core/ParallelUtilities.h"
15 #include "bolt/Passes/ReorderAlgorithm.h"
16 #include "bolt/Passes/ReorderFunctions.h"
17 #include "llvm/Support/CommandLine.h"
18 
19 #include <numeric>
20 #include <vector>
21 
22 #define DEBUG_TYPE "bolt-opts"
23 
24 using namespace llvm;
25 using namespace bolt;
26 
27 namespace {
28 
29 const char *dynoStatsOptName(const bolt::DynoStats::Category C) {
30   if (C == bolt::DynoStats::FIRST_DYNO_STAT)
31     return "none";
32   else if (C == bolt::DynoStats::LAST_DYNO_STAT)
33     return "all";
34 
35   static std::string OptNames[bolt::DynoStats::LAST_DYNO_STAT + 1];
36 
37   OptNames[C] = bolt::DynoStats::Description(C);
38 
39   std::replace(OptNames[C].begin(), OptNames[C].end(), ' ', '-');
40 
41   return OptNames[C].c_str();
42 }
43 
44 const char *dynoStatsOptDesc(const bolt::DynoStats::Category C) {
45   if (C == bolt::DynoStats::FIRST_DYNO_STAT)
46     return "unsorted";
47   else if (C == bolt::DynoStats::LAST_DYNO_STAT)
48     return "sorted by all stats";
49 
50   return bolt::DynoStats::Description(C);
51 }
52 
53 }
54 
55 namespace opts {
56 
57 extern cl::OptionCategory BoltCategory;
58 extern cl::OptionCategory BoltOptCategory;
59 
60 extern cl::opt<bolt::MacroFusionType> AlignMacroOpFusion;
61 extern cl::opt<unsigned> Verbosity;
62 extern cl::opt<bool> EnableBAT;
63 extern cl::opt<unsigned> ExecutionCountThreshold;
64 extern cl::opt<bool> UpdateDebugSections;
65 extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
66 
67 enum DynoStatsSortOrder : char {
68   Ascending,
69   Descending
70 };
71 
72 static cl::opt<DynoStatsSortOrder>
73 DynoStatsSortOrderOpt("print-sorted-by-order",
74   cl::desc("use ascending or descending order when printing functions "
75            "ordered by dyno stats"),
76   cl::ZeroOrMore,
77   cl::init(DynoStatsSortOrder::Descending),
78   cl::cat(BoltOptCategory));
79 
80 cl::list<std::string>
81 HotTextMoveSections("hot-text-move-sections",
82   cl::desc("list of sections containing functions used for hugifying hot text. "
83            "BOLT makes sure these functions are not placed on the same page as "
84            "the hot text. (default=\'.stub,.mover\')."),
85   cl::value_desc("sec1,sec2,sec3,..."),
86   cl::CommaSeparated,
87   cl::ZeroOrMore,
88   cl::cat(BoltCategory));
89 
90 bool isHotTextMover(const BinaryFunction &Function) {
91   for (std::string &SectionName : opts::HotTextMoveSections) {
92     if (Function.getOriginSectionName() &&
93         *Function.getOriginSectionName() == SectionName)
94       return true;
95   }
96 
97   return false;
98 }
99 
100 static cl::opt<bool>
101 MinBranchClusters("min-branch-clusters",
102   cl::desc("use a modified clustering algorithm geared towards minimizing "
103            "branches"),
104   cl::ZeroOrMore,
105   cl::Hidden,
106   cl::cat(BoltOptCategory));
107 
108 static cl::list<Peepholes::PeepholeOpts> Peepholes(
109     "peepholes", cl::CommaSeparated, cl::desc("enable peephole optimizations"),
110     cl::value_desc("opt1,opt2,opt3,..."),
111     cl::values(clEnumValN(Peepholes::PEEP_NONE, "none", "disable peepholes"),
112                clEnumValN(Peepholes::PEEP_DOUBLE_JUMPS, "double-jumps",
113                           "remove double jumps when able"),
114                clEnumValN(Peepholes::PEEP_TAILCALL_TRAPS, "tailcall-traps",
115                           "insert tail call traps"),
116                clEnumValN(Peepholes::PEEP_USELESS_BRANCHES, "useless-branches",
117                           "remove useless conditional branches"),
118                clEnumValN(Peepholes::PEEP_ALL, "all",
119                           "enable all peephole optimizations")),
120     cl::ZeroOrMore, cl::cat(BoltOptCategory));
121 
122 static cl::opt<unsigned>
123 PrintFuncStat("print-function-statistics",
124   cl::desc("print statistics about basic block ordering"),
125   cl::init(0),
126   cl::ZeroOrMore,
127   cl::cat(BoltOptCategory));
128 
129 static cl::list<bolt::DynoStats::Category>
130 PrintSortedBy("print-sorted-by",
131   cl::CommaSeparated,
132   cl::desc("print functions sorted by order of dyno stats"),
133   cl::value_desc("key1,key2,key3,..."),
134   cl::values(
135 #define D(name, ...)                                        \
136     clEnumValN(bolt::DynoStats::name,                     \
137                dynoStatsOptName(bolt::DynoStats::name),   \
138                dynoStatsOptDesc(bolt::DynoStats::name)),
139     DYNO_STATS
140 #undef D
141     clEnumValN(0xffff, ".", ".")
142     ),
143   cl::ZeroOrMore,
144   cl::cat(BoltOptCategory));
145 
146 static cl::opt<bool>
147 PrintUnknown("print-unknown",
148   cl::desc("print names of functions with unknown control flow"),
149   cl::init(false),
150   cl::ZeroOrMore,
151   cl::cat(BoltCategory),
152   cl::Hidden);
153 
154 static cl::opt<bool>
155 PrintUnknownCFG("print-unknown-cfg",
156   cl::desc("dump CFG of functions with unknown control flow"),
157   cl::init(false),
158   cl::ZeroOrMore,
159   cl::cat(BoltCategory),
160   cl::ReallyHidden);
161 
162 cl::opt<bolt::ReorderBasicBlocks::LayoutType> ReorderBlocks(
163     "reorder-blocks", cl::desc("change layout of basic blocks in a function"),
164     cl::init(bolt::ReorderBasicBlocks::LT_NONE),
165     cl::values(
166         clEnumValN(bolt::ReorderBasicBlocks::LT_NONE, "none",
167                    "do not reorder basic blocks"),
168         clEnumValN(bolt::ReorderBasicBlocks::LT_REVERSE, "reverse",
169                    "layout blocks in reverse order"),
170         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE, "normal",
171                    "perform optimal layout based on profile"),
172         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_BRANCH,
173                    "branch-predictor",
174                    "perform optimal layout prioritizing branch "
175                    "predictions"),
176         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE, "cache",
177                    "perform optimal layout prioritizing I-cache "
178                    "behavior"),
179         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE_PLUS, "cache+",
180                    "perform layout optimizing I-cache behavior"),
181         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_EXT_TSP, "ext-tsp",
182                    "perform layout optimizing I-cache behavior"),
183         clEnumValN(bolt::ReorderBasicBlocks::LT_OPTIMIZE_SHUFFLE,
184                    "cluster-shuffle", "perform random layout of clusters")),
185     cl::ZeroOrMore, cl::cat(BoltOptCategory),
186     cl::callback([](const bolt::ReorderBasicBlocks::LayoutType &option) {
187       if (option == bolt::ReorderBasicBlocks::LT_OPTIMIZE_CACHE_PLUS) {
188         WithColor::warning()
189             << "'-reorder-blocks=cache+' is deprecated, "
190             << "please use '-reorder-blocks=ext-tsp' instead\n";
191         ReorderBlocks = bolt::ReorderBasicBlocks::LT_OPTIMIZE_EXT_TSP;
192       }
193     }));
194 
195 static cl::opt<unsigned>
196 ReportBadLayout("report-bad-layout",
197   cl::desc("print top <uint> functions with suboptimal code layout on input"),
198   cl::init(0),
199   cl::ZeroOrMore,
200   cl::Hidden,
201   cl::cat(BoltOptCategory));
202 
203 static cl::opt<bool>
204 ReportStaleFuncs("report-stale",
205   cl::desc("print the list of functions with stale profile"),
206   cl::init(false),
207   cl::ZeroOrMore,
208   cl::Hidden,
209   cl::cat(BoltOptCategory));
210 
211 enum SctcModes : char {
212   SctcAlways,
213   SctcPreserveDirection,
214   SctcHeuristic
215 };
216 
217 static cl::opt<SctcModes>
218 SctcMode("sctc-mode",
219   cl::desc("mode for simplify conditional tail calls"),
220   cl::init(SctcAlways),
221   cl::values(clEnumValN(SctcAlways, "always", "always perform sctc"),
222     clEnumValN(SctcPreserveDirection,
223       "preserve",
224       "only perform sctc when branch direction is "
225       "preserved"),
226     clEnumValN(SctcHeuristic,
227       "heuristic",
228       "use branch prediction data to control sctc")),
229   cl::ZeroOrMore,
230   cl::cat(BoltOptCategory));
231 
232 static cl::opt<unsigned>
233 StaleThreshold("stale-threshold",
234     cl::desc(
235       "maximum percentage of stale functions to tolerate (default: 100)"),
236     cl::init(100),
237     cl::Hidden,
238     cl::cat(BoltOptCategory));
239 
240 static cl::opt<unsigned>
241 TSPThreshold("tsp-threshold",
242   cl::desc("maximum number of hot basic blocks in a function for which to use "
243            "a precise TSP solution while re-ordering basic blocks"),
244   cl::init(10),
245   cl::ZeroOrMore,
246   cl::Hidden,
247   cl::cat(BoltOptCategory));
248 
249 static cl::opt<unsigned>
250 TopCalledLimit("top-called-limit",
251   cl::desc("maximum number of functions to print in top called "
252            "functions section"),
253   cl::init(100),
254   cl::ZeroOrMore,
255   cl::Hidden,
256   cl::cat(BoltCategory));
257 
258 } // namespace opts
259 
260 namespace llvm {
261 namespace bolt {
262 
263 bool BinaryFunctionPass::shouldOptimize(const BinaryFunction &BF) const {
264   return BF.isSimple() && BF.getState() == BinaryFunction::State::CFG &&
265          !BF.isIgnored();
266 }
267 
268 bool BinaryFunctionPass::shouldPrint(const BinaryFunction &BF) const {
269   return BF.isSimple() && !BF.isIgnored();
270 }
271 
272 void NormalizeCFG::runOnFunction(BinaryFunction &BF) {
273   uint64_t NumRemoved = 0;
274   uint64_t NumDuplicateEdges = 0;
275   uint64_t NeedsFixBranches = 0;
276   for (BinaryBasicBlock &BB : BF) {
277     if (!BB.empty())
278       continue;
279 
280     if (BB.isEntryPoint() || BB.isLandingPad())
281       continue;
282 
283     // Handle a dangling empty block.
284     if (BB.succ_size() == 0) {
285       // If an empty dangling basic block has a predecessor, it could be a
286       // result of codegen for __builtin_unreachable. In such case, do not
287       // remove the block.
288       if (BB.pred_size() == 0) {
289         BB.markValid(false);
290         ++NumRemoved;
291       }
292       continue;
293     }
294 
295     // The block should have just one successor.
296     BinaryBasicBlock *Successor = BB.getSuccessor();
297     assert(Successor && "invalid CFG encountered");
298 
299     // Redirect all predecessors to the successor block.
300     while (!BB.pred_empty()) {
301       BinaryBasicBlock *Predecessor = *BB.pred_begin();
302       if (Predecessor->hasJumpTable())
303         break;
304 
305       if (Predecessor == Successor)
306         break;
307 
308       BinaryBasicBlock::BinaryBranchInfo &BI = Predecessor->getBranchInfo(BB);
309       Predecessor->replaceSuccessor(&BB, Successor, BI.Count,
310                                     BI.MispredictedCount);
311       // We need to fix branches even if we failed to replace all successors
312       // and remove the block.
313       NeedsFixBranches = true;
314     }
315 
316     if (BB.pred_empty()) {
317       BB.removeAllSuccessors();
318       BB.markValid(false);
319       ++NumRemoved;
320     }
321   }
322 
323   if (NumRemoved)
324     BF.eraseInvalidBBs();
325 
326   // Check for duplicate successors. Do it after the empty block elimination as
327   // we can get more duplicate successors.
328   for (BinaryBasicBlock &BB : BF)
329     if (!BB.hasJumpTable() && BB.succ_size() == 2 &&
330         BB.getConditionalSuccessor(false) == BB.getConditionalSuccessor(true))
331       ++NumDuplicateEdges;
332 
333   // fixBranches() will get rid of duplicate edges and update jump instructions.
334   if (NumDuplicateEdges || NeedsFixBranches)
335     BF.fixBranches();
336 
337   NumDuplicateEdgesMerged += NumDuplicateEdges;
338   NumBlocksRemoved += NumRemoved;
339 }
340 
341 void NormalizeCFG::runOnFunctions(BinaryContext &BC) {
342   ParallelUtilities::runOnEachFunction(
343       BC, ParallelUtilities::SchedulingPolicy::SP_BB_LINEAR,
344       [&](BinaryFunction &BF) { runOnFunction(BF); },
345       [&](const BinaryFunction &BF) { return !shouldOptimize(BF); },
346       "NormalizeCFG");
347   if (NumBlocksRemoved)
348     outs() << "BOLT-INFO: removed " << NumBlocksRemoved << " empty block"
349            << (NumBlocksRemoved == 1 ? "" : "s") << '\n';
350   if (NumDuplicateEdgesMerged)
351     outs() << "BOLT-INFO: merged " << NumDuplicateEdgesMerged
352            << " duplicate CFG edge" << (NumDuplicateEdgesMerged == 1 ? "" : "s")
353            << '\n';
354 }
355 
356 void EliminateUnreachableBlocks::runOnFunction(BinaryFunction &Function) {
357   if (Function.layout_size() > 0) {
358     unsigned Count;
359     uint64_t Bytes;
360     Function.markUnreachableBlocks();
361     LLVM_DEBUG({
362       for (BinaryBasicBlock *BB : Function.layout()) {
363         if (!BB->isValid()) {
364           dbgs() << "BOLT-INFO: UCE found unreachable block " << BB->getName()
365                  << " in function " << Function << "\n";
366           Function.dump();
367         }
368       }
369     });
370     std::tie(Count, Bytes) = Function.eraseInvalidBBs();
371     DeletedBlocks += Count;
372     DeletedBytes += Bytes;
373     if (Count) {
374       Modified.insert(&Function);
375       if (opts::Verbosity > 0)
376         outs() << "BOLT-INFO: Removed " << Count
377                << " dead basic block(s) accounting for " << Bytes
378                << " bytes in function " << Function << '\n';
379     }
380   }
381 }
382 
383 void EliminateUnreachableBlocks::runOnFunctions(BinaryContext &BC) {
384   for (auto &It : BC.getBinaryFunctions()) {
385     BinaryFunction &Function = It.second;
386     if (shouldOptimize(Function))
387       runOnFunction(Function);
388   }
389 
390   outs() << "BOLT-INFO: UCE removed " << DeletedBlocks << " blocks and "
391          << DeletedBytes << " bytes of code.\n";
392 }
393 
394 bool ReorderBasicBlocks::shouldPrint(const BinaryFunction &BF) const {
395   return (BinaryFunctionPass::shouldPrint(BF) &&
396           opts::ReorderBlocks != ReorderBasicBlocks::LT_NONE);
397 }
398 
399 bool ReorderBasicBlocks::shouldOptimize(const BinaryFunction &BF) const {
400   // Apply execution count threshold
401   if (BF.getKnownExecutionCount() < opts::ExecutionCountThreshold)
402     return false;
403 
404   return BinaryFunctionPass::shouldOptimize(BF);
405 }
406 
407 void ReorderBasicBlocks::runOnFunctions(BinaryContext &BC) {
408   if (opts::ReorderBlocks == ReorderBasicBlocks::LT_NONE)
409     return;
410 
411   std::atomic<uint64_t> ModifiedFuncCount{0};
412 
413   ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
414     modifyFunctionLayout(BF, opts::ReorderBlocks, opts::MinBranchClusters);
415     if (BF.hasLayoutChanged())
416       ++ModifiedFuncCount;
417   };
418 
419   ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
420     return !shouldOptimize(BF);
421   };
422 
423   ParallelUtilities::runOnEachFunction(
424       BC, ParallelUtilities::SchedulingPolicy::SP_BB_LINEAR, WorkFun, SkipFunc,
425       "ReorderBasicBlocks");
426 
427   outs() << "BOLT-INFO: basic block reordering modified layout of "
428          << format("%zu (%.2lf%%) functions\n", ModifiedFuncCount.load(),
429                    100.0 * ModifiedFuncCount.load() /
430                        BC.getBinaryFunctions().size());
431 
432   if (opts::PrintFuncStat > 0) {
433     raw_ostream &OS = outs();
434     // Copy all the values into vector in order to sort them
435     std::map<uint64_t, BinaryFunction &> ScoreMap;
436     auto &BFs = BC.getBinaryFunctions();
437     for (auto It = BFs.begin(); It != BFs.end(); ++It)
438       ScoreMap.insert(std::pair<uint64_t, BinaryFunction &>(
439           It->second.getFunctionScore(), It->second));
440 
441     OS << "\nBOLT-INFO: Printing Function Statistics:\n\n";
442     OS << "           There are " << BFs.size() << " functions in total. \n";
443     OS << "           Number of functions being modified: "
444        << ModifiedFuncCount.load() << "\n";
445     OS << "           User asks for detailed information on top "
446        << opts::PrintFuncStat << " functions. (Ranked by function score)"
447        << "\n\n";
448     uint64_t I = 0;
449     for (std::map<uint64_t, BinaryFunction &>::reverse_iterator Rit =
450              ScoreMap.rbegin();
451          Rit != ScoreMap.rend() && I < opts::PrintFuncStat; ++Rit, ++I) {
452       BinaryFunction &Function = Rit->second;
453 
454       OS << "           Information for function of top: " << (I + 1) << ": \n";
455       OS << "             Function Score is: " << Function.getFunctionScore()
456          << "\n";
457       OS << "             There are " << Function.size()
458          << " number of blocks in this function.\n";
459       OS << "             There are " << Function.getInstructionCount()
460          << " number of instructions in this function.\n";
461       OS << "             The edit distance for this function is: "
462          << Function.getEditDistance() << "\n\n";
463     }
464   }
465 }
466 
467 void ReorderBasicBlocks::modifyFunctionLayout(BinaryFunction &BF,
468                                               LayoutType Type,
469                                               bool MinBranchClusters) const {
470   if (BF.size() == 0 || Type == LT_NONE)
471     return;
472 
473   BinaryFunction::BasicBlockOrderType NewLayout;
474   std::unique_ptr<ReorderAlgorithm> Algo;
475 
476   // Cannot do optimal layout without profile.
477   if (Type != LT_REVERSE && !BF.hasValidProfile())
478     return;
479 
480   if (Type == LT_REVERSE) {
481     Algo.reset(new ReverseReorderAlgorithm());
482   } else if (BF.size() <= opts::TSPThreshold && Type != LT_OPTIMIZE_SHUFFLE) {
483     // Work on optimal solution if problem is small enough
484     LLVM_DEBUG(dbgs() << "finding optimal block layout for " << BF << "\n");
485     Algo.reset(new TSPReorderAlgorithm());
486   } else {
487     LLVM_DEBUG(dbgs() << "running block layout heuristics on " << BF << "\n");
488 
489     std::unique_ptr<ClusterAlgorithm> CAlgo;
490     if (MinBranchClusters)
491       CAlgo.reset(new MinBranchGreedyClusterAlgorithm());
492     else
493       CAlgo.reset(new PHGreedyClusterAlgorithm());
494 
495     switch (Type) {
496     case LT_OPTIMIZE:
497       Algo.reset(new OptimizeReorderAlgorithm(std::move(CAlgo)));
498       break;
499 
500     case LT_OPTIMIZE_BRANCH:
501       Algo.reset(new OptimizeBranchReorderAlgorithm(std::move(CAlgo)));
502       break;
503 
504     case LT_OPTIMIZE_CACHE:
505       Algo.reset(new OptimizeCacheReorderAlgorithm(std::move(CAlgo)));
506       break;
507 
508     case LT_OPTIMIZE_EXT_TSP:
509       Algo.reset(new ExtTSPReorderAlgorithm());
510       break;
511 
512     case LT_OPTIMIZE_SHUFFLE:
513       Algo.reset(new RandomClusterReorderAlgorithm(std::move(CAlgo)));
514       break;
515 
516     default:
517       llvm_unreachable("unexpected layout type");
518     }
519   }
520 
521   Algo->reorderBasicBlocks(BF, NewLayout);
522 
523   BF.updateBasicBlockLayout(NewLayout);
524 }
525 
526 void FixupBranches::runOnFunctions(BinaryContext &BC) {
527   for (auto &It : BC.getBinaryFunctions()) {
528     BinaryFunction &Function = It.second;
529     if (!BC.shouldEmit(Function) || !Function.isSimple())
530       continue;
531 
532     Function.fixBranches();
533   }
534 }
535 
536 void FinalizeFunctions::runOnFunctions(BinaryContext &BC) {
537   ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
538     if (!BF.finalizeCFIState()) {
539       if (BC.HasRelocations) {
540         errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF
541                << ". Exiting.\n";
542         exit(1);
543       }
544       BF.setSimple(false);
545       return;
546     }
547 
548     BF.setFinalized();
549 
550     // Update exception handling information.
551     BF.updateEHRanges();
552   };
553 
554   ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {
555     return !BC.shouldEmit(BF);
556   };
557 
558   ParallelUtilities::runOnEachFunction(
559       BC, ParallelUtilities::SchedulingPolicy::SP_CONSTANT, WorkFun,
560       SkipPredicate, "FinalizeFunctions");
561 }
562 
563 void CheckLargeFunctions::runOnFunctions(BinaryContext &BC) {
564   if (BC.HasRelocations)
565     return;
566 
567   if (!opts::UpdateDebugSections)
568     return;
569 
570   // If the function wouldn't fit, mark it as non-simple. Otherwise, we may emit
571   // incorrect debug info.
572   ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
573     uint64_t HotSize, ColdSize;
574     std::tie(HotSize, ColdSize) =
575         BC.calculateEmittedSize(BF, /*FixBranches=*/false);
576     if (HotSize > BF.getMaxSize())
577       BF.setSimple(false);
578   };
579 
580   ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
581     return !shouldOptimize(BF);
582   };
583 
584   ParallelUtilities::runOnEachFunction(
585       BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
586       SkipFunc, "CheckLargeFunctions");
587 }
588 
589 bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const {
590   // Unlike other passes, allow functions in non-CFG state.
591   return BF.isSimple() && !BF.isIgnored();
592 }
593 
594 void LowerAnnotations::runOnFunctions(BinaryContext &BC) {
595   std::vector<std::pair<MCInst *, uint32_t>> PreservedOffsetAnnotations;
596 
597   for (auto &It : BC.getBinaryFunctions()) {
598     BinaryFunction &BF = It.second;
599     int64_t CurrentGnuArgsSize = 0;
600 
601     // Have we crossed hot/cold border for split functions?
602     bool SeenCold = false;
603 
604     for (BinaryBasicBlock *BB : BF.layout()) {
605       if (BB->isCold() && !SeenCold) {
606         SeenCold = true;
607         CurrentGnuArgsSize = 0;
608       }
609 
610       // First convert GnuArgsSize annotations into CFIs. This may change instr
611       // pointers, so do it before recording ptrs for preserved annotations
612       if (BF.usesGnuArgsSize()) {
613         for (auto II = BB->begin(); II != BB->end(); ++II) {
614           if (!BC.MIB->isInvoke(*II))
615             continue;
616           const int64_t NewGnuArgsSize = BC.MIB->getGnuArgsSize(*II);
617           assert(NewGnuArgsSize >= 0 && "expected non-negative GNU_args_size");
618           if (NewGnuArgsSize != CurrentGnuArgsSize) {
619             auto InsertII = BF.addCFIInstruction(
620                 BB, II,
621                 MCCFIInstruction::createGnuArgsSize(nullptr, NewGnuArgsSize));
622             CurrentGnuArgsSize = NewGnuArgsSize;
623             II = std::next(InsertII);
624           }
625         }
626       }
627 
628       // Now record preserved annotations separately and then strip annotations.
629       for (auto II = BB->begin(); II != BB->end(); ++II) {
630         if (BF.requiresAddressTranslation() && BC.MIB->getOffset(*II))
631           PreservedOffsetAnnotations.emplace_back(&(*II),
632                                                   *BC.MIB->getOffset(*II));
633         BC.MIB->stripAnnotations(*II);
634       }
635     }
636   }
637   for (BinaryFunction *BF : BC.getInjectedBinaryFunctions())
638     for (BinaryBasicBlock &BB : *BF)
639       for (MCInst &Instruction : BB)
640         BC.MIB->stripAnnotations(Instruction);
641 
642   // Release all memory taken by annotations
643   BC.MIB->freeAnnotations();
644 
645   // Reinsert preserved annotations we need during code emission.
646   for (const std::pair<MCInst *, uint32_t> &Item : PreservedOffsetAnnotations)
647     BC.MIB->setOffset(*Item.first, Item.second);
648 }
649 
650 namespace {
651 
652 // This peephole fixes jump instructions that jump to another basic
653 // block with a single jump instruction, e.g.
654 //
655 // B0: ...
656 //     jmp  B1   (or jcc B1)
657 //
658 // B1: jmp  B2
659 //
660 // ->
661 //
662 // B0: ...
663 //     jmp  B2   (or jcc B2)
664 //
665 uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) {
666   uint64_t NumDoubleJumps = 0;
667 
668   MCContext *Ctx = Function.getBinaryContext().Ctx.get();
669   MCPlusBuilder *MIB = Function.getBinaryContext().MIB.get();
670   for (BinaryBasicBlock &BB : Function) {
671     auto checkAndPatch = [&](BinaryBasicBlock *Pred, BinaryBasicBlock *Succ,
672                              const MCSymbol *SuccSym) {
673       // Ignore infinite loop jumps or fallthrough tail jumps.
674       if (Pred == Succ || Succ == &BB)
675         return false;
676 
677       if (Succ) {
678         const MCSymbol *TBB = nullptr;
679         const MCSymbol *FBB = nullptr;
680         MCInst *CondBranch = nullptr;
681         MCInst *UncondBranch = nullptr;
682         bool Res = Pred->analyzeBranch(TBB, FBB, CondBranch, UncondBranch);
683         if (!Res) {
684           LLVM_DEBUG(dbgs() << "analyzeBranch failed in peepholes in block:\n";
685                      Pred->dump());
686           return false;
687         }
688         Pred->replaceSuccessor(&BB, Succ);
689 
690         // We must patch up any existing branch instructions to match up
691         // with the new successor.
692         assert((CondBranch || (!CondBranch && Pred->succ_size() == 1)) &&
693                "Predecessor block has inconsistent number of successors");
694         if (CondBranch && MIB->getTargetSymbol(*CondBranch) == BB.getLabel()) {
695           MIB->replaceBranchTarget(*CondBranch, Succ->getLabel(), Ctx);
696         } else if (UncondBranch &&
697                    MIB->getTargetSymbol(*UncondBranch) == BB.getLabel()) {
698           MIB->replaceBranchTarget(*UncondBranch, Succ->getLabel(), Ctx);
699         } else if (!UncondBranch) {
700           assert(Function.getBasicBlockAfter(Pred, false) != Succ &&
701                  "Don't add an explicit jump to a fallthrough block.");
702           Pred->addBranchInstruction(Succ);
703         }
704       } else {
705         // Succ will be null in the tail call case.  In this case we
706         // need to explicitly add a tail call instruction.
707         MCInst *Branch = Pred->getLastNonPseudoInstr();
708         if (Branch && MIB->isUnconditionalBranch(*Branch)) {
709           assert(MIB->getTargetSymbol(*Branch) == BB.getLabel());
710           Pred->removeSuccessor(&BB);
711           Pred->eraseInstruction(Pred->findInstruction(Branch));
712           Pred->addTailCallInstruction(SuccSym);
713         } else {
714           return false;
715         }
716       }
717 
718       ++NumDoubleJumps;
719       LLVM_DEBUG(dbgs() << "Removed double jump in " << Function << " from "
720                         << Pred->getName() << " -> " << BB.getName() << " to "
721                         << Pred->getName() << " -> " << SuccSym->getName()
722                         << (!Succ ? " (tail)\n" : "\n"));
723 
724       return true;
725     };
726 
727     if (BB.getNumNonPseudos() != 1 || BB.isLandingPad())
728       continue;
729 
730     MCInst *Inst = BB.getFirstNonPseudoInstr();
731     const bool IsTailCall = MIB->isTailCall(*Inst);
732 
733     if (!MIB->isUnconditionalBranch(*Inst) && !IsTailCall)
734       continue;
735 
736     // If we operate after SCTC make sure it's not a conditional tail call.
737     if (IsTailCall && MIB->isConditionalBranch(*Inst))
738       continue;
739 
740     const MCSymbol *SuccSym = MIB->getTargetSymbol(*Inst);
741     BinaryBasicBlock *Succ = BB.getSuccessor();
742 
743     if (((!Succ || &BB == Succ) && !IsTailCall) || (IsTailCall && !SuccSym))
744       continue;
745 
746     std::vector<BinaryBasicBlock *> Preds = {BB.pred_begin(), BB.pred_end()};
747 
748     for (BinaryBasicBlock *Pred : Preds) {
749       if (Pred->isLandingPad())
750         continue;
751 
752       if (Pred->getSuccessor() == &BB ||
753           (Pred->getConditionalSuccessor(true) == &BB && !IsTailCall) ||
754           Pred->getConditionalSuccessor(false) == &BB)
755         if (checkAndPatch(Pred, Succ, SuccSym) && MarkInvalid)
756           BB.markValid(BB.pred_size() != 0 || BB.isLandingPad() ||
757                        BB.isEntryPoint());
758     }
759   }
760 
761   return NumDoubleJumps;
762 }
763 } // namespace
764 
765 bool SimplifyConditionalTailCalls::shouldRewriteBranch(
766     const BinaryBasicBlock *PredBB, const MCInst &CondBranch,
767     const BinaryBasicBlock *BB, const bool DirectionFlag) {
768   if (BeenOptimized.count(PredBB))
769     return false;
770 
771   const bool IsForward = BinaryFunction::isForwardBranch(PredBB, BB);
772 
773   if (IsForward)
774     ++NumOrigForwardBranches;
775   else
776     ++NumOrigBackwardBranches;
777 
778   if (opts::SctcMode == opts::SctcAlways)
779     return true;
780 
781   if (opts::SctcMode == opts::SctcPreserveDirection)
782     return IsForward == DirectionFlag;
783 
784   const ErrorOr<std::pair<double, double>> Frequency =
785       PredBB->getBranchStats(BB);
786 
787   // It's ok to rewrite the conditional branch if the new target will be
788   // a backward branch.
789 
790   // If no data available for these branches, then it should be ok to
791   // do the optimization since it will reduce code size.
792   if (Frequency.getError())
793     return true;
794 
795   // TODO: should this use misprediction frequency instead?
796   const bool Result = (IsForward && Frequency.get().first >= 0.5) ||
797                       (!IsForward && Frequency.get().first <= 0.5);
798 
799   return Result == DirectionFlag;
800 }
801 
802 uint64_t SimplifyConditionalTailCalls::fixTailCalls(BinaryFunction &BF) {
803   // Need updated indices to correctly detect branch' direction.
804   BF.updateLayoutIndices();
805   BF.markUnreachableBlocks();
806 
807   MCPlusBuilder *MIB = BF.getBinaryContext().MIB.get();
808   MCContext *Ctx = BF.getBinaryContext().Ctx.get();
809   uint64_t NumLocalCTCCandidates = 0;
810   uint64_t NumLocalCTCs = 0;
811   uint64_t LocalCTCTakenCount = 0;
812   uint64_t LocalCTCExecCount = 0;
813   std::vector<std::pair<BinaryBasicBlock *, const BinaryBasicBlock *>>
814       NeedsUncondBranch;
815 
816   // Will block be deleted by UCE?
817   auto isValid = [](const BinaryBasicBlock *BB) {
818     return (BB->pred_size() != 0 || BB->isLandingPad() || BB->isEntryPoint());
819   };
820 
821   for (BinaryBasicBlock *BB : BF.layout()) {
822     // Locate BB with a single direct tail-call instruction.
823     if (BB->getNumNonPseudos() != 1)
824       continue;
825 
826     MCInst *Instr = BB->getFirstNonPseudoInstr();
827     if (!MIB->isTailCall(*Instr) || MIB->isConditionalBranch(*Instr))
828       continue;
829 
830     const MCSymbol *CalleeSymbol = MIB->getTargetSymbol(*Instr);
831     if (!CalleeSymbol)
832       continue;
833 
834     // Detect direction of the possible conditional tail call.
835     const bool IsForwardCTC = BF.isForwardCall(CalleeSymbol);
836 
837     // Iterate through all predecessors.
838     for (BinaryBasicBlock *PredBB : BB->predecessors()) {
839       BinaryBasicBlock *CondSucc = PredBB->getConditionalSuccessor(true);
840       if (!CondSucc)
841         continue;
842 
843       ++NumLocalCTCCandidates;
844 
845       const MCSymbol *TBB = nullptr;
846       const MCSymbol *FBB = nullptr;
847       MCInst *CondBranch = nullptr;
848       MCInst *UncondBranch = nullptr;
849       bool Result = PredBB->analyzeBranch(TBB, FBB, CondBranch, UncondBranch);
850 
851       // analyzeBranch() can fail due to unusual branch instructions, e.g. jrcxz
852       if (!Result) {
853         LLVM_DEBUG(dbgs() << "analyzeBranch failed in SCTC in block:\n";
854                    PredBB->dump());
855         continue;
856       }
857 
858       assert(Result && "internal error analyzing conditional branch");
859       assert(CondBranch && "conditional branch expected");
860 
861       // It's possible that PredBB is also a successor to BB that may have
862       // been processed by a previous iteration of the SCTC loop, in which
863       // case it may have been marked invalid.  We should skip rewriting in
864       // this case.
865       if (!PredBB->isValid()) {
866         assert(PredBB->isSuccessor(BB) &&
867                "PredBB should be valid if it is not a successor to BB");
868         continue;
869       }
870 
871       // We don't want to reverse direction of the branch in new order
872       // without further profile analysis.
873       const bool DirectionFlag = CondSucc == BB ? IsForwardCTC : !IsForwardCTC;
874       if (!shouldRewriteBranch(PredBB, *CondBranch, BB, DirectionFlag))
875         continue;
876 
877       // Record this block so that we don't try to optimize it twice.
878       BeenOptimized.insert(PredBB);
879 
880       uint64_t Count = 0;
881       if (CondSucc != BB) {
882         // Patch the new target address into the conditional branch.
883         MIB->reverseBranchCondition(*CondBranch, CalleeSymbol, Ctx);
884         // Since we reversed the condition on the branch we need to change
885         // the target for the unconditional branch or add a unconditional
886         // branch to the old target.  This has to be done manually since
887         // fixupBranches is not called after SCTC.
888         NeedsUncondBranch.emplace_back(PredBB, CondSucc);
889         Count = PredBB->getFallthroughBranchInfo().Count;
890       } else {
891         // Change destination of the conditional branch.
892         MIB->replaceBranchTarget(*CondBranch, CalleeSymbol, Ctx);
893         Count = PredBB->getTakenBranchInfo().Count;
894       }
895       const uint64_t CTCTakenFreq =
896           Count == BinaryBasicBlock::COUNT_NO_PROFILE ? 0 : Count;
897 
898       // Annotate it, so "isCall" returns true for this jcc
899       MIB->setConditionalTailCall(*CondBranch);
900       // Add info abount the conditional tail call frequency, otherwise this
901       // info will be lost when we delete the associated BranchInfo entry
902       auto &CTCAnnotation =
903           MIB->getOrCreateAnnotationAs<uint64_t>(*CondBranch, "CTCTakenCount");
904       CTCAnnotation = CTCTakenFreq;
905 
906       // Remove the unused successor which may be eliminated later
907       // if there are no other users.
908       PredBB->removeSuccessor(BB);
909       // Update BB execution count
910       if (CTCTakenFreq && CTCTakenFreq <= BB->getKnownExecutionCount())
911         BB->setExecutionCount(BB->getExecutionCount() - CTCTakenFreq);
912       else if (CTCTakenFreq > BB->getKnownExecutionCount())
913         BB->setExecutionCount(0);
914 
915       ++NumLocalCTCs;
916       LocalCTCTakenCount += CTCTakenFreq;
917       LocalCTCExecCount += PredBB->getKnownExecutionCount();
918     }
919 
920     // Remove the block from CFG if all predecessors were removed.
921     BB->markValid(isValid(BB));
922   }
923 
924   // Add unconditional branches at the end of BBs to new successors
925   // as long as the successor is not a fallthrough.
926   for (auto &Entry : NeedsUncondBranch) {
927     BinaryBasicBlock *PredBB = Entry.first;
928     const BinaryBasicBlock *CondSucc = Entry.second;
929 
930     const MCSymbol *TBB = nullptr;
931     const MCSymbol *FBB = nullptr;
932     MCInst *CondBranch = nullptr;
933     MCInst *UncondBranch = nullptr;
934     PredBB->analyzeBranch(TBB, FBB, CondBranch, UncondBranch);
935 
936     // Find the next valid block.  Invalid blocks will be deleted
937     // so they shouldn't be considered fallthrough targets.
938     const BinaryBasicBlock *NextBlock = BF.getBasicBlockAfter(PredBB, false);
939     while (NextBlock && !isValid(NextBlock))
940       NextBlock = BF.getBasicBlockAfter(NextBlock, false);
941 
942     // Get the unconditional successor to this block.
943     const BinaryBasicBlock *PredSucc = PredBB->getSuccessor();
944     assert(PredSucc && "The other branch should be a tail call");
945 
946     const bool HasFallthrough = (NextBlock && PredSucc == NextBlock);
947 
948     if (UncondBranch) {
949       if (HasFallthrough)
950         PredBB->eraseInstruction(PredBB->findInstruction(UncondBranch));
951       else
952         MIB->replaceBranchTarget(*UncondBranch, CondSucc->getLabel(), Ctx);
953     } else if (!HasFallthrough) {
954       MCInst Branch;
955       MIB->createUncondBranch(Branch, CondSucc->getLabel(), Ctx);
956       PredBB->addInstruction(Branch);
957     }
958   }
959 
960   if (NumLocalCTCs > 0) {
961     NumDoubleJumps += fixDoubleJumps(BF, true);
962     // Clean-up unreachable tail-call blocks.
963     const std::pair<unsigned, uint64_t> Stats = BF.eraseInvalidBBs();
964     DeletedBlocks += Stats.first;
965     DeletedBytes += Stats.second;
966 
967     assert(BF.validateCFG());
968   }
969 
970   LLVM_DEBUG(dbgs() << "BOLT: created " << NumLocalCTCs
971                     << " conditional tail calls from a total of "
972                     << NumLocalCTCCandidates << " candidates in function " << BF
973                     << ". CTCs execution count for this function is "
974                     << LocalCTCExecCount << " and CTC taken count is "
975                     << LocalCTCTakenCount << "\n";);
976 
977   NumTailCallsPatched += NumLocalCTCs;
978   NumCandidateTailCalls += NumLocalCTCCandidates;
979   CTCExecCount += LocalCTCExecCount;
980   CTCTakenCount += LocalCTCTakenCount;
981 
982   return NumLocalCTCs > 0;
983 }
984 
985 void SimplifyConditionalTailCalls::runOnFunctions(BinaryContext &BC) {
986   if (!BC.isX86())
987     return;
988 
989   for (auto &It : BC.getBinaryFunctions()) {
990     BinaryFunction &Function = It.second;
991 
992     if (!shouldOptimize(Function))
993       continue;
994 
995     if (fixTailCalls(Function)) {
996       Modified.insert(&Function);
997       Function.setHasCanonicalCFG(false);
998     }
999   }
1000 
1001   outs() << "BOLT-INFO: SCTC: patched " << NumTailCallsPatched
1002          << " tail calls (" << NumOrigForwardBranches << " forward)"
1003          << " tail calls (" << NumOrigBackwardBranches << " backward)"
1004          << " from a total of " << NumCandidateTailCalls << " while removing "
1005          << NumDoubleJumps << " double jumps"
1006          << " and removing " << DeletedBlocks << " basic blocks"
1007          << " totalling " << DeletedBytes
1008          << " bytes of code. CTCs total execution count is " << CTCExecCount
1009          << " and the number of times CTCs are taken is " << CTCTakenCount
1010          << ".\n";
1011 }
1012 
1013 uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) {
1014   uint64_t Count = 0;
1015   const BinaryContext &BC = Function.getBinaryContext();
1016   for (BinaryBasicBlock &BB : Function) {
1017     for (MCInst &Inst : BB) {
1018       MCInst OriginalInst;
1019       if (opts::Verbosity > 2)
1020         OriginalInst = Inst;
1021 
1022       if (!BC.MIB->shortenInstruction(Inst, *BC.STI))
1023         continue;
1024 
1025       if (opts::Verbosity > 2) {
1026         BC.scopeLock();
1027         outs() << "BOLT-INFO: shortening:\nBOLT-INFO:    ";
1028         BC.printInstruction(outs(), OriginalInst, 0, &Function);
1029         outs() << "BOLT-INFO: to:";
1030         BC.printInstruction(outs(), Inst, 0, &Function);
1031       }
1032 
1033       ++Count;
1034     }
1035   }
1036 
1037   return Count;
1038 }
1039 
1040 void ShortenInstructions::runOnFunctions(BinaryContext &BC) {
1041   std::atomic<uint64_t> NumShortened{0};
1042   if (!BC.isX86())
1043     return;
1044 
1045   ParallelUtilities::runOnEachFunction(
1046       BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR,
1047       [&](BinaryFunction &BF) { NumShortened += shortenInstructions(BF); },
1048       nullptr, "ShortenInstructions");
1049 
1050   outs() << "BOLT-INFO: " << NumShortened << " instructions were shortened\n";
1051 }
1052 
1053 void Peepholes::addTailcallTraps(BinaryFunction &Function) {
1054   MCPlusBuilder *MIB = Function.getBinaryContext().MIB.get();
1055   for (BinaryBasicBlock &BB : Function) {
1056     MCInst *Inst = BB.getLastNonPseudoInstr();
1057     if (Inst && MIB->isTailCall(*Inst) && MIB->isIndirectBranch(*Inst)) {
1058       MCInst Trap;
1059       if (MIB->createTrap(Trap)) {
1060         BB.addInstruction(Trap);
1061         ++TailCallTraps;
1062       }
1063     }
1064   }
1065 }
1066 
1067 void Peepholes::removeUselessCondBranches(BinaryFunction &Function) {
1068   for (BinaryBasicBlock &BB : Function) {
1069     if (BB.succ_size() != 2)
1070       continue;
1071 
1072     BinaryBasicBlock *CondBB = BB.getConditionalSuccessor(true);
1073     BinaryBasicBlock *UncondBB = BB.getConditionalSuccessor(false);
1074     if (CondBB != UncondBB)
1075       continue;
1076 
1077     const MCSymbol *TBB = nullptr;
1078     const MCSymbol *FBB = nullptr;
1079     MCInst *CondBranch = nullptr;
1080     MCInst *UncondBranch = nullptr;
1081     bool Result = BB.analyzeBranch(TBB, FBB, CondBranch, UncondBranch);
1082 
1083     // analyzeBranch() can fail due to unusual branch instructions,
1084     // e.g. jrcxz, or jump tables (indirect jump).
1085     if (!Result || !CondBranch)
1086       continue;
1087 
1088     BB.removeDuplicateConditionalSuccessor(CondBranch);
1089     ++NumUselessCondBranches;
1090   }
1091 }
1092 
1093 void Peepholes::runOnFunctions(BinaryContext &BC) {
1094   const char Opts =
1095       std::accumulate(opts::Peepholes.begin(), opts::Peepholes.end(), 0,
1096                       [](const char A, const PeepholeOpts B) { return A | B; });
1097   if (Opts == PEEP_NONE)
1098     return;
1099 
1100   for (auto &It : BC.getBinaryFunctions()) {
1101     BinaryFunction &Function = It.second;
1102     if (shouldOptimize(Function)) {
1103       if (Opts & PEEP_DOUBLE_JUMPS)
1104         NumDoubleJumps += fixDoubleJumps(Function, false);
1105       if (Opts & PEEP_TAILCALL_TRAPS)
1106         addTailcallTraps(Function);
1107       if (Opts & PEEP_USELESS_BRANCHES)
1108         removeUselessCondBranches(Function);
1109       assert(Function.validateCFG());
1110     }
1111   }
1112   outs() << "BOLT-INFO: Peephole: " << NumDoubleJumps
1113          << " double jumps patched.\n"
1114          << "BOLT-INFO: Peephole: " << TailCallTraps
1115          << " tail call traps inserted.\n"
1116          << "BOLT-INFO: Peephole: " << NumUselessCondBranches
1117          << " useless conditional branches removed.\n";
1118 }
1119 
1120 bool SimplifyRODataLoads::simplifyRODataLoads(BinaryFunction &BF) {
1121   BinaryContext &BC = BF.getBinaryContext();
1122   MCPlusBuilder *MIB = BC.MIB.get();
1123 
1124   uint64_t NumLocalLoadsSimplified = 0;
1125   uint64_t NumDynamicLocalLoadsSimplified = 0;
1126   uint64_t NumLocalLoadsFound = 0;
1127   uint64_t NumDynamicLocalLoadsFound = 0;
1128 
1129   for (BinaryBasicBlock *BB : BF.layout()) {
1130     for (MCInst &Inst : *BB) {
1131       unsigned Opcode = Inst.getOpcode();
1132       const MCInstrDesc &Desc = BC.MII->get(Opcode);
1133 
1134       // Skip instructions that do not load from memory.
1135       if (!Desc.mayLoad())
1136         continue;
1137 
1138       // Try to statically evaluate the target memory address;
1139       uint64_t TargetAddress;
1140 
1141       if (MIB->hasPCRelOperand(Inst)) {
1142         // Try to find the symbol that corresponds to the PC-relative operand.
1143         MCOperand *DispOpI = MIB->getMemOperandDisp(Inst);
1144         assert(DispOpI != Inst.end() && "expected PC-relative displacement");
1145         assert(DispOpI->isExpr() &&
1146                "found PC-relative with non-symbolic displacement");
1147 
1148         // Get displacement symbol.
1149         const MCSymbol *DisplSymbol;
1150         uint64_t DisplOffset;
1151 
1152         std::tie(DisplSymbol, DisplOffset) =
1153             MIB->getTargetSymbolInfo(DispOpI->getExpr());
1154 
1155         if (!DisplSymbol)
1156           continue;
1157 
1158         // Look up the symbol address in the global symbols map of the binary
1159         // context object.
1160         BinaryData *BD = BC.getBinaryDataByName(DisplSymbol->getName());
1161         if (!BD)
1162           continue;
1163         TargetAddress = BD->getAddress() + DisplOffset;
1164       } else if (!MIB->evaluateMemOperandTarget(Inst, TargetAddress)) {
1165         continue;
1166       }
1167 
1168       // Get the contents of the section containing the target address of the
1169       // memory operand. We are only interested in read-only sections.
1170       ErrorOr<BinarySection &> DataSection =
1171           BC.getSectionForAddress(TargetAddress);
1172       if (!DataSection || !DataSection->isReadOnly())
1173         continue;
1174 
1175       if (BC.getRelocationAt(TargetAddress) ||
1176           BC.getDynamicRelocationAt(TargetAddress))
1177         continue;
1178 
1179       uint32_t Offset = TargetAddress - DataSection->getAddress();
1180       StringRef ConstantData = DataSection->getContents();
1181 
1182       ++NumLocalLoadsFound;
1183       if (BB->hasProfile())
1184         NumDynamicLocalLoadsFound += BB->getExecutionCount();
1185 
1186       if (MIB->replaceMemOperandWithImm(Inst, ConstantData, Offset)) {
1187         ++NumLocalLoadsSimplified;
1188         if (BB->hasProfile())
1189           NumDynamicLocalLoadsSimplified += BB->getExecutionCount();
1190       }
1191     }
1192   }
1193 
1194   NumLoadsFound += NumLocalLoadsFound;
1195   NumDynamicLoadsFound += NumDynamicLocalLoadsFound;
1196   NumLoadsSimplified += NumLocalLoadsSimplified;
1197   NumDynamicLoadsSimplified += NumDynamicLocalLoadsSimplified;
1198 
1199   return NumLocalLoadsSimplified > 0;
1200 }
1201 
1202 void SimplifyRODataLoads::runOnFunctions(BinaryContext &BC) {
1203   for (auto &It : BC.getBinaryFunctions()) {
1204     BinaryFunction &Function = It.second;
1205     if (shouldOptimize(Function) && simplifyRODataLoads(Function))
1206       Modified.insert(&Function);
1207   }
1208 
1209   outs() << "BOLT-INFO: simplified " << NumLoadsSimplified << " out of "
1210          << NumLoadsFound << " loads from a statically computed address.\n"
1211          << "BOLT-INFO: dynamic loads simplified: " << NumDynamicLoadsSimplified
1212          << "\n"
1213          << "BOLT-INFO: dynamic loads found: " << NumDynamicLoadsFound << "\n";
1214 }
1215 
1216 void AssignSections::runOnFunctions(BinaryContext &BC) {
1217   for (BinaryFunction *Function : BC.getInjectedBinaryFunctions()) {
1218     Function->setCodeSectionName(BC.getInjectedCodeSectionName());
1219     Function->setColdCodeSectionName(BC.getInjectedColdCodeSectionName());
1220   }
1221 
1222   // In non-relocation mode functions have pre-assigned section names.
1223   if (!BC.HasRelocations)
1224     return;
1225 
1226   const bool UseColdSection =
1227       BC.NumProfiledFuncs > 0 ||
1228       opts::ReorderFunctions == ReorderFunctions::RT_USER;
1229   for (auto &BFI : BC.getBinaryFunctions()) {
1230     BinaryFunction &Function = BFI.second;
1231     if (opts::isHotTextMover(Function)) {
1232       Function.setCodeSectionName(BC.getHotTextMoverSectionName());
1233       Function.setColdCodeSectionName(BC.getHotTextMoverSectionName());
1234       continue;
1235     }
1236 
1237     if (!UseColdSection || Function.hasValidIndex() ||
1238         Function.hasValidProfile())
1239       Function.setCodeSectionName(BC.getMainCodeSectionName());
1240     else
1241       Function.setCodeSectionName(BC.getColdCodeSectionName());
1242 
1243     if (Function.isSplit())
1244       Function.setColdCodeSectionName(BC.getColdCodeSectionName());
1245   }
1246 }
1247 
1248 void PrintProfileStats::runOnFunctions(BinaryContext &BC) {
1249   double FlowImbalanceMean = 0.0;
1250   size_t NumBlocksConsidered = 0;
1251   double WorstBias = 0.0;
1252   const BinaryFunction *WorstBiasFunc = nullptr;
1253 
1254   // For each function CFG, we fill an IncomingMap with the sum of the frequency
1255   // of incoming edges for each BB. Likewise for each OutgoingMap and the sum
1256   // of the frequency of outgoing edges.
1257   using FlowMapTy = std::unordered_map<const BinaryBasicBlock *, uint64_t>;
1258   std::unordered_map<const BinaryFunction *, FlowMapTy> TotalIncomingMaps;
1259   std::unordered_map<const BinaryFunction *, FlowMapTy> TotalOutgoingMaps;
1260 
1261   // Compute mean
1262   for (const auto &BFI : BC.getBinaryFunctions()) {
1263     const BinaryFunction &Function = BFI.second;
1264     if (Function.empty() || !Function.isSimple())
1265       continue;
1266     FlowMapTy &IncomingMap = TotalIncomingMaps[&Function];
1267     FlowMapTy &OutgoingMap = TotalOutgoingMaps[&Function];
1268     for (const BinaryBasicBlock &BB : Function) {
1269       uint64_t TotalOutgoing = 0ULL;
1270       auto SuccBIIter = BB.branch_info_begin();
1271       for (BinaryBasicBlock *Succ : BB.successors()) {
1272         uint64_t Count = SuccBIIter->Count;
1273         if (Count == BinaryBasicBlock::COUNT_NO_PROFILE || Count == 0) {
1274           ++SuccBIIter;
1275           continue;
1276         }
1277         TotalOutgoing += Count;
1278         IncomingMap[Succ] += Count;
1279         ++SuccBIIter;
1280       }
1281       OutgoingMap[&BB] = TotalOutgoing;
1282     }
1283 
1284     size_t NumBlocks = 0;
1285     double Mean = 0.0;
1286     for (const BinaryBasicBlock &BB : Function) {
1287       // Do not compute score for low frequency blocks, entry or exit blocks
1288       if (IncomingMap[&BB] < 100 || OutgoingMap[&BB] == 0 || BB.isEntryPoint())
1289         continue;
1290       ++NumBlocks;
1291       const double Difference = (double)OutgoingMap[&BB] - IncomingMap[&BB];
1292       Mean += fabs(Difference / IncomingMap[&BB]);
1293     }
1294 
1295     FlowImbalanceMean += Mean;
1296     NumBlocksConsidered += NumBlocks;
1297     if (!NumBlocks)
1298       continue;
1299     double FuncMean = Mean / NumBlocks;
1300     if (FuncMean > WorstBias) {
1301       WorstBias = FuncMean;
1302       WorstBiasFunc = &Function;
1303     }
1304   }
1305   if (NumBlocksConsidered > 0)
1306     FlowImbalanceMean /= NumBlocksConsidered;
1307 
1308   // Compute standard deviation
1309   NumBlocksConsidered = 0;
1310   double FlowImbalanceVar = 0.0;
1311   for (const auto &BFI : BC.getBinaryFunctions()) {
1312     const BinaryFunction &Function = BFI.second;
1313     if (Function.empty() || !Function.isSimple())
1314       continue;
1315     FlowMapTy &IncomingMap = TotalIncomingMaps[&Function];
1316     FlowMapTy &OutgoingMap = TotalOutgoingMaps[&Function];
1317     for (const BinaryBasicBlock &BB : Function) {
1318       if (IncomingMap[&BB] < 100 || OutgoingMap[&BB] == 0)
1319         continue;
1320       ++NumBlocksConsidered;
1321       const double Difference = (double)OutgoingMap[&BB] - IncomingMap[&BB];
1322       FlowImbalanceVar +=
1323           pow(fabs(Difference / IncomingMap[&BB]) - FlowImbalanceMean, 2);
1324     }
1325   }
1326   if (NumBlocksConsidered) {
1327     FlowImbalanceVar /= NumBlocksConsidered;
1328     FlowImbalanceVar = sqrt(FlowImbalanceVar);
1329   }
1330 
1331   // Report to user
1332   outs() << format("BOLT-INFO: Profile bias score: %.4lf%% StDev: %.4lf%%\n",
1333                    (100.0 * FlowImbalanceMean), (100.0 * FlowImbalanceVar));
1334   if (WorstBiasFunc && opts::Verbosity >= 1) {
1335     outs() << "Worst average bias observed in " << WorstBiasFunc->getPrintName()
1336            << "\n";
1337     LLVM_DEBUG(WorstBiasFunc->dump());
1338   }
1339 }
1340 
1341 void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
1342   uint64_t NumRegularFunctions = 0;
1343   uint64_t NumStaleProfileFunctions = 0;
1344   uint64_t NumNonSimpleProfiledFunctions = 0;
1345   uint64_t NumUnknownControlFlowFunctions = 0;
1346   uint64_t TotalSampleCount = 0;
1347   uint64_t StaleSampleCount = 0;
1348   std::vector<const BinaryFunction *> ProfiledFunctions;
1349   const char *StaleFuncsHeader = "BOLT-INFO: Functions with stale profile:\n";
1350   for (auto &BFI : BC.getBinaryFunctions()) {
1351     const BinaryFunction &Function = BFI.second;
1352 
1353     // Ignore PLT functions for stats.
1354     if (Function.isPLTFunction())
1355       continue;
1356 
1357     ++NumRegularFunctions;
1358 
1359     if (!Function.isSimple()) {
1360       if (Function.hasProfile())
1361         ++NumNonSimpleProfiledFunctions;
1362       continue;
1363     }
1364 
1365     if (Function.hasUnknownControlFlow()) {
1366       if (opts::PrintUnknownCFG)
1367         Function.dump();
1368       else if (opts::PrintUnknown)
1369         errs() << "function with unknown control flow: " << Function << '\n';
1370 
1371       ++NumUnknownControlFlowFunctions;
1372     }
1373 
1374     if (!Function.hasProfile())
1375       continue;
1376 
1377     uint64_t SampleCount = Function.getRawBranchCount();
1378     TotalSampleCount += SampleCount;
1379 
1380     if (Function.hasValidProfile()) {
1381       ProfiledFunctions.push_back(&Function);
1382     } else {
1383       if (opts::ReportStaleFuncs) {
1384         outs() << StaleFuncsHeader;
1385         StaleFuncsHeader = "";
1386         outs() << "  " << Function << '\n';
1387       }
1388       ++NumStaleProfileFunctions;
1389       StaleSampleCount += SampleCount;
1390     }
1391   }
1392   BC.NumProfiledFuncs = ProfiledFunctions.size();
1393 
1394   const size_t NumAllProfiledFunctions =
1395       ProfiledFunctions.size() + NumStaleProfileFunctions;
1396   outs() << "BOLT-INFO: " << NumAllProfiledFunctions << " out of "
1397          << NumRegularFunctions << " functions in the binary ("
1398          << format("%.1f", NumAllProfiledFunctions /
1399                                (float)NumRegularFunctions * 100.0f)
1400          << "%) have non-empty execution profile\n";
1401   if (NumNonSimpleProfiledFunctions) {
1402     outs() << "BOLT-INFO: " << NumNonSimpleProfiledFunctions << " function"
1403            << (NumNonSimpleProfiledFunctions == 1 ? "" : "s")
1404            << " with profile could not be optimized\n";
1405   }
1406   if (NumStaleProfileFunctions) {
1407     const float PctStale =
1408         NumStaleProfileFunctions / (float)NumAllProfiledFunctions * 100.0f;
1409     auto printErrorOrWarning = [&]() {
1410       if (PctStale > opts::StaleThreshold)
1411         errs() << "BOLT-ERROR: ";
1412       else
1413         errs() << "BOLT-WARNING: ";
1414     };
1415     printErrorOrWarning();
1416     errs() << NumStaleProfileFunctions
1417            << format(" (%.1f%% of all profiled)", PctStale) << " function"
1418            << (NumStaleProfileFunctions == 1 ? "" : "s")
1419            << " have invalid (possibly stale) profile."
1420               " Use -report-stale to see the list.\n";
1421     if (TotalSampleCount > 0) {
1422       printErrorOrWarning();
1423       errs() << StaleSampleCount << " out of " << TotalSampleCount
1424              << " samples in the binary ("
1425              << format("%.1f", ((100.0f * StaleSampleCount) / TotalSampleCount))
1426              << "%) belong to functions with invalid"
1427                 " (possibly stale) profile.\n";
1428     }
1429     if (PctStale > opts::StaleThreshold) {
1430       errs() << "BOLT-ERROR: stale functions exceed specified threshold of "
1431              << opts::StaleThreshold << "%. Exiting.\n";
1432       exit(1);
1433     }
1434   }
1435 
1436   if (const uint64_t NumUnusedObjects = BC.getNumUnusedProfiledObjects()) {
1437     outs() << "BOLT-INFO: profile for " << NumUnusedObjects
1438            << " objects was ignored\n";
1439   }
1440 
1441   if (ProfiledFunctions.size() > 10) {
1442     if (opts::Verbosity >= 1) {
1443       outs() << "BOLT-INFO: top called functions are:\n";
1444       std::sort(ProfiledFunctions.begin(), ProfiledFunctions.end(),
1445                 [](const BinaryFunction *A, const BinaryFunction *B) {
1446                   return B->getExecutionCount() < A->getExecutionCount();
1447                 });
1448       auto SFI = ProfiledFunctions.begin();
1449       auto SFIend = ProfiledFunctions.end();
1450       for (unsigned I = 0u; I < opts::TopCalledLimit && SFI != SFIend;
1451            ++SFI, ++I)
1452         outs() << "  " << **SFI << " : " << (*SFI)->getExecutionCount() << '\n';
1453     }
1454   }
1455 
1456   if (!opts::PrintSortedBy.empty() &&
1457       std::find(opts::PrintSortedBy.begin(), opts::PrintSortedBy.end(),
1458                 DynoStats::FIRST_DYNO_STAT) == opts::PrintSortedBy.end()) {
1459 
1460     std::vector<const BinaryFunction *> Functions;
1461     std::map<const BinaryFunction *, DynoStats> Stats;
1462 
1463     for (const auto &BFI : BC.getBinaryFunctions()) {
1464       const BinaryFunction &BF = BFI.second;
1465       if (shouldOptimize(BF) && BF.hasValidProfile()) {
1466         Functions.push_back(&BF);
1467         Stats.emplace(&BF, getDynoStats(BF));
1468       }
1469     }
1470 
1471     const bool SortAll =
1472         std::find(opts::PrintSortedBy.begin(), opts::PrintSortedBy.end(),
1473                   DynoStats::LAST_DYNO_STAT) != opts::PrintSortedBy.end();
1474 
1475     const bool Ascending =
1476         opts::DynoStatsSortOrderOpt == opts::DynoStatsSortOrder::Ascending;
1477 
1478     if (SortAll) {
1479       std::stable_sort(Functions.begin(), Functions.end(),
1480                        [Ascending, &Stats](const BinaryFunction *A,
1481                                            const BinaryFunction *B) {
1482                          return Ascending ? Stats.at(A) < Stats.at(B)
1483                                           : Stats.at(B) < Stats.at(A);
1484                        });
1485     } else {
1486       std::stable_sort(
1487           Functions.begin(), Functions.end(),
1488           [Ascending, &Stats](const BinaryFunction *A,
1489                               const BinaryFunction *B) {
1490             const DynoStats &StatsA = Stats.at(A);
1491             const DynoStats &StatsB = Stats.at(B);
1492             return Ascending ? StatsA.lessThan(StatsB, opts::PrintSortedBy)
1493                              : StatsB.lessThan(StatsA, opts::PrintSortedBy);
1494           });
1495     }
1496 
1497     outs() << "BOLT-INFO: top functions sorted by ";
1498     if (SortAll) {
1499       outs() << "dyno stats";
1500     } else {
1501       outs() << "(";
1502       bool PrintComma = false;
1503       for (const DynoStats::Category Category : opts::PrintSortedBy) {
1504         if (PrintComma)
1505           outs() << ", ";
1506         outs() << DynoStats::Description(Category);
1507         PrintComma = true;
1508       }
1509       outs() << ")";
1510     }
1511 
1512     outs() << " are:\n";
1513     auto SFI = Functions.begin();
1514     for (unsigned I = 0; I < 100 && SFI != Functions.end(); ++SFI, ++I) {
1515       const DynoStats Stats = getDynoStats(**SFI);
1516       outs() << "  " << **SFI;
1517       if (!SortAll) {
1518         outs() << " (";
1519         bool PrintComma = false;
1520         for (const DynoStats::Category Category : opts::PrintSortedBy) {
1521           if (PrintComma)
1522             outs() << ", ";
1523           outs() << dynoStatsOptName(Category) << "=" << Stats[Category];
1524           PrintComma = true;
1525         }
1526         outs() << ")";
1527       }
1528       outs() << "\n";
1529     }
1530   }
1531 
1532   if (!BC.TrappedFunctions.empty()) {
1533     errs() << "BOLT-WARNING: " << BC.TrappedFunctions.size() << " function"
1534            << (BC.TrappedFunctions.size() > 1 ? "s" : "")
1535            << " will trap on entry. Use -trap-avx512=0 to disable"
1536               " traps.";
1537     if (opts::Verbosity >= 1 || BC.TrappedFunctions.size() <= 5) {
1538       errs() << '\n';
1539       for (const BinaryFunction *Function : BC.TrappedFunctions)
1540         errs() << "  " << *Function << '\n';
1541     } else {
1542       errs() << " Use -v=1 to see the list.\n";
1543     }
1544   }
1545 
1546   // Print information on missed macro-fusion opportunities seen on input.
1547   if (BC.MissedMacroFusionPairs) {
1548     outs() << "BOLT-INFO: the input contains " << BC.MissedMacroFusionPairs
1549            << " (dynamic count : " << BC.MissedMacroFusionExecCount
1550            << ") opportunities for macro-fusion optimization";
1551     switch (opts::AlignMacroOpFusion) {
1552     case MFT_NONE:
1553       outs() << ". Use -align-macro-fusion to fix.\n";
1554       break;
1555     case MFT_HOT:
1556       outs() << ". Will fix instances on a hot path.\n";
1557       break;
1558     case MFT_ALL:
1559       outs() << " that are going to be fixed\n";
1560       break;
1561     }
1562   }
1563 
1564   // Collect and print information about suboptimal code layout on input.
1565   if (opts::ReportBadLayout) {
1566     std::vector<const BinaryFunction *> SuboptimalFuncs;
1567     for (auto &BFI : BC.getBinaryFunctions()) {
1568       const BinaryFunction &BF = BFI.second;
1569       if (!BF.hasValidProfile())
1570         continue;
1571 
1572       const uint64_t HotThreshold =
1573           std::max<uint64_t>(BF.getKnownExecutionCount(), 1);
1574       bool HotSeen = false;
1575       for (const BinaryBasicBlock *BB : BF.rlayout()) {
1576         if (!HotSeen && BB->getKnownExecutionCount() > HotThreshold) {
1577           HotSeen = true;
1578           continue;
1579         }
1580         if (HotSeen && BB->getKnownExecutionCount() == 0) {
1581           SuboptimalFuncs.push_back(&BF);
1582           break;
1583         }
1584       }
1585     }
1586 
1587     if (!SuboptimalFuncs.empty()) {
1588       std::sort(SuboptimalFuncs.begin(), SuboptimalFuncs.end(),
1589                 [](const BinaryFunction *A, const BinaryFunction *B) {
1590                   return A->getKnownExecutionCount() / A->getSize() >
1591                          B->getKnownExecutionCount() / B->getSize();
1592                 });
1593 
1594       outs() << "BOLT-INFO: " << SuboptimalFuncs.size()
1595              << " functions have "
1596                 "cold code in the middle of hot code. Top functions are:\n";
1597       for (unsigned I = 0;
1598            I < std::min(static_cast<size_t>(opts::ReportBadLayout),
1599                         SuboptimalFuncs.size());
1600            ++I)
1601         SuboptimalFuncs[I]->print(outs());
1602     }
1603   }
1604 
1605   if (NumUnknownControlFlowFunctions) {
1606     outs() << "BOLT-INFO: " << NumUnknownControlFlowFunctions
1607            << " functions have instructions with unknown control flow";
1608     if (!opts::PrintUnknown)
1609       outs() << ". Use -print-unknown to see the list.";
1610     outs() << '\n';
1611   }
1612 }
1613 
1614 void InstructionLowering::runOnFunctions(BinaryContext &BC) {
1615   for (auto &BFI : BC.getBinaryFunctions())
1616     for (BinaryBasicBlock &BB : BFI.second)
1617       for (MCInst &Instruction : BB)
1618         BC.MIB->lowerTailCall(Instruction);
1619 }
1620 
1621 void StripRepRet::runOnFunctions(BinaryContext &BC) {
1622   uint64_t NumPrefixesRemoved = 0;
1623   uint64_t NumBytesSaved = 0;
1624   for (auto &BFI : BC.getBinaryFunctions()) {
1625     for (BinaryBasicBlock &BB : BFI.second) {
1626       auto LastInstRIter = BB.getLastNonPseudo();
1627       if (LastInstRIter == BB.rend() || !BC.MIB->isReturn(*LastInstRIter) ||
1628           !BC.MIB->deleteREPPrefix(*LastInstRIter))
1629         continue;
1630 
1631       NumPrefixesRemoved += BB.getKnownExecutionCount();
1632       ++NumBytesSaved;
1633     }
1634   }
1635 
1636   if (NumBytesSaved)
1637     outs() << "BOLT-INFO: removed " << NumBytesSaved
1638            << " 'repz' prefixes"
1639               " with estimated execution count of "
1640            << NumPrefixesRemoved << " times.\n";
1641 }
1642 
1643 void InlineMemcpy::runOnFunctions(BinaryContext &BC) {
1644   if (!BC.isX86())
1645     return;
1646 
1647   uint64_t NumInlined = 0;
1648   uint64_t NumInlinedDyno = 0;
1649   for (auto &BFI : BC.getBinaryFunctions()) {
1650     for (BinaryBasicBlock &BB : BFI.second) {
1651       for (auto II = BB.begin(); II != BB.end(); ++II) {
1652         MCInst &Inst = *II;
1653 
1654         if (!BC.MIB->isCall(Inst) || MCPlus::getNumPrimeOperands(Inst) != 1 ||
1655             !Inst.getOperand(0).isExpr())
1656           continue;
1657 
1658         const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Inst);
1659         if (CalleeSymbol->getName() != "memcpy" &&
1660             CalleeSymbol->getName() != "memcpy@PLT" &&
1661             CalleeSymbol->getName() != "_memcpy8")
1662           continue;
1663 
1664         const bool IsMemcpy8 = (CalleeSymbol->getName() == "_memcpy8");
1665         const bool IsTailCall = BC.MIB->isTailCall(Inst);
1666 
1667         const InstructionListType NewCode =
1668             BC.MIB->createInlineMemcpy(IsMemcpy8);
1669         II = BB.replaceInstruction(II, NewCode);
1670         std::advance(II, NewCode.size() - 1);
1671         if (IsTailCall) {
1672           MCInst Return;
1673           BC.MIB->createReturn(Return);
1674           II = BB.insertInstruction(std::next(II), std::move(Return));
1675         }
1676 
1677         ++NumInlined;
1678         NumInlinedDyno += BB.getKnownExecutionCount();
1679       }
1680     }
1681   }
1682 
1683   if (NumInlined) {
1684     outs() << "BOLT-INFO: inlined " << NumInlined << " memcpy() calls";
1685     if (NumInlinedDyno)
1686       outs() << ". The calls were executed " << NumInlinedDyno
1687              << " times based on profile.";
1688     outs() << '\n';
1689   }
1690 }
1691 
1692 bool SpecializeMemcpy1::shouldOptimize(const BinaryFunction &Function) const {
1693   if (!BinaryFunctionPass::shouldOptimize(Function))
1694     return false;
1695 
1696   for (const std::string &FunctionSpec : Spec) {
1697     StringRef FunctionName = StringRef(FunctionSpec).split(':').first;
1698     if (Function.hasNameRegex(FunctionName))
1699       return true;
1700   }
1701 
1702   return false;
1703 }
1704 
1705 std::set<size_t> SpecializeMemcpy1::getCallSitesToOptimize(
1706     const BinaryFunction &Function) const {
1707   StringRef SitesString;
1708   for (const std::string &FunctionSpec : Spec) {
1709     StringRef FunctionName;
1710     std::tie(FunctionName, SitesString) = StringRef(FunctionSpec).split(':');
1711     if (Function.hasNameRegex(FunctionName))
1712       break;
1713     SitesString = "";
1714   }
1715 
1716   std::set<size_t> Sites;
1717   SmallVector<StringRef, 4> SitesVec;
1718   SitesString.split(SitesVec, ':');
1719   for (StringRef SiteString : SitesVec) {
1720     if (SiteString.empty())
1721       continue;
1722     size_t Result;
1723     if (!SiteString.getAsInteger(10, Result))
1724       Sites.emplace(Result);
1725   }
1726 
1727   return Sites;
1728 }
1729 
1730 void SpecializeMemcpy1::runOnFunctions(BinaryContext &BC) {
1731   if (!BC.isX86())
1732     return;
1733 
1734   uint64_t NumSpecialized = 0;
1735   uint64_t NumSpecializedDyno = 0;
1736   for (auto &BFI : BC.getBinaryFunctions()) {
1737     BinaryFunction &Function = BFI.second;
1738     if (!shouldOptimize(Function))
1739       continue;
1740 
1741     std::set<size_t> CallsToOptimize = getCallSitesToOptimize(Function);
1742     auto shouldOptimize = [&](size_t N) {
1743       return CallsToOptimize.empty() || CallsToOptimize.count(N);
1744     };
1745 
1746     std::vector<BinaryBasicBlock *> Blocks(Function.pbegin(), Function.pend());
1747     size_t CallSiteID = 0;
1748     for (BinaryBasicBlock *CurBB : Blocks) {
1749       for (auto II = CurBB->begin(); II != CurBB->end(); ++II) {
1750         MCInst &Inst = *II;
1751 
1752         if (!BC.MIB->isCall(Inst) || MCPlus::getNumPrimeOperands(Inst) != 1 ||
1753             !Inst.getOperand(0).isExpr())
1754           continue;
1755 
1756         const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Inst);
1757         if (CalleeSymbol->getName() != "memcpy" &&
1758             CalleeSymbol->getName() != "memcpy@PLT")
1759           continue;
1760 
1761         if (BC.MIB->isTailCall(Inst))
1762           continue;
1763 
1764         ++CallSiteID;
1765 
1766         if (!shouldOptimize(CallSiteID))
1767           continue;
1768 
1769         // Create a copy of a call to memcpy(dest, src, size).
1770         MCInst MemcpyInstr = Inst;
1771 
1772         BinaryBasicBlock *OneByteMemcpyBB = CurBB->splitAt(II);
1773 
1774         BinaryBasicBlock *NextBB = nullptr;
1775         if (OneByteMemcpyBB->getNumNonPseudos() > 1) {
1776           NextBB = OneByteMemcpyBB->splitAt(OneByteMemcpyBB->begin());
1777           NextBB->eraseInstruction(NextBB->begin());
1778         } else {
1779           NextBB = OneByteMemcpyBB->getSuccessor();
1780           OneByteMemcpyBB->eraseInstruction(OneByteMemcpyBB->begin());
1781           assert(NextBB && "unexpected call to memcpy() with no return");
1782         }
1783 
1784         BinaryBasicBlock *MemcpyBB =
1785             Function.addBasicBlock(CurBB->getInputOffset());
1786         InstructionListType CmpJCC =
1787             BC.MIB->createCmpJE(BC.MIB->getIntArgRegister(2), 1,
1788                                 OneByteMemcpyBB->getLabel(), BC.Ctx.get());
1789         CurBB->addInstructions(CmpJCC);
1790         CurBB->addSuccessor(MemcpyBB);
1791 
1792         MemcpyBB->addInstruction(std::move(MemcpyInstr));
1793         MemcpyBB->addSuccessor(NextBB);
1794         MemcpyBB->setCFIState(NextBB->getCFIState());
1795         MemcpyBB->setExecutionCount(0);
1796 
1797         // To prevent the actual call from being moved to cold, we set its
1798         // execution count to 1.
1799         if (CurBB->getKnownExecutionCount() > 0)
1800           MemcpyBB->setExecutionCount(1);
1801 
1802         InstructionListType OneByteMemcpy = BC.MIB->createOneByteMemcpy();
1803         OneByteMemcpyBB->addInstructions(OneByteMemcpy);
1804 
1805         ++NumSpecialized;
1806         NumSpecializedDyno += CurBB->getKnownExecutionCount();
1807 
1808         CurBB = NextBB;
1809 
1810         // Note: we don't expect the next instruction to be a call to memcpy.
1811         II = CurBB->begin();
1812       }
1813     }
1814   }
1815 
1816   if (NumSpecialized) {
1817     outs() << "BOLT-INFO: specialized " << NumSpecialized
1818            << " memcpy() call sites for size 1";
1819     if (NumSpecializedDyno)
1820       outs() << ". The calls were executed " << NumSpecializedDyno
1821              << " times based on profile.";
1822     outs() << '\n';
1823   }
1824 }
1825 
1826 void RemoveNops::runOnFunction(BinaryFunction &BF) {
1827   const BinaryContext &BC = BF.getBinaryContext();
1828   for (BinaryBasicBlock &BB : BF) {
1829     for (int64_t I = BB.size() - 1; I >= 0; --I) {
1830       MCInst &Inst = BB.getInstructionAtIndex(I);
1831       if (BC.MIB->isNoop(Inst) && BC.MIB->hasAnnotation(Inst, "NOP"))
1832         BB.eraseInstructionAtIndex(I);
1833     }
1834   }
1835 }
1836 
1837 void RemoveNops::runOnFunctions(BinaryContext &BC) {
1838   ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
1839     runOnFunction(BF);
1840   };
1841 
1842   ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
1843     return BF.shouldPreserveNops();
1844   };
1845 
1846   ParallelUtilities::runOnEachFunction(
1847       BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
1848       SkipFunc, "RemoveNops");
1849 }
1850 
1851 } // namespace bolt
1852 } // namespace llvm
1853