12f09f445SMaksim Panchenko //===- bolt/Core/BinaryBasicBlock.cpp - Low-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 //
92f09f445SMaksim Panchenko // This file implements the BinaryBasicBlock class.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler
13a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h"
14a34c753fSRafael Auler #include "bolt/Core/BinaryContext.h"
15a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h"
166bb26fcbSAmir Ayupov #include "llvm/ADT/SmallPtrSet.h"
17a34c753fSRafael Auler #include "llvm/MC/MCAsmLayout.h"
18a34c753fSRafael Auler #include "llvm/MC/MCInst.h"
19a34c753fSRafael Auler #include "llvm/Support/Errc.h"
20a34c753fSRafael Auler
21a34c753fSRafael Auler #define DEBUG_TYPE "bolt"
22a34c753fSRafael Auler
23a34c753fSRafael Auler namespace llvm {
24a34c753fSRafael Auler namespace bolt {
25a34c753fSRafael Auler
26a34c753fSRafael Auler constexpr uint32_t BinaryBasicBlock::INVALID_OFFSET;
27a34c753fSRafael Auler
operator <(const BinaryBasicBlock & LHS,const BinaryBasicBlock & RHS)28a34c753fSRafael Auler bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) {
29a34c753fSRafael Auler return LHS.Index < RHS.Index;
30a34c753fSRafael Auler }
31a34c753fSRafael Auler
hasCFG() const3240c2e0faSMaksim Panchenko bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); }
33a34c753fSRafael Auler
isEntryPoint() const34a34c753fSRafael Auler bool BinaryBasicBlock::isEntryPoint() const {
35a34c753fSRafael Auler return getParent()->isEntryPoint(*this);
36a34c753fSRafael Auler }
37a34c753fSRafael Auler
hasInstructions() const38a34c753fSRafael Auler bool BinaryBasicBlock::hasInstructions() const {
39a34c753fSRafael Auler return getParent()->hasInstructions();
40a34c753fSRafael Auler }
41a34c753fSRafael Auler
getJumpTable() const425a343994SMaksim Panchenko const JumpTable *BinaryBasicBlock::getJumpTable() const {
43a34c753fSRafael Auler const MCInst *Inst = getLastNonPseudoInstr();
44a34c753fSRafael Auler const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
455a343994SMaksim Panchenko return JT;
46a34c753fSRafael Auler }
47a34c753fSRafael Auler
adjustNumPseudos(const MCInst & Inst,int Sign)48a34c753fSRafael Auler void BinaryBasicBlock::adjustNumPseudos(const MCInst &Inst, int Sign) {
49a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
50a34c753fSRafael Auler if (BC.MIB->isPseudo(Inst))
51a34c753fSRafael Auler NumPseudos += Sign;
52a34c753fSRafael Auler }
53a34c753fSRafael Auler
getFirstNonPseudo()54a34c753fSRafael Auler BinaryBasicBlock::iterator BinaryBasicBlock::getFirstNonPseudo() {
55a34c753fSRafael Auler const BinaryContext &BC = Function->getBinaryContext();
56a34c753fSRafael Auler for (auto II = Instructions.begin(), E = Instructions.end(); II != E; ++II) {
57a34c753fSRafael Auler if (!BC.MIB->isPseudo(*II))
58a34c753fSRafael Auler return II;
59a34c753fSRafael Auler }
60a34c753fSRafael Auler return end();
61a34c753fSRafael Auler }
62a34c753fSRafael Auler
getLastNonPseudo()63a34c753fSRafael Auler BinaryBasicBlock::reverse_iterator BinaryBasicBlock::getLastNonPseudo() {
64a34c753fSRafael Auler const BinaryContext &BC = Function->getBinaryContext();
6540c2e0faSMaksim Panchenko for (auto RII = Instructions.rbegin(), E = Instructions.rend(); RII != E;
6640c2e0faSMaksim Panchenko ++RII) {
67a34c753fSRafael Auler if (!BC.MIB->isPseudo(*RII))
68a34c753fSRafael Auler return RII;
69a34c753fSRafael Auler }
70a34c753fSRafael Auler return rend();
71a34c753fSRafael Auler }
72a34c753fSRafael Auler
validateSuccessorInvariants()73a34c753fSRafael Auler bool BinaryBasicBlock::validateSuccessorInvariants() {
74a34c753fSRafael Auler const MCInst *Inst = getLastNonPseudoInstr();
75a34c753fSRafael Auler const JumpTable *JT = Inst ? Function->getJumpTable(*Inst) : nullptr;
76a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
77a34c753fSRafael Auler bool Valid = true;
78a34c753fSRafael Auler
79a34c753fSRafael Auler if (JT) {
80a34c753fSRafael Auler // Note: for now we assume that successors do not reference labels from
81a34c753fSRafael Auler // any overlapping jump tables. We only look at the entries for the jump
82a34c753fSRafael Auler // table that is referenced at the last instruction.
83a34c753fSRafael Auler const auto Range = JT->getEntriesForAddress(BC.MIB->getJumpTable(*Inst));
84ae585be1SRafael Auler const std::vector<const MCSymbol *> Entries(
85ae585be1SRafael Auler std::next(JT->Entries.begin(), Range.first),
86ae585be1SRafael Auler std::next(JT->Entries.begin(), Range.second));
87a34c753fSRafael Auler std::set<const MCSymbol *> UniqueSyms(Entries.begin(), Entries.end());
88a34c753fSRafael Auler for (BinaryBasicBlock *Succ : Successors) {
89a34c753fSRafael Auler auto Itr = UniqueSyms.find(Succ->getLabel());
90a34c753fSRafael Auler if (Itr != UniqueSyms.end()) {
91a34c753fSRafael Auler UniqueSyms.erase(Itr);
92a34c753fSRafael Auler } else {
93a34c753fSRafael Auler // Work on the assumption that jump table blocks don't
94a34c753fSRafael Auler // have a conditional successor.
95a34c753fSRafael Auler Valid = false;
9640c2e0faSMaksim Panchenko errs() << "BOLT-WARNING: Jump table successor " << Succ->getName()
97a34c753fSRafael Auler << " not contained in the jump table.\n";
98a34c753fSRafael Auler }
99a34c753fSRafael Auler }
100a34c753fSRafael Auler // If there are any leftover entries in the jump table, they
101a34c753fSRafael Auler // must be one of the function end labels.
102a34c753fSRafael Auler if (Valid) {
103a34c753fSRafael Auler for (const MCSymbol *Sym : UniqueSyms) {
104a34c753fSRafael Auler Valid &= (Sym == Function->getFunctionEndLabel() ||
105a34c753fSRafael Auler Sym == Function->getFunctionColdEndLabel());
106a34c753fSRafael Auler if (!Valid) {
107a34c753fSRafael Auler errs() << "BOLT-WARNING: Jump table contains illegal entry: "
108a34c753fSRafael Auler << Sym->getName() << "\n";
109a34c753fSRafael Auler }
110a34c753fSRafael Auler }
111a34c753fSRafael Auler }
112a34c753fSRafael Auler } else {
113a34c753fSRafael Auler // Unknown control flow.
114a34c753fSRafael Auler if (Inst && BC.MIB->isIndirectBranch(*Inst))
115a34c753fSRafael Auler return true;
116a34c753fSRafael Auler
117a34c753fSRafael Auler const MCSymbol *TBB = nullptr;
118a34c753fSRafael Auler const MCSymbol *FBB = nullptr;
119a34c753fSRafael Auler MCInst *CondBranch = nullptr;
120a34c753fSRafael Auler MCInst *UncondBranch = nullptr;
121a34c753fSRafael Auler
122a34c753fSRafael Auler if (analyzeBranch(TBB, FBB, CondBranch, UncondBranch)) {
123a34c753fSRafael Auler switch (Successors.size()) {
124a34c753fSRafael Auler case 0:
125a34c753fSRafael Auler Valid = !CondBranch && !UncondBranch;
126a34c753fSRafael Auler break;
127a34c753fSRafael Auler case 1: {
12840c2e0faSMaksim Panchenko const bool HasCondBlock =
12940c2e0faSMaksim Panchenko CondBranch && Function->getBasicBlockForLabel(
13040c2e0faSMaksim Panchenko BC.MIB->getTargetSymbol(*CondBranch));
131a34c753fSRafael Auler Valid = !CondBranch || !HasCondBlock;
132a34c753fSRafael Auler break;
133a34c753fSRafael Auler }
134a34c753fSRafael Auler case 2:
13540c2e0faSMaksim Panchenko Valid = (CondBranch &&
136a34c753fSRafael Auler (TBB == getConditionalSuccessor(true)->getLabel() &&
137a34c753fSRafael Auler ((!UncondBranch && !FBB) ||
138a34c753fSRafael Auler (UncondBranch &&
139a34c753fSRafael Auler FBB == getConditionalSuccessor(false)->getLabel()))));
140a34c753fSRafael Auler break;
141a34c753fSRafael Auler }
142a34c753fSRafael Auler }
143a34c753fSRafael Auler }
144a34c753fSRafael Auler if (!Valid) {
145a34c753fSRafael Auler errs() << "BOLT-WARNING: CFG invalid in " << *getFunction() << " @ "
146a34c753fSRafael Auler << getName() << "\n";
147a34c753fSRafael Auler if (JT) {
148a34c753fSRafael Auler errs() << "Jump Table instruction addr = 0x"
149a34c753fSRafael Auler << Twine::utohexstr(BC.MIB->getJumpTable(*Inst)) << "\n";
150a34c753fSRafael Auler JT->print(errs());
151a34c753fSRafael Auler }
152a34c753fSRafael Auler getFunction()->dump();
153a34c753fSRafael Auler }
154a34c753fSRafael Auler return Valid;
155a34c753fSRafael Auler }
156a34c753fSRafael Auler
getSuccessor(const MCSymbol * Label) const157a34c753fSRafael Auler BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label) const {
158a34c753fSRafael Auler if (!Label && succ_size() == 1)
159a34c753fSRafael Auler return *succ_begin();
160a34c753fSRafael Auler
1613652483cSRafael Auler for (BinaryBasicBlock *BB : successors())
162a34c753fSRafael Auler if (BB->getLabel() == Label)
163a34c753fSRafael Auler return BB;
164a34c753fSRafael Auler
165a34c753fSRafael Auler return nullptr;
166a34c753fSRafael Auler }
167a34c753fSRafael Auler
getSuccessor(const MCSymbol * Label,BinaryBranchInfo & BI) const16840c2e0faSMaksim Panchenko BinaryBasicBlock *BinaryBasicBlock::getSuccessor(const MCSymbol *Label,
169a34c753fSRafael Auler BinaryBranchInfo &BI) const {
170a34c753fSRafael Auler auto BIIter = branch_info_begin();
171a34c753fSRafael Auler for (BinaryBasicBlock *BB : successors()) {
172a34c753fSRafael Auler if (BB->getLabel() == Label) {
173a34c753fSRafael Auler BI = *BIIter;
174a34c753fSRafael Auler return BB;
175a34c753fSRafael Auler }
176a34c753fSRafael Auler ++BIIter;
177a34c753fSRafael Auler }
178a34c753fSRafael Auler
179a34c753fSRafael Auler return nullptr;
180a34c753fSRafael Auler }
181a34c753fSRafael Auler
getLandingPad(const MCSymbol * Label) const182a34c753fSRafael Auler BinaryBasicBlock *BinaryBasicBlock::getLandingPad(const MCSymbol *Label) const {
1833652483cSRafael Auler for (BinaryBasicBlock *BB : landing_pads())
184a34c753fSRafael Auler if (BB->getLabel() == Label)
185a34c753fSRafael Auler return BB;
186a34c753fSRafael Auler
187a34c753fSRafael Auler return nullptr;
188a34c753fSRafael Auler }
189a34c753fSRafael Auler
getCFIStateAtInstr(const MCInst * Instr) const190a34c753fSRafael Auler int32_t BinaryBasicBlock::getCFIStateAtInstr(const MCInst *Instr) const {
191a34c753fSRafael Auler assert(
192a34c753fSRafael Auler getFunction()->getState() >= BinaryFunction::State::CFG &&
193a34c753fSRafael Auler "can only calculate CFI state when function is in or past the CFG state");
194a34c753fSRafael Auler
195ebe51c4dSMaksim Panchenko const BinaryFunction::CFIInstrMapType &FDEProgram =
196a34c753fSRafael Auler getFunction()->getFDEProgram();
197a34c753fSRafael Auler
198a34c753fSRafael Auler // Find the last CFI preceding Instr in this basic block.
199a34c753fSRafael Auler const MCInst *LastCFI = nullptr;
200a34c753fSRafael Auler bool InstrSeen = (Instr == nullptr);
20140c2e0faSMaksim Panchenko for (auto RII = Instructions.rbegin(), E = Instructions.rend(); RII != E;
20240c2e0faSMaksim Panchenko ++RII) {
203a34c753fSRafael Auler if (!InstrSeen) {
204a34c753fSRafael Auler InstrSeen = (&*RII == Instr);
205a34c753fSRafael Auler continue;
206a34c753fSRafael Auler }
207a34c753fSRafael Auler if (Function->getBinaryContext().MIB->isCFI(*RII)) {
208a34c753fSRafael Auler LastCFI = &*RII;
209a34c753fSRafael Auler break;
210a34c753fSRafael Auler }
211a34c753fSRafael Auler }
212a34c753fSRafael Auler
213a34c753fSRafael Auler assert(InstrSeen && "instruction expected in basic block");
214a34c753fSRafael Auler
215a34c753fSRafael Auler // CFI state is the same as at basic block entry point.
216a34c753fSRafael Auler if (!LastCFI)
217a34c753fSRafael Auler return getCFIState();
218a34c753fSRafael Auler
219a34c753fSRafael Auler // Fold all RememberState/RestoreState sequences, such as for:
220a34c753fSRafael Auler //
221a34c753fSRafael Auler // [ CFI #(K-1) ]
222a34c753fSRafael Auler // RememberState (#K)
223a34c753fSRafael Auler // ....
224a34c753fSRafael Auler // RestoreState
225a34c753fSRafael Auler // RememberState
226a34c753fSRafael Auler // ....
227a34c753fSRafael Auler // RestoreState
228a34c753fSRafael Auler // [ GNU_args_size ]
229a34c753fSRafael Auler // RememberState
230a34c753fSRafael Auler // ....
231a34c753fSRafael Auler // RestoreState <- LastCFI
232a34c753fSRafael Auler //
233a34c753fSRafael Auler // we return K - the most efficient state to (re-)generate.
234a34c753fSRafael Auler int64_t State = LastCFI->getOperand(0).getImm();
235a34c753fSRafael Auler while (State >= 0 &&
236a34c753fSRafael Auler FDEProgram[State].getOperation() == MCCFIInstruction::OpRestoreState) {
237a34c753fSRafael Auler int32_t Depth = 1;
238a34c753fSRafael Auler --State;
239a34c753fSRafael Auler assert(State >= 0 && "first CFI cannot be RestoreState");
240a34c753fSRafael Auler while (Depth && State >= 0) {
241a34c753fSRafael Auler const MCCFIInstruction &CFIInstr = FDEProgram[State];
2423652483cSRafael Auler if (CFIInstr.getOperation() == MCCFIInstruction::OpRestoreState)
243a34c753fSRafael Auler ++Depth;
2443652483cSRafael Auler else if (CFIInstr.getOperation() == MCCFIInstruction::OpRememberState)
245a34c753fSRafael Auler --Depth;
246a34c753fSRafael Auler --State;
247a34c753fSRafael Auler }
248a34c753fSRafael Auler assert(Depth == 0 && "unbalanced RememberState/RestoreState stack");
249a34c753fSRafael Auler
250a34c753fSRafael Auler // Skip any GNU_args_size.
25140c2e0faSMaksim Panchenko while (State >= 0 && FDEProgram[State].getOperation() ==
25240c2e0faSMaksim 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
addSuccessor(BinaryBasicBlock * Succ,uint64_t Count,uint64_t MispredictedCount)26140c2e0faSMaksim 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
replaceSuccessor(BinaryBasicBlock * Succ,BinaryBasicBlock * NewSucc,uint64_t Count,uint64_t MispredictedCount)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
removeAllSuccessors()288a34c753fSRafael Auler void BinaryBasicBlock::removeAllSuccessors() {
2896bb26fcbSAmir Ayupov SmallPtrSet<BinaryBasicBlock *, 2> UniqSuccessors(succ_begin(), succ_end());
2906bb26fcbSAmir Ayupov for (BinaryBasicBlock *SuccessorBB : UniqSuccessors)
291a34c753fSRafael Auler SuccessorBB->removePredecessor(this);
292a34c753fSRafael Auler Successors.clear();
293a34c753fSRafael Auler BranchInfo.clear();
294a34c753fSRafael Auler }
295a34c753fSRafael Auler
removeSuccessor(BinaryBasicBlock * Succ)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
addPredecessor(BinaryBasicBlock * Pred)312a34c753fSRafael Auler void BinaryBasicBlock::addPredecessor(BinaryBasicBlock *Pred) {
313a34c753fSRafael Auler Predecessors.push_back(Pred);
314a34c753fSRafael Auler }
315a34c753fSRafael Auler
removePredecessor(BinaryBasicBlock * Pred,bool Multiple)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!");
331c907d6e0SAmir Ayupov (void)Erased;
332a34c753fSRafael Auler }
333a34c753fSRafael Auler
removeDuplicateConditionalSuccessor(MCInst * CondBranch)334a34c753fSRafael Auler void BinaryBasicBlock::removeDuplicateConditionalSuccessor(MCInst *CondBranch) {
335a34c753fSRafael Auler assert(succ_size() == 2 && Successors[0] == Successors[1] &&
336a34c753fSRafael Auler "conditional successors expected");
337a34c753fSRafael Auler
338a34c753fSRafael Auler BinaryBasicBlock *Succ = Successors[0];
339a34c753fSRafael Auler const BinaryBranchInfo CondBI = BranchInfo[0];
340a34c753fSRafael Auler const BinaryBranchInfo UncondBI = BranchInfo[1];
341a34c753fSRafael Auler
342a34c753fSRafael Auler eraseInstruction(findInstruction(CondBranch));
343a34c753fSRafael Auler
344a34c753fSRafael Auler Successors.clear();
345a34c753fSRafael Auler BranchInfo.clear();
346a34c753fSRafael Auler
347a34c753fSRafael Auler Successors.push_back(Succ);
348a34c753fSRafael Auler
349a34c753fSRafael Auler uint64_t Count = COUNT_NO_PROFILE;
350a34c753fSRafael Auler if (CondBI.Count != COUNT_NO_PROFILE && UncondBI.Count != COUNT_NO_PROFILE)
351a34c753fSRafael Auler Count = CondBI.Count + UncondBI.Count;
352a34c753fSRafael Auler BranchInfo.push_back({Count, 0});
353a34c753fSRafael Auler }
354a34c753fSRafael Auler
updateJumpTableSuccessors()3555a343994SMaksim Panchenko void BinaryBasicBlock::updateJumpTableSuccessors() {
3565a343994SMaksim Panchenko const JumpTable *JT = getJumpTable();
3575a343994SMaksim Panchenko assert(JT && "Expected jump table instruction.");
3585a343994SMaksim Panchenko
3595a343994SMaksim Panchenko // Clear existing successors.
3605a343994SMaksim Panchenko removeAllSuccessors();
3615a343994SMaksim Panchenko
3625a343994SMaksim Panchenko // Generate the list of successors in deterministic order without duplicates.
3635a343994SMaksim Panchenko SmallVector<BinaryBasicBlock *, 16> SuccessorBBs;
3645a343994SMaksim Panchenko for (const MCSymbol *Label : JT->Entries) {
3655a343994SMaksim Panchenko BinaryBasicBlock *BB = getFunction()->getBasicBlockForLabel(Label);
3665a343994SMaksim Panchenko // Ignore __builtin_unreachable()
3675a343994SMaksim Panchenko if (!BB) {
3685a343994SMaksim Panchenko assert(Label == getFunction()->getFunctionEndLabel() &&
3695a343994SMaksim Panchenko "JT label should match a block or end of function.");
3705a343994SMaksim Panchenko continue;
3715a343994SMaksim Panchenko }
3725a343994SMaksim Panchenko SuccessorBBs.emplace_back(BB);
3735a343994SMaksim Panchenko }
3745a343994SMaksim Panchenko llvm::sort(SuccessorBBs,
3755a343994SMaksim Panchenko [](const BinaryBasicBlock *BB1, const BinaryBasicBlock *BB2) {
3765a343994SMaksim Panchenko return BB1->getInputOffset() < BB2->getInputOffset();
3775a343994SMaksim Panchenko });
3785a343994SMaksim Panchenko SuccessorBBs.erase(std::unique(SuccessorBBs.begin(), SuccessorBBs.end()),
3795a343994SMaksim Panchenko SuccessorBBs.end());
3805a343994SMaksim Panchenko
3815a343994SMaksim Panchenko for (BinaryBasicBlock *BB : SuccessorBBs)
3825a343994SMaksim Panchenko addSuccessor(BB);
3835a343994SMaksim Panchenko }
3845a343994SMaksim Panchenko
adjustExecutionCount(double Ratio)385a34c753fSRafael Auler void BinaryBasicBlock::adjustExecutionCount(double Ratio) {
386a34c753fSRafael Auler auto adjustedCount = [&](uint64_t Count) -> uint64_t {
387a34c753fSRafael Auler double NewCount = Count * Ratio;
388a34c753fSRafael Auler if (!NewCount && Count && (Ratio > 0.0))
389a34c753fSRafael Auler NewCount = 1;
390a34c753fSRafael Auler return NewCount;
391a34c753fSRafael Auler };
392a34c753fSRafael Auler
393a34c753fSRafael Auler setExecutionCount(adjustedCount(getKnownExecutionCount()));
394a34c753fSRafael Auler for (BinaryBranchInfo &BI : branch_info()) {
395a34c753fSRafael Auler if (BI.Count != COUNT_NO_PROFILE)
396a34c753fSRafael Auler BI.Count = adjustedCount(BI.Count);
397a34c753fSRafael Auler if (BI.MispredictedCount != COUNT_INFERRED)
398a34c753fSRafael Auler BI.MispredictedCount = adjustedCount(BI.MispredictedCount);
399a34c753fSRafael Auler }
400a34c753fSRafael Auler }
401a34c753fSRafael Auler
analyzeBranch(const MCSymbol * & TBB,const MCSymbol * & FBB,MCInst * & CondBranch,MCInst * & UncondBranch)40240c2e0faSMaksim Panchenko bool BinaryBasicBlock::analyzeBranch(const MCSymbol *&TBB, const MCSymbol *&FBB,
403a34c753fSRafael Auler MCInst *&CondBranch,
404a34c753fSRafael Auler MCInst *&UncondBranch) {
405a34c753fSRafael Auler auto &MIB = Function->getBinaryContext().MIB;
40640c2e0faSMaksim Panchenko return MIB->analyzeBranch(Instructions.begin(), Instructions.end(), TBB, FBB,
40740c2e0faSMaksim Panchenko CondBranch, UncondBranch);
408a34c753fSRafael Auler }
409a34c753fSRafael Auler
isMacroOpFusionPair(const_iterator I) const410a34c753fSRafael Auler bool BinaryBasicBlock::isMacroOpFusionPair(const_iterator I) const {
411a34c753fSRafael Auler auto &MIB = Function->getBinaryContext().MIB;
412a34c753fSRafael Auler ArrayRef<MCInst> Insts = Instructions;
413a34c753fSRafael Auler return MIB->isMacroOpFusionPair(Insts.slice(I - begin()));
414a34c753fSRafael Auler }
415a34c753fSRafael Auler
416a34c753fSRafael Auler BinaryBasicBlock::const_iterator
getMacroOpFusionPair() const417a34c753fSRafael Auler BinaryBasicBlock::getMacroOpFusionPair() const {
418a34c753fSRafael Auler if (!Function->getBinaryContext().isX86())
419a34c753fSRafael Auler return end();
420a34c753fSRafael Auler
421a34c753fSRafael Auler if (getNumNonPseudos() < 2 || succ_size() != 2)
422a34c753fSRafael Auler return end();
423a34c753fSRafael Auler
424a34c753fSRafael Auler auto RI = getLastNonPseudo();
425a34c753fSRafael Auler assert(RI != rend() && "cannot have an empty block with 2 successors");
426a34c753fSRafael Auler
427a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
428a34c753fSRafael Auler
429a34c753fSRafael Auler // Skip instruction if it's an unconditional branch following
430a34c753fSRafael Auler // a conditional one.
431a34c753fSRafael Auler if (BC.MIB->isUnconditionalBranch(*RI))
432a34c753fSRafael Auler ++RI;
433a34c753fSRafael Auler
434a34c753fSRafael Auler if (!BC.MIB->isConditionalBranch(*RI))
435a34c753fSRafael Auler return end();
436a34c753fSRafael Auler
437a34c753fSRafael Auler // Start checking with instruction preceding the conditional branch.
438a34c753fSRafael Auler ++RI;
439a34c753fSRafael Auler if (RI == rend())
440a34c753fSRafael Auler return end();
441a34c753fSRafael Auler
442a34c753fSRafael Auler auto II = std::prev(RI.base()); // convert to a forward iterator
443a34c753fSRafael Auler if (isMacroOpFusionPair(II))
444a34c753fSRafael Auler return II;
445a34c753fSRafael Auler
446a34c753fSRafael Auler return end();
447a34c753fSRafael Auler }
448a34c753fSRafael Auler
getTerminatorBefore(MCInst * Pos)449a34c753fSRafael Auler MCInst *BinaryBasicBlock::getTerminatorBefore(MCInst *Pos) {
450a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
451a34c753fSRafael Auler auto Itr = rbegin();
452a34c753fSRafael Auler bool Check = Pos ? false : true;
453a34c753fSRafael Auler MCInst *FirstTerminator = nullptr;
454a34c753fSRafael Auler while (Itr != rend()) {
455a34c753fSRafael Auler if (!Check) {
456a34c753fSRafael Auler if (&*Itr == Pos)
457a34c753fSRafael Auler Check = true;
458a34c753fSRafael Auler ++Itr;
459a34c753fSRafael Auler continue;
460a34c753fSRafael Auler }
461a34c753fSRafael Auler if (BC.MIB->isTerminator(*Itr))
462a34c753fSRafael Auler FirstTerminator = &*Itr;
463a34c753fSRafael Auler ++Itr;
464a34c753fSRafael Auler }
465a34c753fSRafael Auler return FirstTerminator;
466a34c753fSRafael Auler }
467a34c753fSRafael Auler
hasTerminatorAfter(MCInst * Pos)468a34c753fSRafael Auler bool BinaryBasicBlock::hasTerminatorAfter(MCInst *Pos) {
469a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
470a34c753fSRafael Auler auto Itr = rbegin();
471a34c753fSRafael Auler while (Itr != rend()) {
472a34c753fSRafael Auler if (&*Itr == Pos)
473a34c753fSRafael Auler return false;
474a34c753fSRafael Auler if (BC.MIB->isTerminator(*Itr))
475a34c753fSRafael Auler return true;
476a34c753fSRafael Auler ++Itr;
477a34c753fSRafael Auler }
478a34c753fSRafael Auler return false;
479a34c753fSRafael Auler }
480a34c753fSRafael Auler
swapConditionalSuccessors()481a34c753fSRafael Auler bool BinaryBasicBlock::swapConditionalSuccessors() {
482a34c753fSRafael Auler if (succ_size() != 2)
483a34c753fSRafael Auler return false;
484a34c753fSRafael Auler
485a34c753fSRafael Auler std::swap(Successors[0], Successors[1]);
486a34c753fSRafael Auler std::swap(BranchInfo[0], BranchInfo[1]);
487a34c753fSRafael Auler return true;
488a34c753fSRafael Auler }
489a34c753fSRafael Auler
addBranchInstruction(const BinaryBasicBlock * Successor)490a34c753fSRafael Auler void BinaryBasicBlock::addBranchInstruction(const BinaryBasicBlock *Successor) {
491a34c753fSRafael Auler assert(isSuccessor(Successor));
492a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
493a34c753fSRafael Auler MCInst NewInst;
494a34c753fSRafael Auler std::unique_lock<std::shared_timed_mutex> Lock(BC.CtxMutex);
495a34c753fSRafael Auler BC.MIB->createUncondBranch(NewInst, Successor->getLabel(), BC.Ctx.get());
496a34c753fSRafael Auler Instructions.emplace_back(std::move(NewInst));
497a34c753fSRafael Auler }
498a34c753fSRafael Auler
addTailCallInstruction(const MCSymbol * Target)499a34c753fSRafael Auler void BinaryBasicBlock::addTailCallInstruction(const MCSymbol *Target) {
500a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
501a34c753fSRafael Auler MCInst NewInst;
502a34c753fSRafael Auler BC.MIB->createTailCall(NewInst, Target, BC.Ctx.get());
503a34c753fSRafael Auler Instructions.emplace_back(std::move(NewInst));
504a34c753fSRafael Auler }
505a34c753fSRafael Auler
getNumCalls() const506a34c753fSRafael Auler uint32_t BinaryBasicBlock::getNumCalls() const {
507a34c753fSRafael Auler uint32_t N = 0;
508a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
509a34c753fSRafael Auler for (const MCInst &Instr : Instructions) {
510a34c753fSRafael Auler if (BC.MIB->isCall(Instr))
511a34c753fSRafael Auler ++N;
512a34c753fSRafael Auler }
513a34c753fSRafael Auler return N;
514a34c753fSRafael Auler }
515a34c753fSRafael Auler
getNumPseudos() const516a34c753fSRafael Auler uint32_t BinaryBasicBlock::getNumPseudos() const {
517a34c753fSRafael Auler #ifndef NDEBUG
518a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
519a34c753fSRafael Auler uint32_t N = 0;
5203652483cSRafael Auler for (const MCInst &Instr : Instructions)
521a34c753fSRafael Auler if (BC.MIB->isPseudo(Instr))
522a34c753fSRafael Auler ++N;
5233652483cSRafael Auler
524a34c753fSRafael Auler if (N != NumPseudos) {
525a34c753fSRafael Auler errs() << "BOLT-ERROR: instructions for basic block " << getName()
52640c2e0faSMaksim Panchenko << " in function " << *Function << ": calculated pseudos " << N
52740c2e0faSMaksim Panchenko << ", set pseudos " << NumPseudos << ", size " << size() << '\n';
528a34c753fSRafael Auler llvm_unreachable("pseudos mismatch");
529a34c753fSRafael Auler }
530a34c753fSRafael Auler #endif
531a34c753fSRafael Auler return NumPseudos;
532a34c753fSRafael Auler }
533a34c753fSRafael Auler
534a34c753fSRafael Auler ErrorOr<std::pair<double, double>>
getBranchStats(const BinaryBasicBlock * Succ) const535a34c753fSRafael Auler BinaryBasicBlock::getBranchStats(const BinaryBasicBlock *Succ) const {
536a34c753fSRafael Auler if (Function->hasValidProfile()) {
537a34c753fSRafael Auler uint64_t TotalCount = 0;
538a34c753fSRafael Auler uint64_t TotalMispreds = 0;
539a34c753fSRafael Auler for (const BinaryBranchInfo &BI : BranchInfo) {
540a34c753fSRafael Auler if (BI.Count != COUNT_NO_PROFILE) {
541a34c753fSRafael Auler TotalCount += BI.Count;
542a34c753fSRafael Auler TotalMispreds += BI.MispredictedCount;
543a34c753fSRafael Auler }
544a34c753fSRafael Auler }
545a34c753fSRafael Auler
546a34c753fSRafael Auler if (TotalCount > 0) {
547*d2c87699SAmir Ayupov auto Itr = llvm::find(Successors, Succ);
548a34c753fSRafael Auler assert(Itr != Successors.end());
549a34c753fSRafael Auler const BinaryBranchInfo &BI = BranchInfo[Itr - Successors.begin()];
550a34c753fSRafael Auler if (BI.Count && BI.Count != COUNT_NO_PROFILE) {
55140c2e0faSMaksim Panchenko if (TotalMispreds == 0)
55240c2e0faSMaksim Panchenko TotalMispreds = 1;
553a34c753fSRafael Auler return std::make_pair(double(BI.Count) / TotalCount,
554a34c753fSRafael Auler double(BI.MispredictedCount) / TotalMispreds);
555a34c753fSRafael Auler }
556a34c753fSRafael Auler }
557a34c753fSRafael Auler }
558a34c753fSRafael Auler return make_error_code(llvm::errc::result_out_of_range);
559a34c753fSRafael Auler }
560a34c753fSRafael Auler
dump() const561a34c753fSRafael Auler void BinaryBasicBlock::dump() const {
562a34c753fSRafael Auler BinaryContext &BC = Function->getBinaryContext();
56340c2e0faSMaksim Panchenko if (Label)
56440c2e0faSMaksim Panchenko outs() << Label->getName() << ":\n";
565a34c753fSRafael Auler BC.printInstructions(outs(), Instructions.begin(), Instructions.end(),
56602d510b4SAmir Ayupov getOffset(), Function);
567a34c753fSRafael Auler outs() << "preds:";
568a34c753fSRafael Auler for (auto itr = pred_begin(); itr != pred_end(); ++itr) {
569a34c753fSRafael Auler outs() << " " << (*itr)->getName();
570a34c753fSRafael Auler }
571a34c753fSRafael Auler outs() << "\nsuccs:";
572a34c753fSRafael Auler for (auto itr = succ_begin(); itr != succ_end(); ++itr) {
573a34c753fSRafael Auler outs() << " " << (*itr)->getName();
574a34c753fSRafael Auler }
575a34c753fSRafael Auler outs() << "\n";
576a34c753fSRafael Auler }
577a34c753fSRafael Auler
estimateSize(const MCCodeEmitter * Emitter) const578a34c753fSRafael Auler uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
579a34c753fSRafael Auler return Function->getBinaryContext().computeCodeSize(begin(), end(), Emitter);
580a34c753fSRafael Auler }
581a34c753fSRafael Auler
582a34c753fSRafael Auler BinaryBasicBlock::BinaryBranchInfo &
getBranchInfo(const BinaryBasicBlock & Succ)583a34c753fSRafael Auler BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
584a34c753fSRafael Auler auto BI = branch_info_begin();
585a34c753fSRafael Auler for (BinaryBasicBlock *BB : successors()) {
586a34c753fSRafael Auler if (&Succ == BB)
587a34c753fSRafael Auler return *BI;
588a34c753fSRafael Auler ++BI;
589a34c753fSRafael Auler }
590a34c753fSRafael Auler
591a34c753fSRafael Auler llvm_unreachable("Invalid successor");
592a34c753fSRafael Auler return *BI;
593a34c753fSRafael Auler }
594a34c753fSRafael Auler
595a34c753fSRafael Auler BinaryBasicBlock::BinaryBranchInfo &
getBranchInfo(const MCSymbol * Label)596a34c753fSRafael Auler BinaryBasicBlock::getBranchInfo(const MCSymbol *Label) {
597a34c753fSRafael Auler auto BI = branch_info_begin();
598a34c753fSRafael Auler for (BinaryBasicBlock *BB : successors()) {
599a34c753fSRafael Auler if (BB->getLabel() == Label)
600a34c753fSRafael Auler return *BI;
601a34c753fSRafael Auler ++BI;
602a34c753fSRafael Auler }
603a34c753fSRafael Auler
604a34c753fSRafael Auler llvm_unreachable("Invalid successor");
605a34c753fSRafael Auler return *BI;
606a34c753fSRafael Auler }
607a34c753fSRafael Auler
splitAt(iterator II)608a34c753fSRafael Auler BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) {
609a34c753fSRafael Auler assert(II != end() && "expected iterator pointing to instruction");
610a34c753fSRafael Auler
6118228c703SMaksim Panchenko BinaryBasicBlock *NewBlock = getFunction()->addBasicBlock();
612a34c753fSRafael Auler
613a34c753fSRafael Auler // Adjust successors/predecessors and propagate the execution count.
614a34c753fSRafael Auler moveAllSuccessorsTo(NewBlock);
615a34c753fSRafael Auler addSuccessor(NewBlock, getExecutionCount(), 0);
616a34c753fSRafael Auler
617a34c753fSRafael Auler // Set correct CFI state for the new block.
618a34c753fSRafael Auler NewBlock->setCFIState(getCFIStateAtInstr(&*II));
619a34c753fSRafael Auler
620a34c753fSRafael Auler // Move instructions over.
621a34c753fSRafael Auler adjustNumPseudos(II, end(), -1);
622a34c753fSRafael Auler NewBlock->addInstructions(II, end());
623a34c753fSRafael Auler Instructions.erase(II, end());
624a34c753fSRafael Auler
625a34c753fSRafael Auler return NewBlock;
626a34c753fSRafael Auler }
627a34c753fSRafael Auler
updateOutputValues(const MCAsmLayout & Layout)628a34c753fSRafael Auler void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) {
629a34c753fSRafael Auler if (!LocSyms)
630a34c753fSRafael Auler return;
631a34c753fSRafael Auler
632a34c753fSRafael Auler const uint64_t BBAddress = getOutputAddressRange().first;
633a34c753fSRafael Auler const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel());
634a34c753fSRafael Auler for (const auto &LocSymKV : *LocSyms) {
635a34c753fSRafael Auler const uint32_t InputFunctionOffset = LocSymKV.first;
636a34c753fSRafael Auler const uint32_t OutputOffset = static_cast<uint32_t>(
637a34c753fSRafael Auler Layout.getSymbolOffset(*LocSymKV.second) - BBOffset);
638a34c753fSRafael Auler getOffsetTranslationTable().emplace_back(
639a34c753fSRafael Auler std::make_pair(OutputOffset, InputFunctionOffset));
640a34c753fSRafael Auler
641a34c753fSRafael Auler // Update reverse (relative to BAT) address lookup table for function.
642a34c753fSRafael Auler if (getFunction()->requiresAddressTranslation()) {
643a34c753fSRafael Auler getFunction()->getInputOffsetToAddressMap().emplace(
644a34c753fSRafael Auler std::make_pair(InputFunctionOffset, OutputOffset + BBAddress));
645a34c753fSRafael Auler }
646a34c753fSRafael Auler }
647a34c753fSRafael Auler LocSyms.reset(nullptr);
648a34c753fSRafael Auler }
649a34c753fSRafael Auler
650a34c753fSRafael Auler } // namespace bolt
651a34c753fSRafael Auler } // namespace llvm
652