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 {
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)
117 return false;
118 // The hot attribute is a manual alternative to profile data, and takes
119 // precedence over it. Check it before the profile summary so that it is
120 // also honored when no profile is available.
121 if (hasHotAttr(F))
122 return true;
123 if (!hasProfileSummary())
124 return false;
125 std::optional<uint64_t> FunctionCount = getEntryCount(F);
126 // FIXME: The heuristic used below for determining hotness is based on
127 // preliminary SPEC tuning for inliner. This will eventually be a
128 // convenience method that calls isHotCount.
129 return FunctionCount && isHotCount(*FunctionCount);
130 }
131
132 /// Returns true if \p F contains hot code.
133 template <typename FuncT, typename BFIT>
134 bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const {
135 if (!F)
136 return false;
137 // The hot attribute is a manual alternative to profile data, and takes
138 // precedence over it. Check it before the profile summary so that it is
139 // also honored when no profile is available.
140 if (hasHotAttr(F))
141 return true;
142 if (!hasProfileSummary())
143 return false;
144 if (auto FunctionCount = getEntryCount(F))
145 if (isHotCount(*FunctionCount))
146 return true;
147
148 if (auto TotalCallCount = getTotalCallCount(F))
149 if (isHotCount(*TotalCallCount))
150 return true;
151
152 for (const auto &BB : *F)
153 if (isHotBlock(&BB, &BFI))
154 return true;
155 return false;
156 }
157 /// Returns true if \p F has cold function entry.
158 LLVM_ABI bool isFunctionEntryCold(const Function *F) const;
159 /// Returns true if \p F contains only cold code.
160 template <typename FuncT, typename BFIT>
161 bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const {
162 if (!F)
163 return false;
164 // The hot attribute is a manual alternative to profile data, and takes
165 // precedence over it. Check it before the profile summary so that it is
166 // also honored when no profile is available.
167 if (hasHotAttr(F))
168 return false;
169 if (!hasProfileSummary())
170 return false;
171 if (auto FunctionCount = getEntryCount(F))
172 if (!isColdCount(*FunctionCount))
173 return false;
174
175 if (auto TotalCallCount = getTotalCallCount(F))
176 if (!isColdCount(*TotalCallCount))
177 return false;
178
179 for (const auto &BB : *F)
180 if (!isColdBlock(&BB, &BFI))
181 return false;
182 return true;
183 }
184 /// Returns true if the hotness of \p F is unknown.
185 LLVM_ABI bool isFunctionHotnessUnknown(const Function &F) const;
186 /// Returns true if \p F contains hot code with regard to a given hot
187 /// percentile cutoff value.
188 template <typename FuncT, typename BFIT>
190 const FuncT *F, BFIT &BFI) const {
191 return isFunctionHotOrColdInCallGraphNthPercentile<true, FuncT, BFIT>(
192 PercentileCutoff, F, BFI);
193 }
194 /// Returns true if \p F contains cold code with regard to a given cold
195 /// percentile cutoff value.
196 template <typename FuncT, typename BFIT>
198 const FuncT *F, BFIT &BFI) const {
199 return isFunctionHotOrColdInCallGraphNthPercentile<false, FuncT, BFIT>(
200 PercentileCutoff, F, BFI);
201 }
202 /// Returns true if count \p C is considered hot.
203 LLVM_ABI bool isHotCount(uint64_t C) const;
204 /// Returns true if count \p C is considered cold.
205 LLVM_ABI bool isColdCount(uint64_t C) const;
206 /// Returns true if count \p C is considered hot with regard to a given
207 /// hot percentile cutoff value.
208 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
209 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
211 /// Returns true if count \p C is considered cold with regard to a given
212 /// cold percentile cutoff value.
213 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
214 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
216 uint64_t C) const;
217
218 /// Returns true if BasicBlock \p BB is considered hot.
219 template <typename BBType, typename BFIT>
220 bool isHotBlock(const BBType *BB, BFIT *BFI) const {
221 auto Count = BFI->getBlockProfileCount(BB);
222 return Count && isHotCount(*Count);
223 }
224
225 /// Returns true if BasicBlock \p BB is considered cold.
226 template <typename BBType, typename BFIT>
227 bool isColdBlock(const BBType *BB, BFIT *BFI) const {
228 auto Count = BFI->getBlockProfileCount(BB);
229 return Count && isColdCount(*Count);
230 }
231
232 template <typename BFIT>
233 bool isColdBlock(BlockFrequency BlockFreq, const BFIT *BFI) const {
234 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
235 return Count && isColdCount(*Count);
236 }
237
238 template <typename BBType, typename BFIT>
239 bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB,
240 BFIT *BFI) const {
241 return isHotOrColdBlockNthPercentile<true, BBType, BFIT>(PercentileCutoff,
242 BB, BFI);
243 }
244
245 template <typename BFIT>
247 BFIT *BFI) const {
248 return isHotOrColdBlockNthPercentile<true, BFIT>(PercentileCutoff,
249 BlockFreq, BFI);
250 }
251
252 /// Returns true if BasicBlock \p BB is considered cold with regard to a given
253 /// cold percentile cutoff value.
254 /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
255 /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
256 template <typename BBType, typename BFIT>
257 bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
258 BFIT *BFI) const {
259 return isHotOrColdBlockNthPercentile<false, BBType, BFIT>(PercentileCutoff,
260 BB, BFI);
261 }
262 template <typename BFIT>
264 BFIT *BFI) const {
265 return isHotOrColdBlockNthPercentile<false, BFIT>(PercentileCutoff,
266 BlockFreq, BFI);
267 }
268 /// Returns true if the call site \p CB is considered hot.
269 LLVM_ABI bool isHotCallSite(const CallBase &CB,
270 BlockFrequencyInfo *BFI) const;
271 /// Returns true if call site \p CB is considered cold.
272 LLVM_ABI bool isColdCallSite(const CallBase &CB,
273 BlockFrequencyInfo *BFI) const;
274 /// Returns HotCountThreshold if set. Recompute HotCountThreshold
275 /// if not set.
277 /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
278 /// if not set.
280 /// Returns HotCountThreshold if set.
282 return HotCountThreshold.value_or(0);
283 }
284 /// Returns ColdCountThreshold if set.
286 return ColdCountThreshold.value_or(0);
287 }
288
289private:
290 template <typename FuncT>
291 std::optional<uint64_t> getTotalCallCount(const FuncT *F) const {
292 return std::nullopt;
293 }
294
295 template <bool isHot, typename FuncT, typename BFIT>
296 bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff,
297 const FuncT *F,
298 BFIT &FI) const {
299 if (!F || !hasProfileSummary())
300 return false;
301 if (auto FunctionCount = getEntryCount(F)) {
302 if (isHot && isHotCountNthPercentile(PercentileCutoff, *FunctionCount))
303 return true;
304 if (!isHot && !isColdCountNthPercentile(PercentileCutoff, *FunctionCount))
305 return false;
306 }
307 if (auto TotalCallCount = getTotalCallCount(F)) {
308 if (isHot && isHotCountNthPercentile(PercentileCutoff, *TotalCallCount))
309 return true;
310 if (!isHot &&
312 return false;
313 }
314 for (const auto &BB : *F) {
315 if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &FI))
316 return true;
317 if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &FI))
318 return false;
319 }
320 return !isHot;
321 }
322
323 template <bool isHot>
324 bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
325
326 template <bool isHot, typename BBType, typename BFIT>
327 bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
328 BFIT *BFI) const {
329 auto Count = BFI->getBlockProfileCount(BB);
330 if constexpr (isHot)
332 else
334 }
335
336 template <bool isHot, typename BFIT>
337 bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
338 BlockFrequency BlockFreq,
339 BFIT *BFI) const {
340 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
341 if constexpr (isHot)
343 else
345 }
346
347 template <typename FuncT>
348 std::optional<uint64_t> getEntryCount(const FuncT *F) const {
349 return F->getEntryCount();
350 }
351
352 /// Returns true if \p F is annotated with the hot attribute, which takes
353 /// precedence over any profile information.
354 template <typename FuncT> bool hasHotAttr(const FuncT *F) const {
355 return F->hasFnAttribute(Attribute::Hot);
356 }
357};
358
359template <>
360inline std::optional<uint64_t>
361ProfileSummaryInfo::getTotalCallCount<Function>(const Function *F) const {
362 if (!hasSampleProfile())
363 return std::nullopt;
364 uint64_t TotalCallCount = 0;
365 for (const auto &BB : *F)
366 for (const auto &I : BB)
368 if (auto CallCount = getProfileCount(cast<CallBase>(I), nullptr))
369 TotalCallCount += *CallCount;
370 return TotalCallCount;
371}
372
373// Declare template specializations for llvm::MachineFunction. Do not implement
374// here, because we cannot include MachineFunction header here, that would break
375// dependency rules.
376template <>
377std::optional<uint64_t> ProfileSummaryInfo::getEntryCount<MachineFunction>(
378 const MachineFunction *F) const;
379
380template <>
381bool ProfileSummaryInfo::hasHotAttr<MachineFunction>(
382 const MachineFunction *F) const;
383
384/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
386 std::unique_ptr<ProfileSummaryInfo> PSI;
387
388public:
389 static char ID;
391
392 ProfileSummaryInfo &getPSI() { return *PSI; }
393 const ProfileSummaryInfo &getPSI() const { return *PSI; }
394
395 bool doInitialization(Module &M) override;
396 bool doFinalization(Module &M) override;
397 void getAnalysisUsage(AnalysisUsage &AU) const override {
398 AU.setPreservesAll();
399 }
400};
401
402/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
404 : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
405public:
407
409
410private:
412 LLVM_ABI static AnalysisKey Key;
413};
414
415/// Printer pass that uses \c ProfileSummaryAnalysis.
417 : public RequiredPassInfoMixin<ProfileSummaryPrinterPass> {
418 raw_ostream &OS;
419
420public:
421 explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
423};
424
425} // end namespace llvm
426
427#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: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
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.
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
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.