15
15
#define LLVM_ANALYSIS_PROFILESUMMARYINFO_H
16
16
17
17
#include " llvm/ADT/DenseMap.h"
18
+ #include " llvm/Analysis/BlockFrequencyInfo.h"
19
+ #include " llvm/CodeGen/MachineFunction.h"
20
+ #include " llvm/IR/Function.h"
21
+ #include " llvm/IR/Instructions.h"
18
22
#include " llvm/IR/PassManager.h"
19
23
#include " llvm/IR/ProfileSummary.h"
20
24
#include " llvm/Pass.h"
23
27
24
28
namespace llvm {
25
29
class BasicBlock ;
26
- class BlockFrequencyInfo ;
27
30
class CallBase ;
28
- class Function ;
29
31
30
32
// / Analysis providing profile information.
31
33
// /
@@ -107,28 +109,77 @@ class ProfileSummaryInfo {
107
109
bool hasHugeWorkingSetSize () const ;
108
110
// / Returns true if the working set size of the code is considered large.
109
111
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 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<Function::ProfileCount> 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->getCount ());
123
+ }
124
+
112
125
// / Returns true if \p F contains hot code.
113
- bool isFunctionHotInCallGraph (const Function *F,
114
- BlockFrequencyInfo &BFI) const ;
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->getCount ()))
132
+ return true ;
133
+
134
+ if (auto TotalCallCount = getTotalCallCount (F)) {
135
+ if (isHotCount (*TotalCallCount))
136
+ return true ;
137
+ }
138
+
139
+ for (const auto &BB : *F)
140
+ if (isHotBlock (&BB, &BFI))
141
+ return true ;
142
+ return false ;
143
+ }
115
144
// / Returns true if \p F has cold function entry.
116
145
bool isFunctionEntryCold (const Function *F) const ;
117
146
// / Returns true if \p F contains only cold code.
118
- bool isFunctionColdInCallGraph (const Function *F,
119
- BlockFrequencyInfo &BFI) const ;
147
+ template <typename FuncT, typename BFIT>
148
+ bool isFunctionColdInCallGraph (const FuncT *F, BFIT &BFI) const {
149
+ if (!F || !hasProfileSummary ())
150
+ return false ;
151
+ if (auto FunctionCount = getEntryCount (F))
152
+ if (!isColdCount (FunctionCount->getCount ()))
153
+ return false ;
154
+
155
+ if (auto TotalCallCount = getTotalCallCount (F)) {
156
+ if (!isColdCount (*TotalCallCount))
157
+ return false ;
158
+ }
159
+
160
+ for (const auto &BB : *F)
161
+ if (!isColdBlock (&BB, &BFI))
162
+ return false ;
163
+ return true ;
164
+ }
120
165
// / Returns true if the hotness of \p F is unknown.
121
166
bool isFunctionHotnessUnknown (const Function &F) const ;
122
167
// / Returns true if \p F contains hot code with regard to a given hot
123
168
// / percentile cutoff value.
169
+ template <typename FuncT, typename BFIT>
124
170
bool isFunctionHotInCallGraphNthPercentile (int PercentileCutoff,
125
- const Function *F,
126
- BlockFrequencyInfo &BFI) const ;
171
+ const FuncT *F, BFIT &BFI) const {
172
+ return isFunctionHotOrColdInCallGraphNthPercentile<true , FuncT, BFIT>(
173
+ PercentileCutoff, F, BFI);
174
+ }
127
175
// / Returns true if \p F contains cold code with regard to a given cold
128
176
// / percentile cutoff value.
177
+ template <typename FuncT, typename BFIT>
129
178
bool isFunctionColdInCallGraphNthPercentile (int PercentileCutoff,
130
- const Function *F,
131
- BlockFrequencyInfo &BFI) const ;
179
+ const FuncT *F, BFIT &BFI) const {
180
+ return isFunctionHotOrColdInCallGraphNthPercentile<false , FuncT, BFIT>(
181
+ PercentileCutoff, F, BFI);
182
+ }
132
183
// / Returns true if count \p C is considered hot.
133
184
bool isHotCount (uint64_t C) const ;
134
185
// / Returns true if count \p C is considered cold.
@@ -143,22 +194,57 @@ class ProfileSummaryInfo {
143
194
// / PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
144
195
// / the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
145
196
bool isColdCountNthPercentile (int PercentileCutoff, uint64_t C) const ;
197
+
146
198
// / Returns true if BasicBlock \p BB is considered hot.
147
- bool isHotBlock (const BasicBlock *BB, BlockFrequencyInfo *BFI) const ;
199
+ template <typename BBType, typename BFIT>
200
+ bool isHotBlock (const BBType *BB, BFIT *BFI) const {
201
+ auto Count = BFI->getBlockProfileCount (BB);
202
+ return Count && isHotCount (*Count);
203
+ }
204
+
148
205
// / 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 ;
206
+ template <typename BBType, typename BFIT>
207
+ bool isColdBlock (const BBType *BB, BFIT *BFI) const {
208
+ auto Count = BFI->getBlockProfileCount (BB);
209
+ return Count && isColdCount (*Count);
210
+ }
211
+
212
+ template <typename BFIT>
213
+ bool isColdBlock (BlockFrequency BlockFreq, const BFIT *BFI) const {
214
+ auto Count = BFI->getProfileCountFromFreq (BlockFreq.getFrequency ());
215
+ return Count && isColdCount (*Count);
216
+ }
217
+
218
+ template <typename BBType, typename BFIT>
219
+ bool isHotBlockNthPercentile (int PercentileCutoff, const BBType *BB,
220
+ BFIT *BFI) const {
221
+ return isHotOrColdBlockNthPercentile<true , BBType, BFIT>(PercentileCutoff,
222
+ BB, BFI);
223
+ }
224
+
225
+ template <typename BFIT>
226
+ bool isHotBlockNthPercentile (int PercentileCutoff, BlockFrequency BlockFreq,
227
+ BFIT *BFI) const {
228
+ return isHotOrColdBlockNthPercentile<true , BFIT>(PercentileCutoff,
229
+ BlockFreq, BFI);
230
+ }
231
+
156
232
// / Returns true if BasicBlock \p BB is considered cold with regard to a given
157
233
// / cold percentile cutoff value.
158
234
// / PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
159
235
// / 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 ;
236
+ template <typename BBType, typename BFIT>
237
+ bool isColdBlockNthPercentile (int PercentileCutoff, const BBType *BB,
238
+ BFIT *BFI) const {
239
+ return isHotOrColdBlockNthPercentile<false , BBType, BFIT>(PercentileCutoff,
240
+ BB, BFI);
241
+ }
242
+ template <typename BFIT>
243
+ bool isColdBlockNthPercentile (int PercentileCutoff, BlockFrequency BlockFreq,
244
+ BFIT *BFI) const {
245
+ return isHotOrColdBlockNthPercentile<false , BFIT>(PercentileCutoff,
246
+ BlockFreq, BFI);
247
+ }
162
248
// / Returns true if the call site \p CB is considered hot.
163
249
bool isHotCallSite (const CallBase &CB, BlockFrequencyInfo *BFI) const ;
164
250
// / Returns true if call site \p CB is considered cold.
@@ -178,18 +264,97 @@ class ProfileSummaryInfo {
178
264
return ColdCountThreshold.value_or (0 );
179
265
}
180
266
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 ;
267
+ private:
268
+ template <typename FuncT>
269
+ std::optional<uint64_t > getTotalCallCount (const FuncT *F) const {
270
+ return std::nullopt;
271
+ }
272
+
273
+ template <bool isHot, typename FuncT, typename BFIT>
274
+ bool isFunctionHotOrColdInCallGraphNthPercentile (int PercentileCutoff,
275
+ const FuncT *F,
276
+ BFIT &FI) const {
277
+ if (!F || !hasProfileSummary ())
278
+ return false ;
279
+ if (auto FunctionCount = getEntryCount (F)) {
280
+ if (isHot &&
281
+ isHotCountNthPercentile (PercentileCutoff, FunctionCount->getCount ()))
282
+ return true ;
283
+ if (!isHot && !isColdCountNthPercentile (PercentileCutoff,
284
+ FunctionCount->getCount ()))
285
+ return false ;
286
+ }
287
+ if (auto TotalCallCount = getTotalCallCount (F)) {
288
+ if (isHot && isHotCountNthPercentile (PercentileCutoff, *TotalCallCount))
289
+ return true ;
290
+ if (!isHot &&
291
+ !isColdCountNthPercentile (PercentileCutoff, *TotalCallCount))
292
+ return false ;
293
+ }
294
+ for (const auto &BB : *F) {
295
+ if (isHot && isHotBlockNthPercentile (PercentileCutoff, &BB, &FI))
296
+ return true ;
297
+ if (!isHot && !isColdBlockNthPercentile (PercentileCutoff, &BB, &FI))
298
+ return false ;
299
+ }
300
+ return !isHot;
301
+ }
302
+
303
+ template <bool isHot>
304
+ bool isHotOrColdCountNthPercentile (int PercentileCutoff, uint64_t C) const ;
305
+
306
+ template <bool isHot, typename BBType, typename BFIT>
307
+ bool isHotOrColdBlockNthPercentile (int PercentileCutoff, const BBType *BB,
308
+ BFIT *BFI) const {
309
+ auto Count = BFI->getBlockProfileCount (BB);
310
+ if (isHot)
311
+ return Count && isHotCountNthPercentile (PercentileCutoff, *Count);
312
+ else
313
+ return Count && isColdCountNthPercentile (PercentileCutoff, *Count);
314
+ }
315
+
316
+ template <bool isHot, typename BFIT>
317
+ bool isHotOrColdBlockNthPercentile (int PercentileCutoff,
318
+ BlockFrequency BlockFreq,
319
+ BFIT *BFI) const {
320
+ auto Count = BFI->getProfileCountFromFreq (BlockFreq.getFrequency ());
321
+ if (isHot)
322
+ return Count && isHotCountNthPercentile (PercentileCutoff, *Count);
323
+ else
324
+ return Count && isColdCountNthPercentile (PercentileCutoff, *Count);
325
+ }
326
+
327
+ template <typename FuncT>
328
+ std::optional<Function::ProfileCount> getEntryCount (const FuncT *F) const {
329
+ return F->getEntryCount ();
330
+ }
191
331
};
192
332
333
+ template <>
334
+ inline std::optional<uint64_t >
335
+ ProfileSummaryInfo::getTotalCallCount<Function>(const Function *F) const {
336
+ if (!hasSampleProfile ())
337
+ return std::nullopt;
338
+ uint64_t TotalCallCount = 0 ;
339
+ for (const auto &BB : *F) {
340
+ for (const auto &I : BB) {
341
+ if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
342
+ if (auto CallCount = getProfileCount (cast<CallBase>(I), nullptr )) {
343
+ TotalCallCount += *CallCount;
344
+ }
345
+ }
346
+ }
347
+ }
348
+ return TotalCallCount;
349
+ }
350
+
351
+ template <>
352
+ inline std::optional<Function::ProfileCount>
353
+ ProfileSummaryInfo::getEntryCount<MachineFunction>(
354
+ const MachineFunction *F) const {
355
+ return F->getFunction ().getEntryCount ();
356
+ }
357
+
193
358
// / An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
194
359
class ProfileSummaryInfoWrapperPass : public ImmutablePass {
195
360
std::unique_ptr<ProfileSummaryInfo> PSI;
0 commit comments