xref: /llvm-project/bolt/lib/Core/BinaryBasicBlock.cpp (revision f40d25dd8d3ad7bcfa8f5e8f74f245ab1a7675df)
1 //===- bolt/Core/BinaryBasicBlock.cpp - Low-level basic block -------------===//
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 the BinaryBasicBlock class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "bolt/Core/BinaryBasicBlock.h"
14 #include "bolt/Core/BinaryContext.h"
15 #include "bolt/Core/BinaryFunction.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/MC/MCAsmLayout.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/Support/Errc.h"
20 
21 #define DEBUG_TYPE "bolt"
22 
23 namespace llvm {
24 namespace bolt {
25 
26 constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET;
27 
28 bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
29   return LHS.Index < RHS.Index;
30 }
31 
32 bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); }
33 
34 bool BinaryBasicBlock::isEntryPoint() const {
35   return getParent()->isEntryPoint(*this);
36 }
37 
38 bool BinaryBasicBlock::hasInstructions() const {
39   return getParent()->hasInstructions();
40 }
41 
42 const JumpTable *BinaryBasicBlock::getJumpTable() const {
43   const MCInst *Inst = getLastNonPseudoInstr();
44   const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
45   return JT;
46 }
47 
48 void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
49   BinaryContext &BC = Function->getBinaryContext();
50   if (BC.MIB->isPseudo(Inst))
51     NumPseudos += Sign;
52 }
53 
54 BinaryBasicBlock::iterator BinaryBasicBlock::getFirstNonPseudo() {
55   const BinaryContext &BC = Function->getBinaryContext();
56   for (auto II = Instructions.begin(), E = Instructions.end(); II != E; ++II) {
57     if (!BC.MIB->isPseudo(*II))
58       return II;
59   }
60   return end();
61 }
62 
63 BinaryBasicBlock::reverse_iterator BinaryBasicBlock::getLastNonPseudo() {
64   const BinaryContext &BC = Function->getBinaryContext();
65   for (auto RII = Instructions.rbegin(), E = Instructions.rend(); RII != E;
66        ++RII) {
67     if (!BC.MIB->isPseudo(*RII))
68       return RII;
69   }
70   return rend();
71 }
72 
73 bool BinaryBasicBlock::validateSuccessorInvariants() {
74   const MCInst *Inst = getLastNonPseudoInstr();
75   const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
76   BinaryContext &BC = Function->getBinaryContext();
77   bool Valid = true;
78 
79   if (JT) {
80     // Note: for now we assume that successors do not reference labels from
81     // any overlapping jump tables.  We only look at the entries for the jump
82     // table that is referenced at the last instruction.
83     const auto Range = JT->getEntriesForAddress(BC.MIB->getJumpTable(*Inst));
84     const std::vector<const MCSymbol *> Entries(
85         std::next(JT->Entries.begin(), Range.first),
86         std::next(JT->Entries.begin(), Range.second));
87     std::set<const MCSymbol *> UniqueSyms(Entries.begin(), Entries.end());
88     for (BinaryBasicBlock *Succ : Successors) {
89       auto Itr = UniqueSyms.find(Succ->getLabel());
90       if (Itr != UniqueSyms.end()) {
91         UniqueSyms.erase(Itr);
92       } else {
93         // Work on the assumption that jump table blocks don't
94         // have a conditional successor.
95         Valid = false;
96         errs() << "BOLT-WARNING: Jump table successor " << Succ->getName()
97                << " not contained in the jump table.\n";
98       }
99     }
100     // If there are any leftover entries in the jump table, they
101     // must be one of the function end labels.
102     if (Valid) {
103       for (const MCSymbol *Sym : UniqueSyms) {
104         Valid &= (Sym == Function->getFunctionEndLabel() ||
105                   Sym == Function->getFunctionEndLabel(getFragmentNum()));
106         if (!Valid) {
107           errs() << "BOLT-WARNING: Jump table contains illegal entry: "
108                  << Sym->getName() << "\n";
109         }
110       }
111     }
112   } else {
113     // Unknown control flow.
114     if (Inst && BC.MIB->isIndirectBranch(*Inst))
115       return true;
116 
117     const MCSymbol *TBB = nullptr;
118     const MCSymbol *FBB = nullptr;
119     MCInst *CondBranch = nullptr;
120     MCInst *UncondBranch = nullptr;
121 
122     if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
123       switch (Successors.size()) {
124       case 0:
125         Valid = !CondBranch && !UncondBranch;
126         break;
127       case 1: {
128         const bool HasCondBlock =
129             CondBranch && Function->getBasicBlockForLabel(
130                               BC.MIB->getTargetSymbol(*CondBranch));
131         Valid = !CondBranch || !HasCondBlock;
132         break;
133       }
134       case 2:
135         Valid = (CondBranch &&
136                  (TBB == getConditionalSuccessor(true)->getLabel() &&
137                   ((!UncondBranch && !FBB) ||
138                    (UncondBranch &&
139                     FBB == getConditionalSuccessor(false)->getLabel()))));
140         break;
141       }
142     }
143   }
144   if (!Valid) {
145     errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
146            << getName() << "\n";
147     if (JT) {
148       errs() << "Jump Table instruction addr = 0x"
149              << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
150       JT->print(errs());
151     }
152     getFunction()->dump();
153   }
154   return Valid;
155 }
156 
157 BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
158   if (!Label && succ_size() == 1)
159     return *succ_begin();
160 
161   for (BinaryBasicBlock *BB : successors())
162     if (BB->getLabel() == Label)
163       return BB;
164 
165   return nullptr;
166 }
167 
168 BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label,
169                                                  BinaryBranchInfo &BI) const {
170   auto BIIter = branch_info_begin();
171   for (BinaryBasicBlock *BB : successors()) {
172     if (BB->getLabel() == Label) {
173       BI = *BIIter;
174       return BB;
175     }
176     ++BIIter;
177   }
178 
179   return nullptr;
180 }
181 
182 BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
183   for (BinaryBasicBlock *BB : landing_pads())
184     if (BB->getLabel() == Label)
185       return BB;
186 
187   return nullptr;
188 }
189 
190 int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const {
191   assert(
192       getFunction()->getState() >= BinaryFunction::State::CFG &&
193       "can only calculate CFI state when function is in or past the CFG state");
194 
195   const BinaryFunction::CFIInstrMapType &FDEProgram =
196       getFunction()->getFDEProgram();
197 
198   // Find the last CFI preceding Instr in this basic block.
199   const MCInst *LastCFI = nullptr;
200   bool InstrSeen = (Instr == nullptr);
201   for (const MCInst &Inst : llvm::reverse(Instructions)) {
202     if (!InstrSeen) {
203       InstrSeen = (&Inst == Instr);
204       continue;
205     }
206     if (Function->getBinaryContext().MIB->isCFI(Inst)) {
207       LastCFI = &Inst;
208       break;
209     }
210   }
211 
212   assert(InstrSeen && "instruction expected in basic block");
213 
214   // CFI state is the same as at basic block entry point.
215   if (!LastCFI)
216     return getCFIState();
217 
218   // Fold all RememberState/RestoreState sequences, such as for:
219   //
220   //   [ CFI #(K-1) ]
221   //   RememberState (#K)
222   //     ....
223   //   RestoreState
224   //   RememberState
225   //     ....
226   //   RestoreState
227   //   [ GNU_args_size ]
228   //   RememberState
229   //     ....
230   //   RestoreState   <- LastCFI
231   //
232   // we return K - the most efficient state to (re-)generate.
233   int64_t State = LastCFI->getOperand(0).getImm();
234   while (State >= 0 &&
235          FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) {
236     int32_t Depth = 1;
237     --State;
238     assert(State >= 0 && "first CFI cannot be RestoreState");
239     while (Depth && State >= 0) {
240       const MCCFIInstruction &CFIInstr = FDEProgram[State];
241       if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState)
242         ++Depth;
243       else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState)
244         --Depth;
245       --State;
246     }
247     assert(Depth == 0 && "unbalanced RememberState/RestoreState stack");
248 
249     // Skip any GNU_args_size.
250     while (State >= 0 && FDEProgram[State].getOperation() ==
251                              MCCFIInstruction::OpGnuArgsSize) {
252       --State;
253     }
254   }
255 
256   assert((State + 1 >= 0) && "miscalculated CFI state");
257   return State + 1;
258 }
259 
260 void BinaryBasicBlock::addSuccessor(BinaryBasicBlock *Succ, uint64_t Count,
261                                     uint64_t MispredictedCount) {
262   Successors.push_back(Succ);
263   BranchInfo.push_back({Count, MispredictedCount});
264   Succ->Predecessors.push_back(this);
265 }
266 
267 void BinaryBasicBlock::replaceSuccessor(BinaryBasicBlock *Succ,
268                                         BinaryBasicBlock *NewSucc,
269                                         uint64_t Count,
270                                         uint64_t MispredictedCount) {
271   Succ->removePredecessor(this, /*Multiple=*/false);
272   auto I = succ_begin();
273   auto BI = BranchInfo.begin();
274   for (; I != succ_end(); ++I) {
275     assert(BI != BranchInfo.end() && "missing BranchInfo entry");
276     if (*I == Succ)
277       break;
278     ++BI;
279   }
280   assert(I != succ_end() && "no such successor!");
281 
282   *I = NewSucc;
283   *BI = BinaryBranchInfo{Count, MispredictedCount};
284   NewSucc->addPredecessor(this);
285 }
286 
287 void BinaryBasicBlock::removeAllSuccessors() {
288   SmallPtrSet<BinaryBasicBlock *, 2> UniqSuccessors(succ_begin(), succ_end());
289   for (BinaryBasicBlock *SuccessorBB : UniqSuccessors)
290     SuccessorBB->removePredecessor(this);
291   Successors.clear();
292   BranchInfo.clear();
293 }
294 
295 void BinaryBasicBlock::removeSuccessor(BinaryBasicBlock *Succ) {
296   Succ->removePredecessor(this, /*Multiple=*/false);
297   auto I = succ_begin();
298   auto BI = BranchInfo.begin();
299   for (; I != succ_end(); ++I) {
300     assert(BI != BranchInfo.end() && "missing BranchInfo entry");
301     if (*I == Succ)
302       break;
303     ++BI;
304   }
305   assert(I != succ_end() && "no such successor!");
306 
307   Successors.erase(I);
308   BranchInfo.erase(BI);
309 }
310 
311 void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
312   Predecessors.push_back(Pred);
313 }
314 
315 void BinaryBasicBlock::removePredecessor(BinaryBasicBlock *Pred,
316                                          bool Multiple) {
317   // Note: the predecessor could be listed multiple times.
318   bool Erased = false;
319   for (auto PredI = Predecessors.begin(); PredI != Predecessors.end();) {
320     if (*PredI == Pred) {
321       Erased = true;
322       PredI = Predecessors.erase(PredI);
323       if (!Multiple)
324         return;
325     } else {
326       ++PredI;
327     }
328   }
329   assert(Erased && "Pred is not a predecessor of this block!");
330   (void)Erased;
331 }
332 
333 void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) {
334   assert(succ_size() == 2 && Successors[0] == Successors[1] &&
335          "conditional successors expected");
336 
337   BinaryBasicBlock *Succ = Successors[0];
338   const BinaryBranchInfo CondBI = BranchInfo[0];
339   const BinaryBranchInfo UncondBI = BranchInfo[1];
340 
341   eraseInstruction(findInstruction(CondBranch));
342 
343   Successors.clear();
344   BranchInfo.clear();
345 
346   Successors.push_back(Succ);
347 
348   uint64_t Count = COUNT_NO_PROFILE;
349   if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE)
350     Count = CondBI.Count + UncondBI.Count;
351   BranchInfo.push_back({Count, 0});
352 }
353 
354 void BinaryBasicBlock::updateJumpTableSuccessors() {
355   const JumpTable *JT = getJumpTable();
356   assert(JT && "Expected jump table instruction.");
357 
358   // Clear existing successors.
359   removeAllSuccessors();
360 
361   // Generate the list of successors in deterministic order without duplicates.
362   SmallVector<BinaryBasicBlock *, 16> SuccessorBBs;
363   for (const MCSymbol *Label : JT->Entries) {
364     BinaryBasicBlock *BB = getFunction()->getBasicBlockForLabel(Label);
365     // Ignore __builtin_unreachable()
366     if (!BB) {
367       assert(Label == getFunction()->getFunctionEndLabel() &&
368              "JT label should match a block or end of function.");
369       continue;
370     }
371     SuccessorBBs.emplace_back(BB);
372   }
373   llvm::sort(SuccessorBBs,
374              [](const BinaryBasicBlock *BB1, const BinaryBasicBlock *BB2) {
375                return BB1->getInputOffset() < BB2->getInputOffset();
376              });
377   SuccessorBBs.erase(std::unique(SuccessorBBs.begin(), SuccessorBBs.end()),
378                      SuccessorBBs.end());
379 
380   for (BinaryBasicBlock *BB : SuccessorBBs)
381     addSuccessor(BB);
382 }
383 
384 void BinaryBasicBlock::adjustExecutionCount(double Ratio) {
385   auto adjustedCount = [&](uint64_t Count) -> uint64_t {
386     double NewCount = Count * Ratio;
387     if (!NewCount && Count && (Ratio > 0.0))
388       NewCount = 1;
389     return NewCount;
390   };
391 
392   setExecutionCount(adjustedCount(getKnownExecutionCount()));
393   for (BinaryBranchInfo &BI : branch_info()) {
394     if (BI.Count != COUNT_NO_PROFILE)
395       BI.Count = adjustedCount(BI.Count);
396     if (BI.MispredictedCount != COUNT_INFERRED)
397       BI.MispredictedCount = adjustedCount(BI.MispredictedCount);
398   }
399 }
400 
401 bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB, const MCSymbol *&FBB,
402                                      MCInst *&CondBranch,
403                                      MCInst *&UncondBranch) {
404   auto &MIB = Function->getBinaryContext().MIB;
405   return MIB->analyzeBranch(Instructions.begin(), Instructions.end(), TBB, FBB,
406                             CondBranch, UncondBranch);
407 }
408 
409 bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const {
410   auto &MIB = Function->getBinaryContext().MIB;
411   ArrayRef<MCInst> Insts = Instructions;
412   return MIB->isMacroOpFusionPair(Insts.slice(I - begin()));
413 }
414 
415 BinaryBasicBlock::const_iterator
416 BinaryBasicBlock::getMacroOpFusionPair() const {
417   if (!Function->getBinaryContext().isX86())
418     return end();
419 
420   if (getNumNonPseudos() < 2 || succ_size() != 2)
421     return end();
422 
423   auto RI = getLastNonPseudo();
424   assert(RI != rend() && "cannot have an empty block with 2 successors");
425 
426   BinaryContext &BC = Function->getBinaryContext();
427 
428   // Skip instruction if it's an unconditional branch following
429   // a conditional one.
430   if (BC.MIB->isUnconditionalBranch(*RI))
431     ++RI;
432 
433   if (!BC.MIB->isConditionalBranch(*RI))
434     return end();
435 
436   // Start checking with instruction preceding the conditional branch.
437   ++RI;
438   if (RI == rend())
439     return end();
440 
441   auto II = std::prev(RI.base()); // convert to a forward iterator
442   if (isMacroOpFusionPair(II))
443     return II;
444 
445   return end();
446 }
447 
448 MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) {
449   BinaryContext &BC = Function->getBinaryContext();
450   auto Itr = rbegin();
451   bool Check = Pos ? false : true;
452   MCInst *FirstTerminator = nullptr;
453   while (Itr != rend()) {
454     if (!Check) {
455       if (&*Itr == Pos)
456         Check = true;
457       ++Itr;
458       continue;
459     }
460     if (BC.MIB->isTerminator(*Itr))
461       FirstTerminator = &*Itr;
462     ++Itr;
463   }
464   return FirstTerminator;
465 }
466 
467 bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) {
468   BinaryContext &BC = Function->getBinaryContext();
469   auto Itr = rbegin();
470   while (Itr != rend()) {
471     if (&*Itr == Pos)
472       return false;
473     if (BC.MIB->isTerminator(*Itr))
474       return true;
475     ++Itr;
476   }
477   return false;
478 }
479 
480 bool BinaryBasicBlock::swapConditionalSuccessors() {
481   if (succ_size() != 2)
482     return false;
483 
484   std::swap(Successors[0], Successors[1]);
485   std::swap(BranchInfo[0], BranchInfo[1]);
486   return true;
487 }
488 
489 void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) {
490   assert(isSuccessor(Successor));
491   BinaryContext &BC = Function->getBinaryContext();
492   MCInst NewInst;
493   std::unique_lock<llvm::sys::RWMutex> Lock(BC.CtxMutex);
494   BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
495   Instructions.emplace_back(std::move(NewInst));
496 }
497 
498 void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
499   BinaryContext &BC = Function->getBinaryContext();
500   MCInst NewInst;
501   BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get());
502   Instructions.emplace_back(std::move(NewInst));
503 }
504 
505 uint32_t BinaryBasicBlock::getNumCalls() const {
506   uint32_t N = 0;
507   BinaryContext &BC = Function->getBinaryContext();
508   for (const MCInst &Instr : Instructions) {
509     if (BC.MIB->isCall(Instr))
510       ++N;
511   }
512   return N;
513 }
514 
515 uint32_t BinaryBasicBlock::getNumPseudos() const {
516 #ifndef NDEBUG
517   BinaryContext &BC = Function->getBinaryContext();
518   uint32_t N = 0;
519   for (const MCInst &Instr : Instructions)
520     if (BC.MIB->isPseudo(Instr))
521       ++N;
522 
523   if (N != NumPseudos) {
524     errs() << "BOLT-ERROR: instructions for basic block " << getName()
525            << " in function " << *Function << ": calculated pseudos " << N
526            << ", set pseudos " << NumPseudos << ", size " << size() << '\n';
527     llvm_unreachable("pseudos mismatch");
528   }
529 #endif
530   return NumPseudos;
531 }
532 
533 ErrorOr<std::pair<double, double>>
534 BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
535   if (Function->hasValidProfile()) {
536     uint64_t TotalCount = 0;
537     uint64_t TotalMispreds = 0;
538     for (const BinaryBranchInfo &BI : BranchInfo) {
539       if (BI.Count != COUNT_NO_PROFILE) {
540         TotalCount += BI.Count;
541         TotalMispreds += BI.MispredictedCount;
542       }
543     }
544 
545     if (TotalCount > 0) {
546       auto Itr = llvm::find(Successors, Succ);
547       assert(Itr != Successors.end());
548       const BinaryBranchInfo &BI = BranchInfo[Itr - Successors.begin()];
549       if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
550         if (TotalMispreds == 0)
551           TotalMispreds = 1;
552         return std::make_pair(double(BI.Count) / TotalCount,
553                               double(BI.MispredictedCount) / TotalMispreds);
554       }
555     }
556   }
557   return make_error_code(llvm::errc::result_out_of_range);
558 }
559 
560 void BinaryBasicBlock::dump() const {
561   BinaryContext &BC = Function->getBinaryContext();
562   if (Label)
563     outs() << Label->getName() << ":\n";
564   BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
565                        getOffset(), Function);
566   outs() << "preds:";
567   for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
568     outs() << " " << (*itr)->getName();
569   }
570   outs() << "\nsuccs:";
571   for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
572     outs() << " " << (*itr)->getName();
573   }
574   outs() << "\n";
575 }
576 
577 uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
578   return Function->getBinaryContext().computeCodeSize(begin(), end(), Emitter);
579 }
580 
581 BinaryBasicBlock::BinaryBranchInfo &
582 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
583   return const_cast<BinaryBranchInfo &>(
584       static_cast<const BinaryBasicBlock &>(*this).getBranchInfo(Succ));
585 }
586 
587 const BinaryBasicBlock::BinaryBranchInfo &
588 BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) const {
589   const auto Zip = llvm::zip(successors(), branch_info());
590   const auto Result = llvm::find_if(
591       Zip, [&](const auto &Tuple) { return std::get<0>(Tuple) == &Succ; });
592   assert(Result != Zip.end() && "Cannot find target in successors");
593   return std::get<1>(*Result);
594 }
595 
596 BinaryBasicBlock::BinaryBranchInfo &
597 BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) {
598   auto BI = branch_info_begin();
599   for (BinaryBasicBlock *BB : successors()) {
600     if (BB->getLabel() == Label)
601       return *BI;
602     ++BI;
603   }
604 
605   llvm_unreachable("Invalid successor");
606   return *BI;
607 }
608 
609 BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
610   assert(II != end() && "expected iterator pointing to instruction");
611 
612   BinaryBasicBlock *NewBlock = getFunction()->addBasicBlock();
613 
614   // Adjust successors/predecessors and propagate the execution count.
615   moveAllSuccessorsTo(NewBlock);
616   addSuccessor(NewBlock, getExecutionCount(), 0);
617 
618   // Set correct CFI state for the new block.
619   NewBlock->setCFIState(getCFIStateAtInstr(&*II));
620 
621   // Move instructions over.
622   adjustNumPseudos(II, end(), -1);
623   NewBlock->addInstructions(II, end());
624   Instructions.erase(II, end());
625 
626   return NewBlock;
627 }
628 
629 void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) {
630   if (!LocSyms)
631     return;
632 
633   const uint64_t BBAddress = getOutputAddressRange().first;
634   const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel());
635   for (const auto &LocSymKV : *LocSyms) {
636     const uint32_t InputFunctionOffset = LocSymKV.first;
637     const uint32_t OutputOffset = static_cast<uint32_t>(
638         Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
639     getOffsetTranslationTable().emplace_back(
640         std::make_pair(OutputOffset, InputFunctionOffset));
641 
642     // Update reverse (relative to BAT) address lookup table for function.
643     if (getFunction()->requiresAddressTranslation()) {
644       getFunction()->getInputOffsetToAddressMap().emplace(
645           std::make_pair(InputFunctionOffset, OutputOffset + BBAddress));
646     }
647   }
648   LocSyms.reset(nullptr);
649 }
650 
651 } // namespace bolt
652 } // namespace llvm
653