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