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