1 //===- bolt/Passes/TailDuplication.cpp ------------------------------------===// 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 // This file implements the TailDuplication class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "bolt/Passes/TailDuplication.h" 14 #include "llvm/ADT/DenseMap.h" 15 #include "llvm/MC/MCRegisterInfo.h" 16 17 #include <numeric> 18 19 #define DEBUG_TYPE "taildup" 20 21 using namespace llvm; 22 23 namespace opts { 24 25 extern cl::OptionCategory BoltOptCategory; 26 extern cl::opt<bool> NoThreads; 27 28 cl::opt<bolt::TailDuplication::DuplicationMode> TailDuplicationMode( 29 "tail-duplication", 30 cl::desc("duplicate unconditional branches that cross a cache line"), 31 cl::init(bolt::TailDuplication::TD_NONE), 32 cl::values(clEnumValN(bolt::TailDuplication::TD_NONE, "none", 33 "do not apply"), 34 clEnumValN(bolt::TailDuplication::TD_AGGRESSIVE, "aggressive", 35 "aggressive strategy"), 36 clEnumValN(bolt::TailDuplication::TD_MODERATE, "moderate", 37 "moderate strategy"), 38 clEnumValN(bolt::TailDuplication::TD_CACHE, "cache", 39 "cache-aware duplication strategy")), 40 cl::ZeroOrMore, cl::Hidden, cl::cat(BoltOptCategory)); 41 42 static cl::opt<unsigned> 43 TailDuplicationMinimumOffset("tail-duplication-minimum-offset", 44 cl::desc("minimum offset needed between block " 45 "and successor to allow duplication"), 46 cl::ReallyHidden, cl::init(64), 47 cl::cat(BoltOptCategory)); 48 49 static cl::opt<unsigned> TailDuplicationMaximumDuplication( 50 "tail-duplication-maximum-duplication", 51 cl::desc("tail blocks whose size (in bytes) exceeds the value are never " 52 "duplicated"), 53 cl::ZeroOrMore, cl::ReallyHidden, cl::init(24), cl::cat(BoltOptCategory)); 54 55 static cl::opt<unsigned> TailDuplicationMinimumDuplication( 56 "tail-duplication-minimum-duplication", 57 cl::desc("tail blocks with size (in bytes) not exceeding the value are " 58 "always duplicated"), 59 cl::ReallyHidden, cl::init(2), cl::cat(BoltOptCategory)); 60 61 static cl::opt<bool> TailDuplicationConstCopyPropagation( 62 "tail-duplication-const-copy-propagation", 63 cl::desc("enable const and copy propagation after tail duplication"), 64 cl::ReallyHidden, cl::init(false), cl::cat(BoltOptCategory)); 65 66 static cl::opt<unsigned> TailDuplicationMaxCacheDistance( 67 "tail-duplication-max-cache-distance", 68 cl::desc("The weight of backward jumps for ExtTSP value"), cl::init(256), 69 cl::ReallyHidden, cl::cat(BoltOptCategory)); 70 71 static cl::opt<double> TailDuplicationCacheBackwardWeight( 72 "tail-duplication-cache-backward-weight", 73 cl::desc( 74 "The maximum distance (in bytes) of backward jumps for ExtTSP value"), 75 cl::init(0.5), cl::ReallyHidden, cl::cat(BoltOptCategory)); 76 77 } // namespace opts 78 79 namespace llvm { 80 namespace bolt { 81 82 void TailDuplication::getCallerSavedRegs(const MCInst &Inst, BitVector &Regs, 83 BinaryContext &BC) const { 84 if (!BC.MIB->isCall(Inst)) 85 return; 86 BitVector CallRegs = BitVector(BC.MRI->getNumRegs(), false); 87 BC.MIB->getCalleeSavedRegs(CallRegs); 88 CallRegs.flip(); 89 Regs |= CallRegs; 90 } 91 92 bool TailDuplication::regIsPossiblyOverwritten(const MCInst &Inst, unsigned Reg, 93 BinaryContext &BC) const { 94 BitVector WrittenRegs = BitVector(BC.MRI->getNumRegs(), false); 95 BC.MIB->getWrittenRegs(Inst, WrittenRegs); 96 getCallerSavedRegs(Inst, WrittenRegs, BC); 97 if (BC.MIB->isRep(Inst)) 98 BC.MIB->getRepRegs(WrittenRegs); 99 WrittenRegs &= BC.MIB->getAliases(Reg, false); 100 return WrittenRegs.any(); 101 } 102 103 bool TailDuplication::regIsDefinitelyOverwritten(const MCInst &Inst, 104 unsigned Reg, 105 BinaryContext &BC) const { 106 BitVector WrittenRegs = BitVector(BC.MRI->getNumRegs(), false); 107 BC.MIB->getWrittenRegs(Inst, WrittenRegs); 108 getCallerSavedRegs(Inst, WrittenRegs, BC); 109 if (BC.MIB->isRep(Inst)) 110 BC.MIB->getRepRegs(WrittenRegs); 111 return (!regIsUsed(Inst, Reg, BC) && WrittenRegs.test(Reg) && 112 !BC.MIB->isConditionalMove(Inst)); 113 } 114 115 bool TailDuplication::regIsUsed(const MCInst &Inst, unsigned Reg, 116 BinaryContext &BC) const { 117 BitVector SrcRegs = BitVector(BC.MRI->getNumRegs(), false); 118 BC.MIB->getSrcRegs(Inst, SrcRegs); 119 SrcRegs &= BC.MIB->getAliases(Reg, true); 120 return SrcRegs.any(); 121 } 122 123 bool TailDuplication::isOverwrittenBeforeUsed(BinaryBasicBlock &StartBB, 124 unsigned Reg) const { 125 BinaryFunction *BF = StartBB.getFunction(); 126 BinaryContext &BC = BF->getBinaryContext(); 127 std::queue<BinaryBasicBlock *> Q; 128 for (auto Itr = StartBB.succ_begin(); Itr != StartBB.succ_end(); ++Itr) { 129 BinaryBasicBlock *NextBB = *Itr; 130 Q.push(NextBB); 131 } 132 std::set<BinaryBasicBlock *> Visited; 133 // Breadth first search through successive blocks and see if Reg is ever used 134 // before its overwritten 135 while (Q.size() > 0) { 136 BinaryBasicBlock *CurrBB = Q.front(); 137 Q.pop(); 138 if (Visited.count(CurrBB)) 139 continue; 140 Visited.insert(CurrBB); 141 bool Overwritten = false; 142 for (auto Itr = CurrBB->begin(); Itr != CurrBB->end(); ++Itr) { 143 MCInst &Inst = *Itr; 144 if (regIsUsed(Inst, Reg, BC)) 145 return false; 146 if (regIsDefinitelyOverwritten(Inst, Reg, BC)) { 147 Overwritten = true; 148 break; 149 } 150 } 151 if (Overwritten) 152 continue; 153 for (auto Itr = CurrBB->succ_begin(); Itr != CurrBB->succ_end(); ++Itr) { 154 BinaryBasicBlock *NextBB = *Itr; 155 Q.push(NextBB); 156 } 157 } 158 return true; 159 } 160 161 void TailDuplication::constantAndCopyPropagate( 162 BinaryBasicBlock &OriginalBB, 163 std::vector<BinaryBasicBlock *> &BlocksToPropagate) { 164 BinaryFunction *BF = OriginalBB.getFunction(); 165 BinaryContext &BC = BF->getBinaryContext(); 166 167 BlocksToPropagate.insert(BlocksToPropagate.begin(), &OriginalBB); 168 // Iterate through the original instructions to find one to propagate 169 for (auto Itr = OriginalBB.begin(); Itr != OriginalBB.end(); ++Itr) { 170 MCInst &OriginalInst = *Itr; 171 // It must be a non conditional 172 if (BC.MIB->isConditionalMove(OriginalInst)) 173 continue; 174 175 // Move immediate or move register 176 if ((!BC.MII->get(OriginalInst.getOpcode()).isMoveImmediate() || 177 !OriginalInst.getOperand(1).isImm()) && 178 (!BC.MII->get(OriginalInst.getOpcode()).isMoveReg() || 179 !OriginalInst.getOperand(1).isReg())) 180 continue; 181 182 // True if this is constant propagation and not copy propagation 183 bool ConstantProp = BC.MII->get(OriginalInst.getOpcode()).isMoveImmediate(); 184 // The Register to replaced 185 unsigned Reg = OriginalInst.getOperand(0).getReg(); 186 // True if the register to replace was replaced everywhere it was used 187 bool ReplacedEverywhere = true; 188 // True if the register was definitely overwritten 189 bool Overwritten = false; 190 // True if the register to replace and the register to replace with (for 191 // copy propagation) has not been overwritten and is still usable 192 bool RegsActive = true; 193 194 // Iterate through successor blocks and through their instructions 195 for (BinaryBasicBlock *NextBB : BlocksToPropagate) { 196 for (auto PropagateItr = 197 ((NextBB == &OriginalBB) ? Itr + 1 : NextBB->begin()); 198 PropagateItr < NextBB->end(); ++PropagateItr) { 199 MCInst &PropagateInst = *PropagateItr; 200 if (regIsUsed(PropagateInst, Reg, BC)) { 201 bool Replaced = false; 202 // If both registers are active for copy propagation or the register 203 // to replace is active for constant propagation 204 if (RegsActive) { 205 // Set Replaced and so ReplacedEverwhere to false if it cannot be 206 // replaced (no replacing that opcode, Register is src and dest) 207 if (ConstantProp) 208 Replaced = BC.MIB->replaceRegWithImm( 209 PropagateInst, Reg, OriginalInst.getOperand(1).getImm()); 210 else 211 Replaced = BC.MIB->replaceRegWithReg( 212 PropagateInst, Reg, OriginalInst.getOperand(1).getReg()); 213 } 214 ReplacedEverywhere = ReplacedEverywhere && Replaced; 215 } 216 // For copy propagation, make sure no propagation happens after the 217 // register to replace with is overwritten 218 if (!ConstantProp && 219 regIsPossiblyOverwritten(PropagateInst, 220 OriginalInst.getOperand(1).getReg(), BC)) 221 RegsActive = false; 222 223 // Make sure no propagation happens after the register to replace is 224 // overwritten 225 if (regIsPossiblyOverwritten(PropagateInst, Reg, BC)) 226 RegsActive = false; 227 228 // Record if the register to replace is overwritten 229 if (regIsDefinitelyOverwritten(PropagateInst, Reg, BC)) { 230 Overwritten = true; 231 break; 232 } 233 } 234 if (Overwritten) 235 break; 236 } 237 238 // If the register was replaced everwhere and it was overwritten in either 239 // one of the iterated through blocks or one of the successor blocks, delete 240 // the original move instruction 241 if (ReplacedEverywhere && 242 (Overwritten || 243 isOverwrittenBeforeUsed( 244 *BlocksToPropagate[BlocksToPropagate.size() - 1], Reg))) { 245 // If both registers are active for copy propagation or the register 246 // to replace is active for constant propagation 247 StaticInstructionDeletionCount++; 248 DynamicInstructionDeletionCount += OriginalBB.getExecutionCount(); 249 Itr = std::prev(OriginalBB.eraseInstruction(Itr)); 250 } 251 } 252 } 253 254 bool TailDuplication::isInCacheLine(const BinaryBasicBlock &BB, 255 const BinaryBasicBlock &Succ) const { 256 if (&BB == &Succ) 257 return true; 258 259 BinaryFunction::BasicBlockOrderType BlockLayout = 260 BB.getFunction()->getLayout(); 261 uint64_t Distance = 0; 262 int Direction = (Succ.getLayoutIndex() > BB.getLayoutIndex()) ? 1 : -1; 263 264 for (unsigned I = BB.getLayoutIndex() + Direction; I != Succ.getLayoutIndex(); 265 I += Direction) { 266 Distance += BlockLayout[I]->getOriginalSize(); 267 if (Distance > opts::TailDuplicationMinimumOffset) 268 return false; 269 } 270 return true; 271 } 272 273 std::vector<BinaryBasicBlock *> 274 TailDuplication::moderateDuplicate(BinaryBasicBlock &BB, 275 BinaryBasicBlock &Tail) const { 276 std::vector<BinaryBasicBlock *> BlocksToDuplicate; 277 // The block must be hot 278 if (BB.getKnownExecutionCount() == 0) 279 return BlocksToDuplicate; 280 // and its sucessor is not already in the same cache line 281 if (isInCacheLine(BB, Tail)) 282 return BlocksToDuplicate; 283 // and its size do not exceed the maximum allowed size 284 if (Tail.getOriginalSize() > opts::TailDuplicationMaximumDuplication) 285 return BlocksToDuplicate; 286 // If duplicating would introduce a new branch, don't duplicate 287 for (auto Itr = Tail.succ_begin(); Itr != Tail.succ_end(); ++Itr) { 288 if ((*Itr)->getLayoutIndex() == Tail.getLayoutIndex() + 1) 289 return BlocksToDuplicate; 290 } 291 292 BlocksToDuplicate.push_back(&Tail); 293 return BlocksToDuplicate; 294 } 295 296 std::vector<BinaryBasicBlock *> 297 TailDuplication::aggressiveDuplicate(BinaryBasicBlock &BB, 298 BinaryBasicBlock &Tail) const { 299 std::vector<BinaryBasicBlock *> BlocksToDuplicate; 300 // The block must be hot 301 if (BB.getKnownExecutionCount() == 0) 302 return BlocksToDuplicate; 303 // and its sucessor is not already in the same cache line 304 if (isInCacheLine(BB, Tail)) 305 return BlocksToDuplicate; 306 307 BinaryBasicBlock *CurrBB = &BB; 308 while (CurrBB) { 309 LLVM_DEBUG(dbgs() << "Aggressive tail duplication: adding " 310 << CurrBB->getName() << " to duplication list\n";); 311 BlocksToDuplicate.push_back(CurrBB); 312 313 if (CurrBB->hasJumpTable()) { 314 LLVM_DEBUG(dbgs() << "Aggressive tail duplication: clearing duplication " 315 "list due to a JT in " 316 << CurrBB->getName() << '\n';); 317 BlocksToDuplicate.clear(); 318 break; 319 } 320 321 // With no successors, we've reached the end and should duplicate all of 322 // BlocksToDuplicate 323 if (CurrBB->succ_size() == 0) 324 break; 325 326 // With two successors, if they're both a jump, we should duplicate all 327 // blocks in BlocksToDuplicate. Otherwise, we cannot find a simple stream of 328 // blocks to copy 329 if (CurrBB->succ_size() >= 2) { 330 if (CurrBB->getConditionalSuccessor(false)->getLayoutIndex() == 331 CurrBB->getLayoutIndex() + 1 || 332 CurrBB->getConditionalSuccessor(true)->getLayoutIndex() == 333 CurrBB->getLayoutIndex() + 1) { 334 LLVM_DEBUG(dbgs() << "Aggressive tail duplication: clearing " 335 "duplication list, can't find a simple stream at " 336 << CurrBB->getName() << '\n';); 337 BlocksToDuplicate.clear(); 338 } 339 break; 340 } 341 342 // With one successor, if its a jump, we should duplicate all blocks in 343 // BlocksToDuplicate. Otherwise, we should keep going 344 BinaryBasicBlock *SuccBB = CurrBB->getSuccessor(); 345 if (SuccBB->getLayoutIndex() != CurrBB->getLayoutIndex() + 1) 346 break; 347 CurrBB = SuccBB; 348 } 349 // Don't duplicate if its too much code 350 unsigned DuplicationByteCount = std::accumulate( 351 std::begin(BlocksToDuplicate), std::end(BlocksToDuplicate), 0, 352 [](int value, BinaryBasicBlock *p) { 353 return value + p->getOriginalSize(); 354 }); 355 if (DuplicationByteCount > opts::TailDuplicationMaximumDuplication) { 356 LLVM_DEBUG(dbgs() << "Aggressive tail duplication: duplication byte count (" 357 << DuplicationByteCount << ") exceeds maximum " 358 << opts::TailDuplicationMaximumDuplication << '\n';); 359 BlocksToDuplicate.clear(); 360 } 361 LLVM_DEBUG(dbgs() << "Aggressive tail duplication: found " 362 << BlocksToDuplicate.size() << " blocks to duplicate\n";); 363 return BlocksToDuplicate; 364 } 365 366 bool TailDuplication::shouldDuplicate(BinaryBasicBlock *Pred, 367 BinaryBasicBlock *Tail) const { 368 if (Pred == Tail) 369 return false; 370 // Cannot duplicate non-tail blocks 371 if (Tail->succ_size() != 0) 372 return false; 373 // The blocks are already in the order 374 if (Pred->getLayoutIndex() + 1 == Tail->getLayoutIndex()) 375 return false; 376 // No tail duplication for blocks with jump tables 377 if (Pred->hasJumpTable()) 378 return false; 379 if (Tail->hasJumpTable()) 380 return false; 381 382 return true; 383 } 384 385 double TailDuplication::cacheScore(uint64_t SrcAddr, uint64_t SrcSize, 386 uint64_t DstAddr, uint64_t DstSize, 387 uint64_t Count) const { 388 assert(Count != BinaryBasicBlock::COUNT_NO_PROFILE); 389 390 bool IsForwardJump = SrcAddr <= DstAddr; 391 uint64_t JumpDistance = 0; 392 // Computing the length of the jump so that it takes the sizes of the two 393 // blocks into consideration 394 if (IsForwardJump) { 395 JumpDistance = (DstAddr + DstSize) - (SrcAddr); 396 } else { 397 JumpDistance = (SrcAddr + SrcSize) - (DstAddr); 398 } 399 400 if (JumpDistance >= opts::TailDuplicationMaxCacheDistance) 401 return 0; 402 double Prob = 1.0 - static_cast<double>(JumpDistance) / 403 opts::TailDuplicationMaxCacheDistance; 404 return (IsForwardJump ? 1.0 : opts::TailDuplicationCacheBackwardWeight) * 405 Prob * Count; 406 } 407 408 bool TailDuplication::cacheScoreImproved(const MCCodeEmitter *Emitter, 409 BinaryFunction &BF, 410 BinaryBasicBlock *Pred, 411 BinaryBasicBlock *Tail) const { 412 // Collect (estimated) basic block sizes 413 DenseMap<BinaryBasicBlock *, uint64_t> BBSize; 414 for (BinaryBasicBlock *BB : BF.layout()) { 415 BBSize[BB] = std::max<uint64_t>(BB->estimateSize(Emitter), 1); 416 } 417 418 // Build current addresses of basic blocks starting at the entry block 419 DenseMap<BinaryBasicBlock *, uint64_t> CurAddr; 420 uint64_t Addr = 0; 421 for (BinaryBasicBlock *SrcBB : BF.layout()) { 422 CurAddr[SrcBB] = Addr; 423 Addr += BBSize[SrcBB]; 424 } 425 426 // Build new addresses (after duplication) starting at the entry block 427 DenseMap<BinaryBasicBlock *, uint64_t> NewAddr; 428 Addr = 0; 429 for (BinaryBasicBlock *SrcBB : BF.layout()) { 430 NewAddr[SrcBB] = Addr; 431 Addr += BBSize[SrcBB]; 432 if (SrcBB == Pred) 433 Addr += BBSize[Tail]; 434 } 435 436 // Compute the cache score for the existing layout of basic blocks 437 double CurScore = 0; 438 for (BinaryBasicBlock *SrcBB : BF.layout()) { 439 auto BI = SrcBB->branch_info_begin(); 440 for (BinaryBasicBlock *DstBB : SrcBB->successors()) { 441 if (SrcBB != DstBB) { 442 CurScore += cacheScore(CurAddr[SrcBB], BBSize[SrcBB], CurAddr[DstBB], 443 BBSize[DstBB], BI->Count); 444 } 445 ++BI; 446 } 447 } 448 449 // Compute the cache score for the layout of blocks after tail duplication 450 double NewScore = 0; 451 for (BinaryBasicBlock *SrcBB : BF.layout()) { 452 auto BI = SrcBB->branch_info_begin(); 453 for (BinaryBasicBlock *DstBB : SrcBB->successors()) { 454 if (SrcBB != DstBB) { 455 if (SrcBB == Pred && DstBB == Tail) { 456 NewScore += cacheScore(NewAddr[SrcBB], BBSize[SrcBB], 457 NewAddr[SrcBB] + BBSize[SrcBB], BBSize[DstBB], 458 BI->Count); 459 } else { 460 NewScore += cacheScore(NewAddr[SrcBB], BBSize[SrcBB], NewAddr[DstBB], 461 BBSize[DstBB], BI->Count); 462 } 463 } 464 ++BI; 465 } 466 } 467 468 return NewScore > CurScore; 469 } 470 471 std::vector<BinaryBasicBlock *> 472 TailDuplication::cacheDuplicate(const MCCodeEmitter *Emitter, 473 BinaryFunction &BF, BinaryBasicBlock *Pred, 474 BinaryBasicBlock *Tail) const { 475 std::vector<BinaryBasicBlock *> BlocksToDuplicate; 476 477 // No need to duplicate cold basic blocks 478 if (Pred->isCold() || Tail->isCold()) { 479 return BlocksToDuplicate; 480 } 481 // Always duplicate "small" tail basic blocks, which might be beneficial for 482 // code size, since a jump instruction is eliminated 483 if (Tail->estimateSize(Emitter) <= opts::TailDuplicationMinimumDuplication) { 484 BlocksToDuplicate.push_back(Tail); 485 return BlocksToDuplicate; 486 } 487 // Never duplicate "large" tail basic blocks 488 if (Tail->estimateSize(Emitter) > opts::TailDuplicationMaximumDuplication) { 489 return BlocksToDuplicate; 490 } 491 // Do not append basic blocks after the last hot block in the current layout 492 auto NextBlock = BF.getBasicBlockAfter(Pred); 493 if (NextBlock == nullptr || (!Pred->isCold() && NextBlock->isCold())) { 494 return BlocksToDuplicate; 495 } 496 497 // Duplicate the tail only if it improves the cache score 498 if (cacheScoreImproved(Emitter, BF, Pred, Tail)) { 499 BlocksToDuplicate.push_back(Tail); 500 } 501 502 return BlocksToDuplicate; 503 } 504 505 std::vector<BinaryBasicBlock *> TailDuplication::duplicateBlocks( 506 BinaryBasicBlock &BB, 507 const std::vector<BinaryBasicBlock *> &BlocksToDuplicate) const { 508 BinaryFunction *BF = BB.getFunction(); 509 BinaryContext &BC = BF->getBinaryContext(); 510 511 // Ratio of this new branches execution count to the total size of the 512 // successor's execution count. Used to set this new branches execution count 513 // and lower the old successor's execution count 514 double ExecutionCountRatio = 515 BB.getExecutionCount() >= BB.getSuccessor()->getExecutionCount() 516 ? 1.0 517 : (double)BB.getExecutionCount() / 518 BB.getSuccessor()->getExecutionCount(); 519 520 // Use the last branch info when adding a successor to LastBB 521 BinaryBasicBlock::BinaryBranchInfo &LastBI = 522 BB.getBranchInfo(*(BB.getSuccessor())); 523 524 BinaryBasicBlock *LastOriginalBB = &BB; 525 BinaryBasicBlock *LastDuplicatedBB = &BB; 526 assert(LastDuplicatedBB->succ_size() == 1 && 527 "tail duplication cannot act on a block with more than 1 successor"); 528 LastDuplicatedBB->removeSuccessor(LastDuplicatedBB->getSuccessor()); 529 530 std::vector<std::unique_ptr<BinaryBasicBlock>> DuplicatedBlocks; 531 std::vector<BinaryBasicBlock *> DuplicatedBlocksToReturn; 532 533 for (BinaryBasicBlock *CurBB : BlocksToDuplicate) { 534 DuplicatedBlocks.emplace_back( 535 BF->createBasicBlock((BC.Ctx)->createNamedTempSymbol("tail-dup"))); 536 BinaryBasicBlock *NewBB = DuplicatedBlocks.back().get(); 537 538 NewBB->addInstructions(CurBB->begin(), CurBB->end()); 539 // Set execution count as if it was just a copy of the original 540 NewBB->setExecutionCount(CurBB->getExecutionCount()); 541 NewBB->setIsCold(CurBB->isCold()); 542 LastDuplicatedBB->addSuccessor(NewBB, LastBI); 543 544 DuplicatedBlocksToReturn.push_back(NewBB); 545 546 // As long as its not the first block, adjust both original and duplicated 547 // to what they should be 548 if (LastDuplicatedBB != &BB) { 549 LastOriginalBB->adjustExecutionCount(1.0 - ExecutionCountRatio); 550 LastDuplicatedBB->adjustExecutionCount(ExecutionCountRatio); 551 } 552 553 if (CurBB->succ_size() == 1) 554 LastBI = CurBB->getBranchInfo(*(CurBB->getSuccessor())); 555 556 LastOriginalBB = CurBB; 557 LastDuplicatedBB = NewBB; 558 } 559 560 LastDuplicatedBB->addSuccessors( 561 LastOriginalBB->succ_begin(), LastOriginalBB->succ_end(), 562 LastOriginalBB->branch_info_begin(), LastOriginalBB->branch_info_end()); 563 564 LastOriginalBB->adjustExecutionCount(1.0 - ExecutionCountRatio); 565 LastDuplicatedBB->adjustExecutionCount(ExecutionCountRatio); 566 567 BF->insertBasicBlocks(&BB, std::move(DuplicatedBlocks)); 568 569 return DuplicatedBlocksToReturn; 570 } 571 572 void TailDuplication::runOnFunction(BinaryFunction &Function) { 573 // Create a separate MCCodeEmitter to allow lock-free execution 574 BinaryContext::IndependentCodeEmitter Emitter; 575 if (!opts::NoThreads) { 576 Emitter = Function.getBinaryContext().createIndependentMCCodeEmitter(); 577 } 578 579 Function.updateLayoutIndices(); 580 581 // New blocks will be added and layout will change, 582 // so make a copy here to iterate over the original layout 583 BinaryFunction::BasicBlockOrderType BlockLayout = Function.getLayout(); 584 bool ModifiedFunction = false; 585 for (BinaryBasicBlock *BB : BlockLayout) { 586 AllDynamicCount += BB->getKnownExecutionCount(); 587 588 // The block must be with one successor 589 if (BB->succ_size() != 1) 590 continue; 591 BinaryBasicBlock *Tail = BB->getSuccessor(); 592 // Verify that the tail should be duplicated 593 if (!shouldDuplicate(BB, Tail)) 594 continue; 595 596 std::vector<BinaryBasicBlock *> BlocksToDuplicate; 597 if (opts::TailDuplicationMode == TailDuplication::TD_AGGRESSIVE) { 598 BlocksToDuplicate = aggressiveDuplicate(*BB, *Tail); 599 } else if (opts::TailDuplicationMode == TailDuplication::TD_MODERATE) { 600 BlocksToDuplicate = moderateDuplicate(*BB, *Tail); 601 } else if (opts::TailDuplicationMode == TailDuplication::TD_CACHE) { 602 BlocksToDuplicate = cacheDuplicate(Emitter.MCE.get(), Function, BB, Tail); 603 } else { 604 llvm_unreachable("unknown tail duplication mode"); 605 } 606 607 if (BlocksToDuplicate.empty()) 608 continue; 609 610 // Apply the the duplication 611 ModifiedFunction = true; 612 DuplicationsDynamicCount += BB->getExecutionCount(); 613 auto DuplicatedBlocks = duplicateBlocks(*BB, BlocksToDuplicate); 614 for (BinaryBasicBlock *BB : DuplicatedBlocks) { 615 DuplicatedBlockCount++; 616 DuplicatedByteCount += BB->estimateSize(Emitter.MCE.get()); 617 } 618 619 if (opts::TailDuplicationConstCopyPropagation) { 620 constantAndCopyPropagate(*BB, DuplicatedBlocks); 621 BinaryBasicBlock *FirstBB = BlocksToDuplicate[0]; 622 if (FirstBB->pred_size() == 1) { 623 BinaryBasicBlock *PredBB = *FirstBB->pred_begin(); 624 if (PredBB->succ_size() == 1) 625 constantAndCopyPropagate(*PredBB, BlocksToDuplicate); 626 } 627 } 628 629 // Layout indices might be stale after duplication 630 Function.updateLayoutIndices(); 631 } 632 if (ModifiedFunction) 633 ModifiedFunctions++; 634 } 635 636 void TailDuplication::runOnFunctions(BinaryContext &BC) { 637 if (opts::TailDuplicationMode == TailDuplication::TD_NONE) 638 return; 639 640 for (auto &It : BC.getBinaryFunctions()) { 641 BinaryFunction &Function = It.second; 642 if (!shouldOptimize(Function)) 643 continue; 644 runOnFunction(Function); 645 } 646 647 outs() << "BOLT-INFO: tail duplication" 648 << format(" modified %zu (%.2f%%) functions;", ModifiedFunctions, 649 100.0 * ModifiedFunctions / BC.getBinaryFunctions().size()) 650 << format(" duplicated %zu blocks (%zu bytes) responsible for", 651 DuplicatedBlockCount, DuplicatedByteCount) 652 << format(" %zu dynamic executions (%.2f%% of all block executions)", 653 DuplicationsDynamicCount, 654 100.0 * DuplicationsDynamicCount / AllDynamicCount) 655 << "\n"; 656 657 if (opts::TailDuplicationConstCopyPropagation) { 658 outs() << "BOLT-INFO: tail duplication " 659 << format("applied %zu static and %zu dynamic propagation deletions", 660 StaticInstructionDeletionCount, 661 DynamicInstructionDeletionCount) 662 << "\n"; 663 } 664 } 665 666 } // end namespace bolt 667 } // end namespace llvm 668