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