LLVM 24.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 {
29struct AnalysisOptions;
31class MachineFunction;
32
33/// Analysis providing profile information.
34///
35/// This is an immutable analysis pass that provides ability to query global
36/// (program-level) profile information. The main APIs are isHotCount and
37/// isColdCount that tells whether a given profile count is considered hot/cold
38/// based on the profile summary. This also provides convenience methods to
39/// check whether a function is hot or cold.
40
41// FIXME: Provide convenience methods to determine hotness/coldness of other IR
42// units. This would require making this depend on BFI.
44private:
45 const AnalysisOptions &Opts;
46 const Module *M;
47 std::unique_ptr<ProfileSummary> Summary;
48 void computeThresholds();
49 // Count thresholds to answer isHotCount and isColdCount queries.
50 std::optional<uint64_t> HotCountThreshold, ColdCountThreshold;
51 // True if the working set size of the code is considered huge,
52 // because the number of profile counts required to reach the hot
53 // percentile is above a huge threshold.
54 std::optional<bool> HasHugeWorkingSetSize;
55 // True if the working set size of the code is considered large,
56 // because the number of profile counts required to reach the hot
57 // percentile is above a large threshold.
58 std::optional<bool> HasLargeWorkingSetSize;
59 // Compute the threshold for a given cutoff.
60 std::optional<uint64_t> computeThreshold(int PercentileCutoff) const;
61 // The map that caches the threshold values. The keys are the percentile
62 // cutoff values and the values are the corresponding threshold values.
63 mutable DenseMap<int, uint64_t> ThresholdCache;
64
65public:
68
69 /// If a summary is provided as argument, use that. Otherwise,
70 /// if the `Summary` member is null, attempt to refresh.
71 LLVM_ABI void refresh(std::unique_ptr<ProfileSummary> &&Other = nullptr);
72
73 /// Returns true if profile summary is available.
74 bool hasProfileSummary() const { return Summary != nullptr; }
75
76 /// Returns true if module \c M has sample profile.
77 bool hasSampleProfile() const {
78 return hasProfileSummary() &&
79 Summary->getKind() == ProfileSummary::PSK_Sample;
80 }
81
82 /// Returns true if module \c M has instrumentation profile.
84 return hasProfileSummary() &&
85 Summary->getKind() == ProfileSummary::PSK_Instr;
86 }
87
88 /// Returns true if module \c M has context sensitive instrumentation profile.
90 return hasProfileSummary() &&
91 Summary->getKind() == ProfileSummary::PSK_CSInstr;
92 }
93
94 /// Handle the invalidation of this information.
95 ///
96 /// When used as a result of \c ProfileSummaryAnalysis this method will be
97 /// called when the module this was computed for changes. Since profile
98 /// summary is immutable after it is annotated on the module, we return false
99 /// here.
101 ModuleAnalysisManager::Invalidator &) {
102 return false;
103 }
104
105 /// Returns the profile count for \p CallInst.
106 LLVM_ABI std::optional<uint64_t>
108 /// Returns true if module \c M has partial-profile sample profile.
110 /// Returns true if the working set size of the code is considered huge.
111 LLVM_ABI bool hasHugeWorkingSetSize() const;
112 /// Returns true if the working set size of the code is considered large.
113 LLVM_ABI bool hasLargeWorkingSetSize() const;
114 /// Returns true if \p F has hot function entry. If it returns false, it
115 /// either means it is not hot or it is unknown whether it is hot or not (for
116 /// example, no profile data is available).
117 template <typename FuncT> bool isFunctionEntryHot(const FuncT *F) const {
118 if (!F)
119 return false;
120 // The hot attribute is a manual alternative to profile data, and takes
121 // precedence over it. Check it before the profile summary so that it is
122 // also honored when no profile is available.
123 if (hasHotAttr(F))
124 return true;
125 if (!hasProfileSummary())
126 return false;
127 std::optional<uint64_t> FunctionCount = getEntryCount(F);
128 // FIXME: The heuristic used below for determining hotness is based on
129 // preliminary SPEC tuning for inliner. This will eventually be a
130 // convenience method that calls isHotCount.
131 return FunctionCount && isHotCount(*FunctionCount);
132 }
133
134 /// Returns true if \p F contains hot code.
135 template <typename FuncT, typename BFIT>
136 bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const {
137 if (!F)
138 return false;
139 // The hot attribute is a manual alternative to profile data, and takes
140 // precedence over it. Check it before the profile summary so that it is
141 // also honored when no profile is available.
142 if (hasHotAttr(F))
143 return true;
144 if (!hasProfileSummary())
145 return false;
146 if (auto FunctionCount = getEntryCount(F))
147 if (isHotCount(*FunctionCount))
148 return true;
149
150 if (auto TotalCallCount = getTotalCallCount(F))
151 if (isHotCount(*TotalCallCount))
152 return true;
153
154 for (const auto &BB : *F)
155 if (isHotBlock(&BB, &BFI))
156 return true;
157 return false;
158 }
159 /// Returns true if \p F has cold function entry.
160 LLVM_ABI bool isFunctionEntryCold(const Function *F) const;
161 /// Returns true if \p F contains only cold code.
162 template <typename FuncT, typename BFIT>
163 bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const {
164 if (!F)
165 return false;
166 // The hot attribute is a manual alternative to profile data, and takes
167 // precedence over it. Check it before the profile summary so that it is
168 // also honored when no profile is available.
169 if (hasHotAttr(F))
170 return false;
171 if (!hasProfileSummary())
172 return false;
173 if (auto FunctionCount = getEntryCount(F))
174 if (!isColdCount(*FunctionCount))
175 return false;
176
177 if (auto TotalCallCount = getTotalCallCount(F))
178 if (!isColdCount(*TotalCallCount))
179 return false;
180
181 for (const auto &BB : *F)
182 if (!isColdBlock(&BB, &BFI))
183 return false;
184 return true;
185 }
186 /// Returns true if the hotness of \p F is unknown.
187 LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const;
188 /// Returns true if \p F contains hot code with regard to a given hot
189 /// percentile cutoff value.
190 template <typename FuncT, typename BFIT>
192 const FuncT *F, BFIT &BFI) const {
193 return isFunctionHotOrColdInCallGraphNthPercentile<true, FuncT, BFIT>(
194 PercentileCutoff, F, BFI);
195 }
196 /// Returns true if \p F contains cold code with regard to a given cold
197 /// percentile cutoff value.
198 template <typename FuncT, typename BFIT>
200 const FuncT *F, BFIT &BFI) const {
201 return isFunctionHotOrColdInCallGraphNthPercentile<false, FuncT, BFIT>(
202 PercentileCutoff, F, BFI);
203 }
204 /// Returns true if count \p C is considered hot.
205 LLVM_ABI bool isHotCount(uint64_t C) const;
206 /// Returns true if count \p C is considered cold.
207 LLVM_ABI bool isColdCount(uint64_t C) const;
208 /// Returns true if count \p C is considered hot with regard to a given
209 /// hot percentile cutoff value.
210 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
211 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
213 /// Returns true if count \p C is considered cold with regard to a given
214 /// cold percentile cutoff value.
215 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
216 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
218 uint64_t C) const;
219
220 /// Returns true if BasicBlock \p BB is considered hot.
221 template <typename BBType, typename BFIT>
222 bool isHotBlock(const BBType *BB, BFIT *BFI) const {
223 auto Count = BFI->getBlockProfileCount(BB);
224 return Count && isHotCount(*Count);
225 }
226
227 /// Returns true if BasicBlock \p BB is considered cold.
228 template <typename BBType, typename BFIT>
229 bool isColdBlock(const BBType *BB, BFIT *BFI) const {
230 auto Count = BFI->getBlockProfileCount(BB);
231 return Count && isColdCount(*Count);
232 }
233
234 template <typename BFIT>
235 bool isColdBlock(BlockFrequency BlockFreq, const BFIT *BFI) const {
236 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
237 return Count && isColdCount(*Count);
238 }
239
240 template <typename BBType, typename BFIT>
241 bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB,
242 BFIT *BFI) const {
243 return isHotOrColdBlockNthPercentile<true, BBType, BFIT>(PercentileCutoff,
244 BB, BFI);
245 }
246
247 template <typename BFIT>
249 BFIT *BFI) const {
250 return isHotOrColdBlockNthPercentile<true, BFIT>(PercentileCutoff,
251 BlockFreq, BFI);
252 }
253
254 /// Returns true if BasicBlock \p BB is considered cold with regard to a given
255 /// cold percentile cutoff value.
256 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
257 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
258 template <typename BBType, typename BFIT>
259 bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
260 BFIT *BFI) const {
261 return isHotOrColdBlockNthPercentile<false, BBType, BFIT>(PercentileCutoff,
262 BB, BFI);
263 }
264 template <typename BFIT>
266 BFIT *BFI) const {
267 return isHotOrColdBlockNthPercentile<false, BFIT>(PercentileCutoff,
268 BlockFreq, BFI);
269 }
270 /// Returns true if the call site \p CB is considered hot.
271 LLVM_ABI bool isHotCallSite(const CallBase &CB,
272 BlockFrequencyInfo *BFI) const;
273 /// Returns true if call site \p CB is considered cold.
274 LLVM_ABI bool isColdCallSite(const CallBase &CB,
275 BlockFrequencyInfo *BFI) const;
276 /// Returns HotCountThreshold if set. Recompute HotCountThreshold
277 /// if not set.
279 /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
280 /// if not set.
282 /// Returns HotCountThreshold if set.
284 return HotCountThreshold.value_or(0);
285 }
286 /// Returns ColdCountThreshold if set.
288 return ColdCountThreshold.value_or(0);
289 }
290
291private:
292 template <typename FuncT>
293 std::optional<uint64_t> getTotalCallCount(const FuncT *F) const {
294 return std::nullopt;
295 }
296
297 template <bool isHot, typename FuncT, typename BFIT>
298 bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff,
299 const FuncT *F,
300 BFIT &FI) const {
301 if (!F || !hasProfileSummary())
302 return false;
303 if (auto FunctionCount = getEntryCount(F)) {
304 if (isHot && isHotCountNthPercentile(PercentileCutoff, *FunctionCount))
305 return true;
306 if (!isHot && !isColdCountNthPercentile(PercentileCutoff, *FunctionCount))
307 return false;
308 }
309 if (auto TotalCallCount = getTotalCallCount(F)) {
310 if (isHot && isHotCountNthPercentile(PercentileCutoff, *TotalCallCount))
311 return true;
312 if (!isHot &&
314 return false;
315 }
316 for (const auto &BB : *F) {
317 if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &FI))
318 return true;
319 if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &FI))
320 return false;
321 }
322 return !isHot;
323 }
324
325 template <bool isHot>
326 bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
327
328 template <bool isHot, typename BBType, typename BFIT>
329 bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
330 BFIT *BFI) const {
331 auto Count = BFI->getBlockProfileCount(BB);
332 if constexpr (isHot)
334 else
336 }
337
338 template <bool isHot, typename BFIT>
339 bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
340 BlockFrequency BlockFreq,
341 BFIT *BFI) const {
342 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
343 if constexpr (isHot)
345 else
347 }
348
349 template <typename FuncT>
350 std::optional<uint64_t> getEntryCount(const FuncT *F) const {
351 return F->getEntryCount();
352 }
353
354 /// Returns true if \p F is annotated with the hot attribute, which takes
355 /// precedence over any profile information.
356 template <typename FuncT> bool hasHotAttr(const FuncT *F) const {
357 return F->hasFnAttribute(Attribute::Hot);
358 }
359};
360
361template <>
362inline std::optional<uint64_t>
363ProfileSummaryInfo::getTotalCallCount<Function>(const Function *F) const {
364 if (!hasSampleProfile())
365 return std::nullopt;
366 uint64_t TotalCallCount = 0;
367 for (const auto &BB : *F)
368 for (const auto &I : BB)
370 if (auto CallCount = getProfileCount(cast<CallBase>(I), nullptr))
371 TotalCallCount += *CallCount;
372 return TotalCallCount;
373}
374
375// Declare template specializations for llvm::MachineFunction. Do not implement
376// here, because we cannot include MachineFunction header here, that would break
377// dependency rules.
378template <>
379std::optional<uint64_t> ProfileSummaryInfo::getEntryCount<MachineFunction>(
380 const MachineFunction *F) const;
381
382template <>
383bool ProfileSummaryInfo::hasHotAttr<MachineFunction>(
384 const MachineFunction *F) const;
385
386/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
388 std::unique_ptr<ProfileSummaryInfo> PSI;
389
390public:
391 static char ID;
393
394 ProfileSummaryInfo &getPSI() { return *PSI; }
395 const ProfileSummaryInfo &getPSI() const { return *PSI; }
396
397 bool doInitialization(Module &M) override;
398 bool doFinalization(Module &M) override;
399 void getAnalysisUsage(AnalysisUsage &AU) const override {
400 AU.setPreservesAll();
401 }
402};
403
404/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
406 : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
407public:
409
411
412private:
414 LLVM_ABI static AnalysisKey Key;
415};
416
417/// Printer pass that uses \c ProfileSummaryAnalysis.
419 : public RequiredPassInfoMixin<ProfileSummaryPrinterPass> {
420 raw_ostream &OS;
421
422public:
423 explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
425};
426
427} // end namespace llvm
428
429#endif
uint64_t uint64_t
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)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:211
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
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:285
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
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.
LLVM_ABI ProfileSummaryInfo(const Module &M)
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.
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
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.