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