LLVM 23.0.0git
ProfileSummaryInfo.h
Go to the documentation of this file.
1//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
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 contains a pass that provides access to profile summary
10// information.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ANALYSIS_PROFILESUMMARYINFO_H
15#define LLVM_ANALYSIS_PROFILESUMMARYINFO_H
16
17#include "llvm/ADT/DenseMap.h"
18#include "llvm/IR/Function.h"
20#include "llvm/IR/PassManager.h"
22#include "llvm/Pass.h"
25#include <memory>
26#include <optional>
27
28namespace llvm {
30class MachineFunction;
31
32/// Analysis providing profile information.
33///
34/// This is an immutable analysis pass that provides ability to query global
35/// (program-level) profile information. The main APIs are isHotCount and
36/// isColdCount that tells whether a given profile count is considered hot/cold
37/// based on the profile summary. This also provides convenience methods to
38/// check whether a function is hot or cold.
39
40// FIXME: Provide convenience methods to determine hotness/coldness of other IR
41// units. This would require making this depend on BFI.
43private:
44 const Module *M;
45 std::unique_ptr<ProfileSummary> Summary;
46 void computeThresholds();
47 // Count thresholds to answer isHotCount and isColdCount queries.
48 std::optional<uint64_t> HotCountThreshold, ColdCountThreshold;
49 // True if the working set size of the code is considered huge,
50 // because the number of profile counts required to reach the hot
51 // percentile is above a huge threshold.
52 std::optional<bool> HasHugeWorkingSetSize;
53 // True if the working set size of the code is considered large,
54 // because the number of profile counts required to reach the hot
55 // percentile is above a large threshold.
56 std::optional<bool> HasLargeWorkingSetSize;
57 // Compute the threshold for a given cutoff.
58 std::optional<uint64_t> computeThreshold(int PercentileCutoff) const;
59 // The map that caches the threshold values. The keys are the percentile
60 // cutoff values and the values are the corresponding threshold values.
61 mutable DenseMap<int, uint64_t> ThresholdCache;
62
63public:
64 ProfileSummaryInfo(const Module &M) : M(&M) { refresh(); }
66
67 /// If a summary is provided as argument, use that. Otherwise,
68 /// if the `Summary` member is null, attempt to refresh.
69 LLVM_ABI void refresh(std::unique_ptr<ProfileSummary> &&Other = nullptr);
70
71 /// Returns true if profile summary is available.
72 bool hasProfileSummary() const { return Summary != nullptr; }
73
74 /// Returns true if module \c M has sample profile.
75 bool hasSampleProfile() const {
76 return hasProfileSummary() &&
77 Summary->getKind() == ProfileSummary::PSK_Sample;
78 }
79
80 /// Returns true if module \c M has instrumentation profile.
82 return hasProfileSummary() &&
83 Summary->getKind() == ProfileSummary::PSK_Instr;
84 }
85
86 /// Returns true if module \c M has context sensitive instrumentation profile.
88 return hasProfileSummary() &&
89 Summary->getKind() == ProfileSummary::PSK_CSInstr;
90 }
91
92 /// Handle the invalidation of this information.
93 ///
94 /// When used as a result of \c ProfileSummaryAnalysis this method will be
95 /// called when the module this was computed for changes. Since profile
96 /// summary is immutable after it is annotated on the module, we return false
97 /// here.
99 ModuleAnalysisManager::Invalidator &) {
100 return false;
101 }
102
103 /// Returns the profile count for \p CallInst.
104 LLVM_ABI std::optional<uint64_t>
106 /// Returns true if module \c M has partial-profile sample profile.
108 /// Returns true if the working set size of the code is considered huge.
109 LLVM_ABI bool hasHugeWorkingSetSize() const;
110 /// Returns true if the working set size of the code is considered large.
111 LLVM_ABI bool hasLargeWorkingSetSize() const;
112 /// Returns true if \p F has hot function entry. If it returns false, it
113 /// either means it is not hot or it is unknown whether it is hot or not (for
114 /// example, no profile data is available).
115 template <typename FuncT> bool isFunctionEntryHot(const FuncT *F) const {
116 if (!F || !hasProfileSummary())
117 return false;
118 std::optional<uint64_t> FunctionCount = getEntryCount(F);
119 // FIXME: The heuristic used below for determining hotness is based on
120 // preliminary SPEC tuning for inliner. This will eventually be a
121 // convenience method that calls isHotCount.
122 return FunctionCount && isHotCount(*FunctionCount);
123 }
124
125 /// Returns true if \p F contains hot code.
126 template <typename FuncT, typename BFIT>
127 bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const {
128 if (!F || !hasProfileSummary())
129 return false;
130 if (auto FunctionCount = getEntryCount(F))
131 if (isHotCount(*FunctionCount))
132 return true;
133
134 if (auto TotalCallCount = getTotalCallCount(F))
135 if (isHotCount(*TotalCallCount))
136 return true;
137
138 for (const auto &BB : *F)
139 if (isHotBlock(&BB, &BFI))
140 return true;
141 return false;
142 }
143 /// Returns true if \p F has cold function entry.
144 LLVM_ABI bool isFunctionEntryCold(const Function *F) const;
145 /// Returns true if \p F contains only cold code.
146 template <typename FuncT, typename BFIT>
147 bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const {
148 if (!F || !hasProfileSummary())
149 return false;
150 if (auto FunctionCount = getEntryCount(F))
151 if (!isColdCount(*FunctionCount))
152 return false;
153
154 if (auto TotalCallCount = getTotalCallCount(F))
155 if (!isColdCount(*TotalCallCount))
156 return false;
157
158 for (const auto &BB : *F)
159 if (!isColdBlock(&BB, &BFI))
160 return false;
161 return true;
162 }
163 /// Returns true if the hotness of \p F is unknown.
164 LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const;
165 /// Returns true if \p F contains hot code with regard to a given hot
166 /// percentile cutoff value.
167 template <typename FuncT, typename BFIT>
169 const FuncT *F, BFIT &BFI) const {
170 return isFunctionHotOrColdInCallGraphNthPercentile<true, FuncT, BFIT>(
171 PercentileCutoff, F, BFI);
172 }
173 /// Returns true if \p F contains cold code with regard to a given cold
174 /// percentile cutoff value.
175 template <typename FuncT, typename BFIT>
177 const FuncT *F, BFIT &BFI) const {
178 return isFunctionHotOrColdInCallGraphNthPercentile<false, FuncT, BFIT>(
179 PercentileCutoff, F, BFI);
180 }
181 /// Returns true if count \p C is considered hot.
182 LLVM_ABI bool isHotCount(uint64_t C) const;
183 /// Returns true if count \p C is considered cold.
184 LLVM_ABI bool isColdCount(uint64_t C) const;
185 /// Returns true if count \p C is considered hot with regard to a given
186 /// hot percentile cutoff value.
187 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
188 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
190 /// Returns true if count \p C is considered cold with regard to a given
191 /// cold percentile cutoff value.
192 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
193 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
195 uint64_t C) const;
196
197 /// Returns true if BasicBlock \p BB is considered hot.
198 template <typename BBType, typename BFIT>
199 bool isHotBlock(const BBType *BB, BFIT *BFI) const {
200 auto Count = BFI->getBlockProfileCount(BB);
201 return Count && isHotCount(*Count);
202 }
203
204 /// Returns true if BasicBlock \p BB is considered cold.
205 template <typename BBType, typename BFIT>
206 bool isColdBlock(const BBType *BB, BFIT *BFI) const {
207 auto Count = BFI->getBlockProfileCount(BB);
208 return Count && isColdCount(*Count);
209 }
210
211 template <typename BFIT>
212 bool isColdBlock(BlockFrequency BlockFreq, const BFIT *BFI) const {
213 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
214 return Count && isColdCount(*Count);
215 }
216
217 template <typename BBType, typename BFIT>
218 bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB,
219 BFIT *BFI) const {
220 return isHotOrColdBlockNthPercentile<true, BBType, BFIT>(PercentileCutoff,
221 BB, BFI);
222 }
223
224 template <typename BFIT>
226 BFIT *BFI) const {
227 return isHotOrColdBlockNthPercentile<true, BFIT>(PercentileCutoff,
228 BlockFreq, BFI);
229 }
230
231 /// Returns true if BasicBlock \p BB is considered cold with regard to a given
232 /// cold percentile cutoff value.
233 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
234 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
235 template <typename BBType, typename BFIT>
236 bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
237 BFIT *BFI) const {
238 return isHotOrColdBlockNthPercentile<false, BBType, BFIT>(PercentileCutoff,
239 BB, BFI);
240 }
241 template <typename BFIT>
243 BFIT *BFI) const {
244 return isHotOrColdBlockNthPercentile<false, BFIT>(PercentileCutoff,
245 BlockFreq, BFI);
246 }
247 /// Returns true if the call site \p CB is considered hot.
248 LLVM_ABI bool isHotCallSite(const CallBase &CB,
249 BlockFrequencyInfo *BFI) const;
250 /// Returns true if call site \p CB is considered cold.
251 LLVM_ABI bool isColdCallSite(const CallBase &CB,
252 BlockFrequencyInfo *BFI) const;
253 /// Returns HotCountThreshold if set. Recompute HotCountThreshold
254 /// if not set.
256 /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
257 /// if not set.
259 /// Returns HotCountThreshold if set.
261 return HotCountThreshold.value_or(0);
262 }
263 /// Returns ColdCountThreshold if set.
265 return ColdCountThreshold.value_or(0);
266 }
267
268private:
269 template <typename FuncT>
270 std::optional<uint64_t> getTotalCallCount(const FuncT *F) const {
271 return std::nullopt;
272 }
273
274 template <bool isHot, typename FuncT, typename BFIT>
275 bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff,
276 const FuncT *F,
277 BFIT &FI) const {
278 if (!F || !hasProfileSummary())
279 return false;
280 if (auto FunctionCount = getEntryCount(F)) {
281 if (isHot && isHotCountNthPercentile(PercentileCutoff, *FunctionCount))
282 return true;
283 if (!isHot && !isColdCountNthPercentile(PercentileCutoff, *FunctionCount))
284 return false;
285 }
286 if (auto TotalCallCount = getTotalCallCount(F)) {
287 if (isHot && isHotCountNthPercentile(PercentileCutoff, *TotalCallCount))
288 return true;
289 if (!isHot &&
291 return false;
292 }
293 for (const auto &BB : *F) {
294 if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &FI))
295 return true;
296 if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &FI))
297 return false;
298 }
299 return !isHot;
300 }
301
302 template <bool isHot>
303 bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
304
305 template <bool isHot, typename BBType, typename BFIT>
306 bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
307 BFIT *BFI) const {
308 auto Count = BFI->getBlockProfileCount(BB);
309 if constexpr (isHot)
311 else
313 }
314
315 template <bool isHot, typename BFIT>
316 bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
317 BlockFrequency BlockFreq,
318 BFIT *BFI) const {
319 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
320 if constexpr (isHot)
322 else
324 }
325
326 template <typename FuncT>
327 std::optional<uint64_t> getEntryCount(const FuncT *F) const {
328 return F->getEntryCount();
329 }
330};
331
332template <>
333inline std::optional<uint64_t>
334ProfileSummaryInfo::getTotalCallCount<Function>(const Function *F) const {
335 if (!hasSampleProfile())
336 return std::nullopt;
337 uint64_t TotalCallCount = 0;
338 for (const auto &BB : *F)
339 for (const auto &I : BB)
341 if (auto CallCount = getProfileCount(cast<CallBase>(I), nullptr))
342 TotalCallCount += *CallCount;
343 return TotalCallCount;
344}
345
346// Declare template specialization for llvm::MachineFunction. Do not implement
347// here, because we cannot include MachineFunction header here, that would break
348// dependency rules.
349template <>
350std::optional<uint64_t> ProfileSummaryInfo::getEntryCount<MachineFunction>(
351 const MachineFunction *F) const;
352
353/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
355 std::unique_ptr<ProfileSummaryInfo> PSI;
356
357public:
358 static char ID;
360
361 ProfileSummaryInfo &getPSI() { return *PSI; }
362 const ProfileSummaryInfo &getPSI() const { return *PSI; }
363
364 bool doInitialization(Module &M) override;
365 bool doFinalization(Module &M) override;
366 void getAnalysisUsage(AnalysisUsage &AU) const override {
367 AU.setPreservesAll();
368 }
369};
370
371/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
373 : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
374public:
376
378
379private:
381 LLVM_ABI static AnalysisKey Key;
382};
383
384/// Printer pass that uses \c ProfileSummaryAnalysis.
386 : public RequiredPassInfoMixin<ProfileSummaryPrinterPass> {
387 raw_ostream &OS;
388
389public:
390 explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
392};
393
394} // end namespace llvm
395
396#endif
#define LLVM_ABI
Definition Compiler.h:215
This file defines the DenseMap class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static cl::opt< unsigned > PercentileCutoff("mfs-psi-cutoff", cl::desc("Percentile profile summary cutoff used to " "determine cold blocks. Unused if set to zero."), cl::init(999950), cl::Hidden)
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
This class represents a function call, abstracting a target machine's calling convention.
ImmutablePass(char &pid)
Definition Pass.h:287
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
LLVM_ABI Result run(Module &M, ModuleAnalysisManager &)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
const ProfileSummaryInfo & getPSI() const
Analysis providing profile information.
bool hasCSInstrumentationProfile() const
Returns true if module M has context sensitive instrumentation profile.
LLVM_ABI uint64_t getOrCompColdCountThreshold() const
Returns ColdCountThreshold if set.
bool hasProfileSummary() const
Returns true if profile summary is available.
bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB, BFIT *BFI) const
bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains only cold code.
LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const
Returns true if the hotness of F is unknown.
bool hasInstrumentationProfile() const
Returns true if module M has instrumentation profile.
bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff, const FuncT *F, BFIT &BFI) const
Returns true if F contains cold code with regard to a given cold percentile cutoff value.
bool hasSampleProfile() const
Returns true if module M has sample profile.
bool isFunctionEntryHot(const FuncT *F) const
Returns true if F has hot function entry.
bool isColdBlock(const BBType *BB, BFIT *BFI) const
Returns true if BasicBlock BB is considered cold.
LLVM_ABI bool isColdCount(uint64_t C) const
Returns true if count C is considered cold.
bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff, const FuncT *F, BFIT &BFI) const
Returns true if F contains hot code with regard to a given hot percentile cutoff value.
LLVM_ABI bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const
Returns true if count C is considered cold with regard to a given cold percentile cutoff value.
LLVM_ABI void refresh(std::unique_ptr< ProfileSummary > &&Other=nullptr)
If a summary is provided as argument, use that.
LLVM_ABI bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const
Returns true if count C is considered hot with regard to a given hot percentile cutoff value.
uint64_t getColdCountThreshold() const
Returns ColdCountThreshold if set.
bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const
Returns true if F contains hot code.
bool isColdBlock(BlockFrequency BlockFreq, const BFIT *BFI) const
LLVM_ABI bool hasPartialSampleProfile() const
Returns true if module M has partial-profile sample profile.
LLVM_ABI bool hasLargeWorkingSetSize() const
Returns true if the working set size of the code is considered large.
LLVM_ABI bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const
Returns true if call site CB is considered cold.
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)=default
LLVM_ABI bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const
Returns true if the call site CB is considered hot.
ProfileSummaryInfo(const Module &M)
uint64_t getHotCountThreshold() const
Returns HotCountThreshold if set.
bool isHotBlock(const BBType *BB, BFIT *BFI) const
Returns true if BasicBlock BB is considered hot.
bool isColdBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq, BFIT *BFI) const
LLVM_ABI bool isHotCount(uint64_t C) const
Returns true if count C is considered hot.
LLVM_ABI bool hasHugeWorkingSetSize() const
Returns true if the working set size of the code is considered huge.
bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB, BFIT *BFI) const
Returns true if BasicBlock BB is considered cold with regard to a given cold percentile cutoff value.
LLVM_ABI uint64_t getOrCompHotCountThreshold() const
Returns HotCountThreshold if set.
bool isHotBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq, BFIT *BFI) const
bool invalidate(Module &, const PreservedAnalyses &, ModuleAnalysisManager::Invalidator &)
Handle the invalidation of this information.
LLVM_ABI std::optional< uint64_t > getProfileCount(const CallBase &CallInst, BlockFrequencyInfo *BFI) const
Returns the profile count for CallInst.
LLVM_ABI bool isFunctionEntryCold(const Function *F) const
Returns true if F has cold function entry.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
A CRTP mix-in for passes that should not be skipped.