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