Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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/PassManager.h" |
||
19 | #include "llvm/IR/ProfileSummary.h" |
||
20 | #include "llvm/Pass.h" |
||
21 | #include <memory> |
||
22 | #include <optional> |
||
23 | |||
24 | namespace llvm { |
||
25 | class BasicBlock; |
||
26 | class BlockFrequencyInfo; |
||
27 | class CallBase; |
||
28 | class Function; |
||
29 | |||
30 | /// Analysis providing profile information. |
||
31 | /// |
||
32 | /// This is an immutable analysis pass that provides ability to query global |
||
33 | /// (program-level) profile information. The main APIs are isHotCount and |
||
34 | /// isColdCount that tells whether a given profile count is considered hot/cold |
||
35 | /// based on the profile summary. This also provides convenience methods to |
||
36 | /// check whether a function is hot or cold. |
||
37 | |||
38 | // FIXME: Provide convenience methods to determine hotness/coldness of other IR |
||
39 | // units. This would require making this depend on BFI. |
||
40 | class ProfileSummaryInfo { |
||
41 | private: |
||
42 | const Module *M; |
||
43 | std::unique_ptr<ProfileSummary> Summary; |
||
44 | void computeThresholds(); |
||
45 | // Count thresholds to answer isHotCount and isColdCount queries. |
||
46 | std::optional<uint64_t> HotCountThreshold, ColdCountThreshold; |
||
47 | // True if the working set size of the code is considered huge, |
||
48 | // because the number of profile counts required to reach the hot |
||
49 | // percentile is above a huge threshold. |
||
50 | std::optional<bool> HasHugeWorkingSetSize; |
||
51 | // True if the working set size of the code is considered large, |
||
52 | // because the number of profile counts required to reach the hot |
||
53 | // percentile is above a large threshold. |
||
54 | std::optional<bool> HasLargeWorkingSetSize; |
||
55 | // Compute the threshold for a given cutoff. |
||
56 | std::optional<uint64_t> computeThreshold(int PercentileCutoff) const; |
||
57 | // The map that caches the threshold values. The keys are the percentile |
||
58 | // cutoff values and the values are the corresponding threshold values. |
||
59 | mutable DenseMap<int, uint64_t> ThresholdCache; |
||
60 | |||
61 | public: |
||
62 | ProfileSummaryInfo(const Module &M) : M(&M) { refresh(); } |
||
63 | ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default; |
||
64 | |||
65 | /// If no summary is present, attempt to refresh. |
||
66 | void refresh(); |
||
67 | |||
68 | /// Returns true if profile summary is available. |
||
69 | bool hasProfileSummary() const { return Summary != nullptr; } |
||
70 | |||
71 | /// Returns true if module \c M has sample profile. |
||
72 | bool hasSampleProfile() const { |
||
73 | return hasProfileSummary() && |
||
74 | Summary->getKind() == ProfileSummary::PSK_Sample; |
||
75 | } |
||
76 | |||
77 | /// Returns true if module \c M has instrumentation profile. |
||
78 | bool hasInstrumentationProfile() const { |
||
79 | return hasProfileSummary() && |
||
80 | Summary->getKind() == ProfileSummary::PSK_Instr; |
||
81 | } |
||
82 | |||
83 | /// Returns true if module \c M has context sensitive instrumentation profile. |
||
84 | bool hasCSInstrumentationProfile() const { |
||
85 | return hasProfileSummary() && |
||
86 | Summary->getKind() == ProfileSummary::PSK_CSInstr; |
||
87 | } |
||
88 | |||
89 | /// Handle the invalidation of this information. |
||
90 | /// |
||
91 | /// When used as a result of \c ProfileSummaryAnalysis this method will be |
||
92 | /// called when the module this was computed for changes. Since profile |
||
93 | /// summary is immutable after it is annotated on the module, we return false |
||
94 | /// here. |
||
95 | bool invalidate(Module &, const PreservedAnalyses &, |
||
96 | ModuleAnalysisManager::Invalidator &) { |
||
97 | return false; |
||
98 | } |
||
99 | |||
100 | /// Returns the profile count for \p CallInst. |
||
101 | std::optional<uint64_t> getProfileCount(const CallBase &CallInst, |
||
102 | BlockFrequencyInfo *BFI, |
||
103 | bool AllowSynthetic = false) const; |
||
104 | /// Returns true if module \c M has partial-profile sample profile. |
||
105 | bool hasPartialSampleProfile() const; |
||
106 | /// Returns true if the working set size of the code is considered huge. |
||
107 | bool hasHugeWorkingSetSize() const; |
||
108 | /// Returns true if the working set size of the code is considered large. |
||
109 | bool hasLargeWorkingSetSize() const; |
||
110 | /// Returns true if \p F has hot function entry. |
||
111 | bool isFunctionEntryHot(const Function *F) const; |
||
112 | /// Returns true if \p F contains hot code. |
||
113 | bool isFunctionHotInCallGraph(const Function *F, |
||
114 | BlockFrequencyInfo &BFI) const; |
||
115 | /// Returns true if \p F has cold function entry. |
||
116 | bool isFunctionEntryCold(const Function *F) const; |
||
117 | /// Returns true if \p F contains only cold code. |
||
118 | bool isFunctionColdInCallGraph(const Function *F, |
||
119 | BlockFrequencyInfo &BFI) const; |
||
120 | /// Returns true if the hotness of \p F is unknown. |
||
121 | bool isFunctionHotnessUnknown(const Function &F) const; |
||
122 | /// Returns true if \p F contains hot code with regard to a given hot |
||
123 | /// percentile cutoff value. |
||
124 | bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff, |
||
125 | const Function *F, |
||
126 | BlockFrequencyInfo &BFI) const; |
||
127 | /// Returns true if \p F contains cold code with regard to a given cold |
||
128 | /// percentile cutoff value. |
||
129 | bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff, |
||
130 | const Function *F, |
||
131 | BlockFrequencyInfo &BFI) const; |
||
132 | /// Returns true if count \p C is considered hot. |
||
133 | bool isHotCount(uint64_t C) const; |
||
134 | /// Returns true if count \p C is considered cold. |
||
135 | bool isColdCount(uint64_t C) const; |
||
136 | /// Returns true if count \p C is considered hot with regard to a given |
||
137 | /// hot percentile cutoff value. |
||
138 | /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where |
||
139 | /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. |
||
140 | bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const; |
||
141 | /// Returns true if count \p C is considered cold with regard to a given |
||
142 | /// cold percentile cutoff value. |
||
143 | /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where |
||
144 | /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. |
||
145 | bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const; |
||
146 | /// Returns true if BasicBlock \p BB is considered hot. |
||
147 | bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const; |
||
148 | /// Returns true if BasicBlock \p BB is considered cold. |
||
149 | bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const; |
||
150 | /// Returns true if BasicBlock \p BB is considered hot with regard to a given |
||
151 | /// hot percentile cutoff value. |
||
152 | /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where |
||
153 | /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. |
||
154 | bool isHotBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB, |
||
155 | BlockFrequencyInfo *BFI) const; |
||
156 | /// Returns true if BasicBlock \p BB is considered cold with regard to a given |
||
157 | /// cold percentile cutoff value. |
||
158 | /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where |
||
159 | /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile. |
||
160 | bool isColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB, |
||
161 | BlockFrequencyInfo *BFI) const; |
||
162 | /// Returns true if the call site \p CB is considered hot. |
||
163 | bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const; |
||
164 | /// Returns true if call site \p CB is considered cold. |
||
165 | bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const; |
||
166 | /// Returns HotCountThreshold if set. Recompute HotCountThreshold |
||
167 | /// if not set. |
||
168 | uint64_t getOrCompHotCountThreshold() const; |
||
169 | /// Returns ColdCountThreshold if set. Recompute HotCountThreshold |
||
170 | /// if not set. |
||
171 | uint64_t getOrCompColdCountThreshold() const; |
||
172 | /// Returns HotCountThreshold if set. |
||
173 | uint64_t getHotCountThreshold() const { |
||
174 | return HotCountThreshold.value_or(0); |
||
175 | } |
||
176 | /// Returns ColdCountThreshold if set. |
||
177 | uint64_t getColdCountThreshold() const { |
||
178 | return ColdCountThreshold.value_or(0); |
||
179 | } |
||
180 | |||
181 | private: |
||
182 | template <bool isHot> |
||
183 | bool isFunctionHotOrColdInCallGraphNthPercentile( |
||
184 | int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const; |
||
185 | template <bool isHot> |
||
186 | bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const; |
||
187 | template <bool isHot> |
||
188 | bool isHotOrColdBlockNthPercentile(int PercentileCutoff, |
||
189 | const BasicBlock *BB, |
||
190 | BlockFrequencyInfo *BFI) const; |
||
191 | }; |
||
192 | |||
193 | /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo. |
||
194 | class ProfileSummaryInfoWrapperPass : public ImmutablePass { |
||
195 | std::unique_ptr<ProfileSummaryInfo> PSI; |
||
196 | |||
197 | public: |
||
198 | static char ID; |
||
199 | ProfileSummaryInfoWrapperPass(); |
||
200 | |||
201 | ProfileSummaryInfo &getPSI() { return *PSI; } |
||
202 | const ProfileSummaryInfo &getPSI() const { return *PSI; } |
||
203 | |||
204 | bool doInitialization(Module &M) override; |
||
205 | bool doFinalization(Module &M) override; |
||
206 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
||
207 | AU.setPreservesAll(); |
||
208 | } |
||
209 | }; |
||
210 | |||
211 | /// An analysis pass based on the new PM to deliver ProfileSummaryInfo. |
||
212 | class ProfileSummaryAnalysis |
||
213 | : public AnalysisInfoMixin<ProfileSummaryAnalysis> { |
||
214 | public: |
||
215 | typedef ProfileSummaryInfo Result; |
||
216 | |||
217 | Result run(Module &M, ModuleAnalysisManager &); |
||
218 | |||
219 | private: |
||
220 | friend AnalysisInfoMixin<ProfileSummaryAnalysis>; |
||
221 | static AnalysisKey Key; |
||
222 | }; |
||
223 | |||
224 | /// Printer pass that uses \c ProfileSummaryAnalysis. |
||
225 | class ProfileSummaryPrinterPass |
||
226 | : public PassInfoMixin<ProfileSummaryPrinterPass> { |
||
227 | raw_ostream &OS; |
||
228 | |||
229 | public: |
||
230 | explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {} |
||
231 | PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); |
||
232 | }; |
||
233 | |||
234 | } // end namespace llvm |
||
235 | |||
236 | #endif |