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 28a34c753fSRafael Auler bool operator<(const BinaryBasicBlock &LHS, const BinaryBasicBlock &RHS) { 29a34c753fSRafael Auler return LHS.Index < RHS.Index; 30a34c753fSRafael Auler } 31a34c753fSRafael Auler 3240c2e0faSMaksim Panchenko bool BinaryBasicBlock::hasCFG() const { return getParent()->hasCFG(); } 33a34c753fSRafael Auler 34a34c753fSRafael Auler bool BinaryBasicBlock::isEntryPoint() const { 35a34c753fSRafael Auler return getParent()->isEntryPoint(*this); 36a34c753fSRafael Auler } 37a34c753fSRafael Auler 38a34c753fSRafael Auler bool BinaryBasicBlock::hasInstructions() const { 39a34c753fSRafael Auler return getParent()->hasInstructions(); 40a34c753fSRafael Auler } 41a34c753fSRafael Auler 425a343994SMaksim 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 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 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 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 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 157a34c753fSRafael 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 16840c2e0faSMaksim 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 182a34c753fSRafael 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 190a34c753fSRafael 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 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 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() { 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 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!"); 331c907d6e0SAmir Ayupov (void)Erased; 332a34c753fSRafael Auler } 333a34c753fSRafael Auler 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 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 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 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 410a34c753fSRafael 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 417a34c753fSRafael 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 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 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 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 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 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 506a34c753fSRafael 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 516a34c753fSRafael 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>> 535a34c753fSRafael 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) { 547a34c753fSRafael Auler auto Itr = std::find(Successors.begin(), Successors.end(), 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 561a34c753fSRafael 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 578a34c753fSRafael 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 & 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 & 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 608a34c753fSRafael Auler BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) { 609a34c753fSRafael Auler assert(II != end() && "expected iterator pointing to instruction"); 610a34c753fSRafael Auler 611*8228c703SMaksim 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 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