12f09f445SMaksim Panchenko //===- bolt/Core/BinaryFunctionProfile.cpp - Profile processing -----------===// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler // 92f09f445SMaksim Panchenko // This file implements BinaryFunction member functions related to processing 102f09f445SMaksim Panchenko // the execution profile. 112f09f445SMaksim Panchenko // 12a34c753fSRafael Auler //===----------------------------------------------------------------------===// 13a34c753fSRafael Auler 14a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h" 15a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h" 16a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 17a34c753fSRafael Auler #include "llvm/Support/Debug.h" 18a34c753fSRafael Auler #include "llvm/Support/raw_ostream.h" 19a34c753fSRafael Auler 20a34c753fSRafael Auler #undef DEBUG_TYPE 21a34c753fSRafael Auler #define DEBUG_TYPE "bolt-prof" 22a34c753fSRafael Auler 23a34c753fSRafael Auler using namespace llvm; 24a34c753fSRafael Auler using namespace bolt; 25a34c753fSRafael Auler 26a34c753fSRafael Auler namespace opts { 27a34c753fSRafael Auler 28a34c753fSRafael Auler extern cl::OptionCategory BoltOptCategory; 29a34c753fSRafael Auler 30c3d53720SAmir Ayupov cl::opt<IndirectCallPromotionType> ICP( 31c3d53720SAmir Ayupov "indirect-call-promotion", cl::init(ICP_NONE), 32a34c753fSRafael Auler cl::desc("indirect call promotion"), 33a34c753fSRafael Auler cl::values( 34a34c753fSRafael Auler clEnumValN(ICP_NONE, "none", "do not perform indirect call promotion"), 35a34c753fSRafael Auler clEnumValN(ICP_CALLS, "calls", "perform ICP on indirect calls"), 36c3d53720SAmir Ayupov clEnumValN(ICP_JUMP_TABLES, "jump-tables", 37c3d53720SAmir Ayupov "perform ICP on jump tables"), 38a34c753fSRafael Auler clEnumValN(ICP_ALL, "all", "perform ICP on calls and jump tables")), 39c3d53720SAmir Ayupov cl::ZeroOrMore, cl::cat(BoltOptCategory)); 40a34c753fSRafael Auler 410d477f63SAmir Ayupov static cl::alias ICPAlias("icp", 420d477f63SAmir Ayupov cl::desc("Alias for --indirect-call-promotion"), 430d477f63SAmir Ayupov cl::aliasopt(ICP)); 440d477f63SAmir Ayupov 45a34c753fSRafael Auler extern cl::opt<JumpTableSupportLevel> JumpTables; 46a34c753fSRafael Auler 47b92436efSFangrui Song static cl::opt<bool> FixFuncCounts( 48b92436efSFangrui Song "fix-func-counts", 49a34c753fSRafael Auler cl::desc("adjust function counts based on basic blocks execution count"), 50b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory)); 51a34c753fSRafael Auler 52b92436efSFangrui Song static cl::opt<bool> FixBlockCounts( 53b92436efSFangrui Song "fix-block-counts", 54a34c753fSRafael Auler cl::desc("adjust block counts based on outgoing branch counts"), 55b92436efSFangrui Song cl::init(true), cl::Hidden, cl::cat(BoltOptCategory)); 56a34c753fSRafael Auler 57a34c753fSRafael Auler static cl::opt<bool> 58a34c753fSRafael Auler InferFallThroughs("infer-fall-throughs", 59a34c753fSRafael Auler cl::desc("infer execution count for fall-through blocks"), 60b92436efSFangrui Song cl::Hidden, cl::cat(BoltOptCategory)); 61a34c753fSRafael Auler 62a34c753fSRafael Auler } // namespace opts 63a34c753fSRafael Auler 64a34c753fSRafael Auler namespace llvm { 65a34c753fSRafael Auler namespace bolt { 66a34c753fSRafael Auler 67a34c753fSRafael Auler void BinaryFunction::postProcessProfile() { 68a34c753fSRafael Auler if (!hasValidProfile()) { 69a34c753fSRafael Auler clearProfile(); 70a34c753fSRafael Auler return; 71a34c753fSRafael Auler } 72a34c753fSRafael Auler 73a34c753fSRafael Auler if (!(getProfileFlags() & PF_LBR)) 74a34c753fSRafael Auler return; 75a34c753fSRafael Auler 76a34c753fSRafael Auler // If we have at least some branch data for the function indicate that it 77a34c753fSRafael Auler // was executed. 783652483cSRafael Auler if (opts::FixFuncCounts && ExecutionCount == 0) 79a34c753fSRafael Auler ExecutionCount = 1; 80a34c753fSRafael Auler 81a34c753fSRafael Auler // Compute preliminary execution count for each basic block. 82a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 83a34c753fSRafael Auler if ((!BB->isEntryPoint() && !BB->isLandingPad()) || 84a34c753fSRafael Auler BB->ExecutionCount == BinaryBasicBlock::COUNT_NO_PROFILE) 85a34c753fSRafael Auler BB->ExecutionCount = 0; 86a34c753fSRafael Auler } 87a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 88a34c753fSRafael Auler auto SuccBIIter = BB->branch_info_begin(); 89a34c753fSRafael Auler for (BinaryBasicBlock *Succ : BB->successors()) { 90a34c753fSRafael Auler // All incoming edges to the primary entry have been accounted for, thus 91a34c753fSRafael Auler // we skip the update here. 92a34c753fSRafael Auler if (SuccBIIter->Count != BinaryBasicBlock::COUNT_NO_PROFILE && 93a34c753fSRafael Auler Succ != BasicBlocks.front()) 94a34c753fSRafael Auler Succ->setExecutionCount(Succ->getExecutionCount() + SuccBIIter->Count); 95a34c753fSRafael Auler ++SuccBIIter; 96a34c753fSRafael Auler } 97a34c753fSRafael Auler } 98a34c753fSRafael Auler 99ccb99dd1SMaksim Panchenko // Fix for old profiles. 100ccb99dd1SMaksim Panchenko for (BinaryBasicBlock *BB : BasicBlocks) { 101ccb99dd1SMaksim Panchenko if (BB->size() != 1 || BB->succ_size() != 1) 102ccb99dd1SMaksim Panchenko continue; 103ccb99dd1SMaksim Panchenko 104ccb99dd1SMaksim Panchenko if (BB->getKnownExecutionCount() == 0) 105ccb99dd1SMaksim Panchenko continue; 106ccb99dd1SMaksim Panchenko 107ccb99dd1SMaksim Panchenko MCInst *Instr = BB->getFirstNonPseudoInstr(); 108ccb99dd1SMaksim Panchenko assert(Instr && "expected non-pseudo instr"); 109ccb99dd1SMaksim Panchenko if (!BC.MIB->hasAnnotation(*Instr, "NOP")) 110ccb99dd1SMaksim Panchenko continue; 111ccb99dd1SMaksim Panchenko 112ccb99dd1SMaksim Panchenko BinaryBasicBlock *FTSuccessor = BB->getSuccessor(); 113ccb99dd1SMaksim Panchenko BinaryBasicBlock::BinaryBranchInfo &BI = BB->getBranchInfo(*FTSuccessor); 114ccb99dd1SMaksim Panchenko if (!BI.Count) { 115ccb99dd1SMaksim Panchenko BI.Count = BB->getKnownExecutionCount(); 116ccb99dd1SMaksim Panchenko FTSuccessor->setExecutionCount(FTSuccessor->getKnownExecutionCount() + 117ccb99dd1SMaksim Panchenko BI.Count); 118ccb99dd1SMaksim Panchenko } 119ccb99dd1SMaksim Panchenko } 120ccb99dd1SMaksim Panchenko 121a34c753fSRafael Auler if (opts::FixBlockCounts) { 122a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 123a34c753fSRafael Auler // Make sure that execution count of a block is at least the branch count 124a34c753fSRafael Auler // of an incoming/outgoing jump. 125a34c753fSRafael Auler auto SuccBIIter = BB->branch_info_begin(); 126a34c753fSRafael Auler for (BinaryBasicBlock *Succ : BB->successors()) { 127a34c753fSRafael Auler uint64_t Count = SuccBIIter->Count; 128a34c753fSRafael Auler if (Count != BinaryBasicBlock::COUNT_NO_PROFILE && Count > 0) { 129a34c753fSRafael Auler Succ->setExecutionCount(std::max(Succ->getExecutionCount(), Count)); 130a34c753fSRafael Auler BB->setExecutionCount(std::max(BB->getExecutionCount(), Count)); 131a34c753fSRafael Auler } 132a34c753fSRafael Auler ++SuccBIIter; 133a34c753fSRafael Auler } 134a34c753fSRafael Auler // Make sure that execution count of a block is at least the number of 135a34c753fSRafael Auler // function calls from the block. 136a34c753fSRafael Auler for (MCInst &Inst : *BB) { 137a34c753fSRafael Auler // Ignore non-call instruction 138a34c753fSRafael Auler if (!BC.MIB->isCall(Inst)) 139a34c753fSRafael Auler continue; 140a34c753fSRafael Auler 141a34c753fSRafael Auler auto CountAnnt = BC.MIB->tryGetAnnotationAs<uint64_t>(Inst, "Count"); 1423652483cSRafael Auler if (CountAnnt) 143a34c753fSRafael Auler BB->setExecutionCount(std::max(BB->getExecutionCount(), *CountAnnt)); 144a34c753fSRafael Auler } 145a34c753fSRafael Auler } 146a34c753fSRafael Auler } 147a34c753fSRafael Auler 148a34c753fSRafael Auler if (opts::InferFallThroughs) 149a34c753fSRafael Auler inferFallThroughCounts(); 150a34c753fSRafael Auler 151a34c753fSRafael Auler // Update profile information for jump tables based on CFG branch data. 152a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 153a34c753fSRafael Auler const MCInst *LastInstr = BB->getLastNonPseudoInstr(); 154a34c753fSRafael Auler if (!LastInstr) 155a34c753fSRafael Auler continue; 156a34c753fSRafael Auler const uint64_t JTAddress = BC.MIB->getJumpTable(*LastInstr); 157a34c753fSRafael Auler if (!JTAddress) 158a34c753fSRafael Auler continue; 159a34c753fSRafael Auler JumpTable *JT = getJumpTableContainingAddress(JTAddress); 160a34c753fSRafael Auler if (!JT) 161a34c753fSRafael Auler continue; 162a34c753fSRafael Auler 163a34c753fSRafael Auler uint64_t TotalBranchCount = 0; 164a34c753fSRafael Auler for (const BinaryBasicBlock::BinaryBranchInfo &BranchInfo : 165a34c753fSRafael Auler BB->branch_info()) { 166a34c753fSRafael Auler TotalBranchCount += BranchInfo.Count; 167a34c753fSRafael Auler } 168a34c753fSRafael Auler JT->Count += TotalBranchCount; 169a34c753fSRafael Auler 170c3d53720SAmir Ayupov if (opts::ICP < ICP_JUMP_TABLES && opts::JumpTables < JTS_AGGRESSIVE) 171a34c753fSRafael Auler continue; 172a34c753fSRafael Auler 173a34c753fSRafael Auler if (JT->Counts.empty()) 174a34c753fSRafael Auler JT->Counts.resize(JT->Entries.size()); 175a34c753fSRafael Auler auto EI = JT->Entries.begin(); 176a34c753fSRafael Auler uint64_t Delta = (JTAddress - JT->getAddress()) / JT->EntrySize; 177a34c753fSRafael Auler EI += Delta; 178a34c753fSRafael Auler while (EI != JT->Entries.end()) { 179a34c753fSRafael Auler const BinaryBasicBlock *TargetBB = getBasicBlockForLabel(*EI); 180a34c753fSRafael Auler if (TargetBB) { 181a34c753fSRafael Auler const BinaryBasicBlock::BinaryBranchInfo &BranchInfo = 182a34c753fSRafael Auler BB->getBranchInfo(*TargetBB); 183a34c753fSRafael Auler assert(Delta < JT->Counts.size()); 184a34c753fSRafael Auler JT->Counts[Delta].Count += BranchInfo.Count; 185a34c753fSRafael Auler JT->Counts[Delta].Mispreds += BranchInfo.MispredictedCount; 186a34c753fSRafael Auler } 187a34c753fSRafael Auler ++Delta; 188a34c753fSRafael Auler ++EI; 189a34c753fSRafael Auler // A label marks the start of another jump table. 190a34c753fSRafael Auler if (JT->Labels.count(Delta * JT->EntrySize)) 191a34c753fSRafael Auler break; 192a34c753fSRafael Auler } 193a34c753fSRafael Auler } 194a34c753fSRafael Auler } 195a34c753fSRafael Auler 196a34c753fSRafael Auler void BinaryFunction::mergeProfileDataInto(BinaryFunction &BF) const { 197a34c753fSRafael Auler // No reason to merge invalid or empty profiles into BF. 198a34c753fSRafael Auler if (!hasValidProfile()) 199a34c753fSRafael Auler return; 200a34c753fSRafael Auler 201a34c753fSRafael Auler // Update function execution count. 2023652483cSRafael Auler if (getExecutionCount() != BinaryFunction::COUNT_NO_PROFILE) 203a34c753fSRafael Auler BF.setExecutionCount(BF.getKnownExecutionCount() + getExecutionCount()); 204a34c753fSRafael Auler 205a34c753fSRafael Auler // Since we are merging a valid profile, the new profile should be valid too. 206a34c753fSRafael Auler // It has either already been valid, or it has been cleaned up. 207a34c753fSRafael Auler BF.ProfileMatchRatio = 1.0f; 208a34c753fSRafael Auler 209a34c753fSRafael Auler // Update basic block and edge counts. 210a34c753fSRafael Auler auto BBMergeI = BF.begin(); 211a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 212a34c753fSRafael Auler BinaryBasicBlock *BBMerge = &*BBMergeI; 213a34c753fSRafael Auler assert(getIndex(BB) == BF.getIndex(BBMerge)); 214a34c753fSRafael Auler 215a34c753fSRafael Auler // Update basic block count. 216a34c753fSRafael Auler if (BB->getExecutionCount() != BinaryBasicBlock::COUNT_NO_PROFILE) { 21740c2e0faSMaksim Panchenko BBMerge->setExecutionCount(BBMerge->getKnownExecutionCount() + 21840c2e0faSMaksim Panchenko BB->getExecutionCount()); 219a34c753fSRafael Auler } 220a34c753fSRafael Auler 221a34c753fSRafael Auler // Update edge count for successors of this basic block. 222a34c753fSRafael Auler auto BBMergeSI = BBMerge->succ_begin(); 223a34c753fSRafael Auler auto BIMergeI = BBMerge->branch_info_begin(); 224a34c753fSRafael Auler auto BII = BB->branch_info_begin(); 225a34c753fSRafael Auler for (const BinaryBasicBlock *BBSucc : BB->successors()) { 226a34c753fSRafael Auler (void)BBSucc; 227a34c753fSRafael Auler assert(getIndex(BBSucc) == BF.getIndex(*BBMergeSI)); 2281cc54312SKazu Hirata (void)BBMergeSI; 229a34c753fSRafael Auler 230a34c753fSRafael Auler // At this point no branch count should be set to COUNT_NO_PROFILE. 231a34c753fSRafael Auler assert(BII->Count != BinaryBasicBlock::COUNT_NO_PROFILE && 232a34c753fSRafael Auler "unexpected unknown branch profile"); 233a34c753fSRafael Auler assert(BIMergeI->Count != BinaryBasicBlock::COUNT_NO_PROFILE && 234a34c753fSRafael Auler "unexpected unknown branch profile"); 235a34c753fSRafael Auler 236a34c753fSRafael Auler BIMergeI->Count += BII->Count; 237a34c753fSRafael Auler 238a34c753fSRafael Auler // When we merge inferred and real fall-through branch data, the merged 239a34c753fSRafael Auler // data is considered inferred. 240a34c753fSRafael Auler if (BII->MispredictedCount != BinaryBasicBlock::COUNT_INFERRED && 241a34c753fSRafael Auler BIMergeI->MispredictedCount != BinaryBasicBlock::COUNT_INFERRED) { 242a34c753fSRafael Auler BIMergeI->MispredictedCount += BII->MispredictedCount; 243a34c753fSRafael Auler } else { 244a34c753fSRafael Auler BIMergeI->MispredictedCount = BinaryBasicBlock::COUNT_INFERRED; 245a34c753fSRafael Auler } 246a34c753fSRafael Auler 247a34c753fSRafael Auler ++BBMergeSI; 248a34c753fSRafael Auler ++BII; 249a34c753fSRafael Auler ++BIMergeI; 250a34c753fSRafael Auler } 251a34c753fSRafael Auler assert(BBMergeSI == BBMerge->succ_end()); 252a34c753fSRafael Auler 253a34c753fSRafael Auler ++BBMergeI; 254a34c753fSRafael Auler } 255a34c753fSRafael Auler assert(BBMergeI == BF.end()); 256a34c753fSRafael Auler 257a34c753fSRafael Auler // Merge jump tables profile info. 258a34c753fSRafael Auler auto JTMergeI = BF.JumpTables.begin(); 259a34c753fSRafael Auler for (const auto &JTEntry : JumpTables) { 260a34c753fSRafael Auler if (JTMergeI->second->Counts.empty()) 261a34c753fSRafael Auler JTMergeI->second->Counts.resize(JTEntry.second->Counts.size()); 262a34c753fSRafael Auler auto CountMergeI = JTMergeI->second->Counts.begin(); 263a34c753fSRafael Auler for (const JumpTable::JumpInfo &JI : JTEntry.second->Counts) { 264a34c753fSRafael Auler CountMergeI->Count += JI.Count; 265a34c753fSRafael Auler CountMergeI->Mispreds += JI.Mispreds; 266a34c753fSRafael Auler ++CountMergeI; 267a34c753fSRafael Auler } 268a34c753fSRafael Auler assert(CountMergeI == JTMergeI->second->Counts.end()); 269a34c753fSRafael Auler 270a34c753fSRafael Auler ++JTMergeI; 271a34c753fSRafael Auler } 272a34c753fSRafael Auler assert(JTMergeI == BF.JumpTables.end()); 273a34c753fSRafael Auler } 274a34c753fSRafael Auler 275a34c753fSRafael Auler void BinaryFunction::inferFallThroughCounts() { 276a34c753fSRafael Auler // Work on a basic block at a time, propagating frequency information 277a34c753fSRafael Auler // forwards. 278a34c753fSRafael Auler // It is important to walk in the layout order. 279a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 280a34c753fSRafael Auler const uint64_t BBExecCount = BB->getExecutionCount(); 281a34c753fSRafael Auler 282a34c753fSRafael Auler // Propagate this information to successors, filling in fall-through edges 283a34c753fSRafael Auler // with frequency information 284a34c753fSRafael Auler if (BB->succ_size() == 0) 285a34c753fSRafael Auler continue; 286a34c753fSRafael Auler 287a34c753fSRafael Auler // Calculate frequency of outgoing branches from this node according to 288a34c753fSRafael Auler // LBR data. 289a34c753fSRafael Auler uint64_t ReportedBranches = 0; 2903652483cSRafael Auler for (const BinaryBasicBlock::BinaryBranchInfo &SuccBI : BB->branch_info()) 291a34c753fSRafael Auler if (SuccBI.Count != BinaryBasicBlock::COUNT_NO_PROFILE) 292a34c753fSRafael Auler ReportedBranches += SuccBI.Count; 293a34c753fSRafael Auler 294a34c753fSRafael Auler // Get taken count of conditional tail call if the block ends with one. 295a34c753fSRafael Auler uint64_t CTCTakenCount = 0; 296a34c753fSRafael Auler const MCInst *CTCInstr = BB->getLastNonPseudoInstr(); 297a34c753fSRafael Auler if (CTCInstr && BC.MIB->getConditionalTailCall(*CTCInstr)) { 29840c2e0faSMaksim Panchenko CTCTakenCount = BC.MIB->getAnnotationWithDefault<uint64_t>( 29940c2e0faSMaksim Panchenko *CTCInstr, "CTCTakenCount"); 300a34c753fSRafael Auler } 301a34c753fSRafael Auler 302a34c753fSRafael Auler // Calculate frequency of throws from this node according to LBR data 303a34c753fSRafael Auler // for branching into associated landing pads. Since it is possible 304a34c753fSRafael Auler // for a landing pad to be associated with more than one basic blocks, 305a34c753fSRafael Auler // we may overestimate the frequency of throws for such blocks. 306a34c753fSRafael Auler uint64_t ReportedThrows = 0; 3073652483cSRafael Auler for (const BinaryBasicBlock *LP : BB->landing_pads()) 308a34c753fSRafael Auler ReportedThrows += LP->getExecutionCount(); 309a34c753fSRafael Auler 310a34c753fSRafael Auler const uint64_t TotalReportedJumps = 311a34c753fSRafael Auler ReportedBranches + CTCTakenCount + ReportedThrows; 312a34c753fSRafael Auler 313a34c753fSRafael Auler // Infer the frequency of the fall-through edge, representing not taking the 314a34c753fSRafael Auler // branch. 315a34c753fSRafael Auler uint64_t Inferred = 0; 316a34c753fSRafael Auler if (BBExecCount > TotalReportedJumps) 317a34c753fSRafael Auler Inferred = BBExecCount - TotalReportedJumps; 318a34c753fSRafael Auler 319a34c753fSRafael Auler LLVM_DEBUG( 32040c2e0faSMaksim Panchenko if (BBExecCount < TotalReportedJumps) dbgs() 321a34c753fSRafael Auler << "Fall-through inference is slightly inconsistent. " 322a34c753fSRafael Auler "exec frequency is less than the outgoing edges frequency (" 323a34c753fSRafael Auler << BBExecCount << " < " << ReportedBranches 324a34c753fSRafael Auler << ") for BB at offset 0x" 32540c2e0faSMaksim Panchenko << Twine::utohexstr(getAddress() + BB->getOffset()) << '\n';); 326a34c753fSRafael Auler 327a34c753fSRafael Auler if (BB->succ_size() <= 2) { 328a34c753fSRafael Auler // Skip if the last instruction is an unconditional jump. 329a34c753fSRafael Auler const MCInst *LastInstr = BB->getLastNonPseudoInstr(); 33040c2e0faSMaksim Panchenko if (LastInstr && (BC.MIB->isUnconditionalBranch(*LastInstr) || 331a34c753fSRafael Auler BC.MIB->isIndirectBranch(*LastInstr))) 332a34c753fSRafael Auler continue; 333a34c753fSRafael Auler // If there is an FT it will be the last successor. 334a34c753fSRafael Auler auto &SuccBI = *BB->branch_info_rbegin(); 335a34c753fSRafael Auler auto &Succ = *BB->succ_rbegin(); 336a34c753fSRafael Auler if (SuccBI.Count == 0) { 337a34c753fSRafael Auler SuccBI.Count = Inferred; 338a34c753fSRafael Auler SuccBI.MispredictedCount = BinaryBasicBlock::COUNT_INFERRED; 339*cbd30241SShatianWang Succ->ExecutionCount = 340*cbd30241SShatianWang std::max(Succ->getKnownExecutionCount(), Inferred); 341a34c753fSRafael Auler } 342a34c753fSRafael Auler } 343a34c753fSRafael Auler } 344a34c753fSRafael Auler } 345a34c753fSRafael Auler 346a34c753fSRafael Auler void BinaryFunction::clearProfile() { 347a34c753fSRafael Auler // Keep function execution profile the same. Only clear basic block and edge 348a34c753fSRafael Auler // counts. 349a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) { 350a34c753fSRafael Auler BB->ExecutionCount = 0; 351a34c753fSRafael Auler for (BinaryBasicBlock::BinaryBranchInfo &BI : BB->branch_info()) { 352a34c753fSRafael Auler BI.Count = 0; 353a34c753fSRafael Auler BI.MispredictedCount = 0; 354a34c753fSRafael Auler } 355a34c753fSRafael Auler } 356a34c753fSRafael Auler } 357a34c753fSRafael Auler 358a34c753fSRafael Auler } // namespace bolt 359a34c753fSRafael Auler } // namespace llvm 360