xref: /llvm-project/bolt/lib/Core/BinaryFunctionProfile.cpp (revision cbd302410e9f27013223a96edcd78dfb597979e1)
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