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
41*0d477f63SAmir Ayupov static cl::alias ICPAlias("icp",
42*0d477f63SAmir Ayupov cl::desc("Alias for --indirect-call-promotion"),
43*0d477f63SAmir Ayupov cl::aliasopt(ICP));
44*0d477f63SAmir 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
postProcessProfile()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
mergeProfileDataInto(BinaryFunction & BF) const196a34c753fSRafael 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));
228a34c753fSRafael Auler
229a34c753fSRafael Auler // At this point no branch count should be set to COUNT_NO_PROFILE.
230a34c753fSRafael Auler assert(BII->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
231a34c753fSRafael Auler "unexpected unknown branch profile");
232a34c753fSRafael Auler assert(BIMergeI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
233a34c753fSRafael Auler "unexpected unknown branch profile");
234a34c753fSRafael Auler
235a34c753fSRafael Auler BIMergeI->Count += BII->Count;
236a34c753fSRafael Auler
237a34c753fSRafael Auler // When we merge inferred and real fall-through branch data, the merged
238a34c753fSRafael Auler // data is considered inferred.
239a34c753fSRafael Auler if (BII->MispredictedCount != BinaryBasicBlock::COUNT_INFERRED &&
240a34c753fSRafael Auler BIMergeI->MispredictedCount != BinaryBasicBlock::COUNT_INFERRED) {
241a34c753fSRafael Auler BIMergeI->MispredictedCount += BII->MispredictedCount;
242a34c753fSRafael Auler } else {
243a34c753fSRafael Auler BIMergeI->MispredictedCount = BinaryBasicBlock::COUNT_INFERRED;
244a34c753fSRafael Auler }
245a34c753fSRafael Auler
246a34c753fSRafael Auler ++BBMergeSI;
247a34c753fSRafael Auler ++BII;
248a34c753fSRafael Auler ++BIMergeI;
249a34c753fSRafael Auler }
250a34c753fSRafael Auler assert(BBMergeSI == BBMerge->succ_end());
251a34c753fSRafael Auler
252a34c753fSRafael Auler ++BBMergeI;
253a34c753fSRafael Auler }
254a34c753fSRafael Auler assert(BBMergeI == BF.end());
255a34c753fSRafael Auler
256a34c753fSRafael Auler // Merge jump tables profile info.
257a34c753fSRafael Auler auto JTMergeI = BF.JumpTables.begin();
258a34c753fSRafael Auler for (const auto &JTEntry : JumpTables) {
259a34c753fSRafael Auler if (JTMergeI->second->Counts.empty())
260a34c753fSRafael Auler JTMergeI->second->Counts.resize(JTEntry.second->Counts.size());
261a34c753fSRafael Auler auto CountMergeI = JTMergeI->second->Counts.begin();
262a34c753fSRafael Auler for (const JumpTable::JumpInfo &JI : JTEntry.second->Counts) {
263a34c753fSRafael Auler CountMergeI->Count += JI.Count;
264a34c753fSRafael Auler CountMergeI->Mispreds += JI.Mispreds;
265a34c753fSRafael Auler ++CountMergeI;
266a34c753fSRafael Auler }
267a34c753fSRafael Auler assert(CountMergeI == JTMergeI->second->Counts.end());
268a34c753fSRafael Auler
269a34c753fSRafael Auler ++JTMergeI;
270a34c753fSRafael Auler }
271a34c753fSRafael Auler assert(JTMergeI == BF.JumpTables.end());
272a34c753fSRafael Auler }
273a34c753fSRafael Auler
inferFallThroughCounts()274a34c753fSRafael Auler void BinaryFunction::inferFallThroughCounts() {
275a34c753fSRafael Auler // Work on a basic block at a time, propagating frequency information
276a34c753fSRafael Auler // forwards.
277a34c753fSRafael Auler // It is important to walk in the layout order.
278a34c753fSRafael Auler for (BinaryBasicBlock *BB : BasicBlocks) {
279a34c753fSRafael Auler const uint64_t BBExecCount = BB->getExecutionCount();
280a34c753fSRafael Auler
281a34c753fSRafael Auler // Propagate this information to successors, filling in fall-through edges
282a34c753fSRafael Auler // with frequency information
283a34c753fSRafael Auler if (BB->succ_size() == 0)
284a34c753fSRafael Auler continue;
285a34c753fSRafael Auler
286a34c753fSRafael Auler // Calculate frequency of outgoing branches from this node according to
287a34c753fSRafael Auler // LBR data.
288a34c753fSRafael Auler uint64_t ReportedBranches = 0;
2893652483cSRafael Auler for (const BinaryBasicBlock::BinaryBranchInfo &SuccBI : BB->branch_info())
290a34c753fSRafael Auler if (SuccBI.Count != BinaryBasicBlock::COUNT_NO_PROFILE)
291a34c753fSRafael Auler ReportedBranches += SuccBI.Count;
292a34c753fSRafael Auler
293a34c753fSRafael Auler // Get taken count of conditional tail call if the block ends with one.
294a34c753fSRafael Auler uint64_t CTCTakenCount = 0;
295a34c753fSRafael Auler const MCInst *CTCInstr = BB->getLastNonPseudoInstr();
296a34c753fSRafael Auler if (CTCInstr && BC.MIB->getConditionalTailCall(*CTCInstr)) {
29740c2e0faSMaksim Panchenko CTCTakenCount = BC.MIB->getAnnotationWithDefault<uint64_t>(
29840c2e0faSMaksim Panchenko *CTCInstr, "CTCTakenCount");
299a34c753fSRafael Auler }
300a34c753fSRafael Auler
301a34c753fSRafael Auler // Calculate frequency of throws from this node according to LBR data
302a34c753fSRafael Auler // for branching into associated landing pads. Since it is possible
303a34c753fSRafael Auler // for a landing pad to be associated with more than one basic blocks,
304a34c753fSRafael Auler // we may overestimate the frequency of throws for such blocks.
305a34c753fSRafael Auler uint64_t ReportedThrows = 0;
3063652483cSRafael Auler for (const BinaryBasicBlock *LP : BB->landing_pads())
307a34c753fSRafael Auler ReportedThrows += LP->getExecutionCount();
308a34c753fSRafael Auler
309a34c753fSRafael Auler const uint64_t TotalReportedJumps =
310a34c753fSRafael Auler ReportedBranches + CTCTakenCount + ReportedThrows;
311a34c753fSRafael Auler
312a34c753fSRafael Auler // Infer the frequency of the fall-through edge, representing not taking the
313a34c753fSRafael Auler // branch.
314a34c753fSRafael Auler uint64_t Inferred = 0;
315a34c753fSRafael Auler if (BBExecCount > TotalReportedJumps)
316a34c753fSRafael Auler Inferred = BBExecCount - TotalReportedJumps;
317a34c753fSRafael Auler
318a34c753fSRafael Auler LLVM_DEBUG(
31940c2e0faSMaksim Panchenko if (BBExecCount < TotalReportedJumps) dbgs()
320a34c753fSRafael Auler << "Fall-through inference is slightly inconsistent. "
321a34c753fSRafael Auler "exec frequency is less than the outgoing edges frequency ("
322a34c753fSRafael Auler << BBExecCount << " < " << ReportedBranches
323a34c753fSRafael Auler << ") for BB at offset 0x"
32440c2e0faSMaksim Panchenko << Twine::utohexstr(getAddress() + BB->getOffset()) << '\n';);
325a34c753fSRafael Auler
326a34c753fSRafael Auler if (BB->succ_size() <= 2) {
327a34c753fSRafael Auler // Skip if the last instruction is an unconditional jump.
328a34c753fSRafael Auler const MCInst *LastInstr = BB->getLastNonPseudoInstr();
32940c2e0faSMaksim Panchenko if (LastInstr && (BC.MIB->isUnconditionalBranch(*LastInstr) ||
330a34c753fSRafael Auler BC.MIB->isIndirectBranch(*LastInstr)))
331a34c753fSRafael Auler continue;
332a34c753fSRafael Auler // If there is an FT it will be the last successor.
333a34c753fSRafael Auler auto &SuccBI = *BB->branch_info_rbegin();
334a34c753fSRafael Auler auto &Succ = *BB->succ_rbegin();
335a34c753fSRafael Auler if (SuccBI.Count == 0) {
336a34c753fSRafael Auler SuccBI.Count = Inferred;
337a34c753fSRafael Auler SuccBI.MispredictedCount = BinaryBasicBlock::COUNT_INFERRED;
338a34c753fSRafael Auler Succ->ExecutionCount += Inferred;
339a34c753fSRafael Auler }
340a34c753fSRafael Auler }
341a34c753fSRafael Auler }
342a34c753fSRafael Auler
343a34c753fSRafael Auler return;
344a34c753fSRafael Auler }
345a34c753fSRafael Auler
clearProfile()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