1 //===- ProfileSummaryInfo.cpp - Global profile summary information --------===//
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 the global profile summary
10 // information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Analysis/ProfileSummaryInfo.h"
15 #include "llvm/Analysis/BlockFrequencyInfo.h"
16 #include "llvm/IR/BasicBlock.h"
17 #include "llvm/IR/CallSite.h"
18 #include "llvm/IR/Metadata.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/ProfileSummary.h"
21 using namespace llvm;
22 
23 // The following two parameters determine the threshold for a count to be
24 // considered hot/cold. These two parameters are percentile values (multiplied
25 // by 10000). If the counts are sorted in descending order, the minimum count to
26 // reach ProfileSummaryCutoffHot gives the threshold to determine a hot count.
27 // Similarly, the minimum count to reach ProfileSummaryCutoffCold gives the
28 // threshold for determining cold count (everything <= this threshold is
29 // considered cold).
30 
31 static cl::opt<int> ProfileSummaryCutoffHot(
32     "profile-summary-cutoff-hot", cl::Hidden, cl::init(990000), cl::ZeroOrMore,
33     cl::desc("A count is hot if it exceeds the minimum count to"
34              " reach this percentile of total counts."));
35 
36 static cl::opt<int> ProfileSummaryCutoffCold(
37     "profile-summary-cutoff-cold", cl::Hidden, cl::init(999999), cl::ZeroOrMore,
38     cl::desc("A count is cold if it is below the minimum count"
39              " to reach this percentile of total counts."));
40 
41 static cl::opt<unsigned> ProfileSummaryHugeWorkingSetSizeThreshold(
42     "profile-summary-huge-working-set-size-threshold", cl::Hidden,
43     cl::init(15000), cl::ZeroOrMore,
44     cl::desc("The code working set size is considered huge if the number of"
45              " blocks required to reach the -profile-summary-cutoff-hot"
46              " percentile exceeds this count."));
47 
48 // The next two options override the counts derived from summary computation and
49 // are useful for debugging purposes.
50 static cl::opt<int> ProfileSummaryHotCount(
51     "profile-summary-hot-count", cl::ReallyHidden, cl::ZeroOrMore,
52     cl::desc("A fixed hot count that overrides the count derived from"
53              " profile-summary-cutoff-hot"));
54 
55 static cl::opt<int> ProfileSummaryColdCount(
56     "profile-summary-cold-count", cl::ReallyHidden, cl::ZeroOrMore,
57     cl::desc("A fixed cold count that overrides the count derived from"
58              " profile-summary-cutoff-cold"));
59 
60 // Find the summary entry for a desired percentile of counts.
61 static const ProfileSummaryEntry &getEntryForPercentile(SummaryEntryVector &DS,
62                                                         uint64_t Percentile) {
63   auto Compare = [](const ProfileSummaryEntry &Entry, uint64_t Percentile) {
64     return Entry.Cutoff < Percentile;
65   };
66   auto It = std::lower_bound(DS.begin(), DS.end(), Percentile, Compare);
67   // The required percentile has to be <= one of the percentiles in the
68   // detailed summary.
69   if (It == DS.end())
70     report_fatal_error("Desired percentile exceeds the maximum cutoff");
71   return *It;
72 }
73 
74 // The profile summary metadata may be attached either by the frontend or by
75 // any backend passes (IR level instrumentation, for example). This method
76 // checks if the Summary is null and if so checks if the summary metadata is now
77 // available in the module and parses it to get the Summary object. Returns true
78 // if a valid Summary is available.
79 bool ProfileSummaryInfo::computeSummary() {
80   if (Summary)
81     return true;
82   // First try to get context sensitive ProfileSummary.
83   auto *SummaryMD = M.getProfileSummary(/* IsCS */ true);
84   if (SummaryMD) {
85     Summary.reset(ProfileSummary::getFromMD(SummaryMD));
86     return true;
87   }
88   // This will actually return PSK_Instr or PSK_Sample summary.
89   SummaryMD = M.getProfileSummary(/* IsCS */ false);
90   if (!SummaryMD)
91     return false;
92   Summary.reset(ProfileSummary::getFromMD(SummaryMD));
93   return true;
94 }
95 
96 Optional<uint64_t>
97 ProfileSummaryInfo::getProfileCount(const Instruction *Inst,
98                                     BlockFrequencyInfo *BFI,
99                                     bool AllowSynthetic) {
100   if (!Inst)
101     return None;
102   assert((isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) &&
103          "We can only get profile count for call/invoke instruction.");
104   if (hasSampleProfile()) {
105     // In sample PGO mode, check if there is a profile metadata on the
106     // instruction. If it is present, determine hotness solely based on that,
107     // since the sampled entry count may not be accurate. If there is no
108     // annotated on the instruction, return None.
109     uint64_t TotalCount;
110     if (Inst->extractProfTotalWeight(TotalCount))
111       return TotalCount;
112     return None;
113   }
114   if (BFI)
115     return BFI->getBlockProfileCount(Inst->getParent(), AllowSynthetic);
116   return None;
117 }
118 
119 /// Returns true if the function's entry is hot. If it returns false, it
120 /// either means it is not hot or it is unknown whether it is hot or not (for
121 /// example, no profile data is available).
122 bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) {
123   if (!F || !computeSummary())
124     return false;
125   auto FunctionCount = F->getEntryCount();
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.getCount());
130 }
131 
132 /// Returns true if the function contains hot code. This can include a hot
133 /// function entry count, hot basic block, or (in the case of Sample PGO)
134 /// hot total call edge count.
135 /// If it returns false, it either means it is not hot or it is unknown
136 /// (for example, no profile data is available).
137 bool ProfileSummaryInfo::isFunctionHotInCallGraph(const Function *F,
138                                                   BlockFrequencyInfo &BFI) {
139   if (!F || !computeSummary())
140     return false;
141   if (auto FunctionCount = F->getEntryCount())
142     if (isHotCount(FunctionCount.getCount()))
143       return true;
144 
145   if (hasSampleProfile()) {
146     uint64_t TotalCallCount = 0;
147     for (const auto &BB : *F)
148       for (const auto &I : BB)
149         if (isa<CallInst>(I) || isa<InvokeInst>(I))
150           if (auto CallCount = getProfileCount(&I, nullptr))
151             TotalCallCount += CallCount.getValue();
152     if (isHotCount(TotalCallCount))
153       return true;
154   }
155   for (const auto &BB : *F)
156     if (isHotBlock(&BB, &BFI))
157       return true;
158   return false;
159 }
160 
161 /// Returns true if the function only contains cold code. This means that
162 /// the function entry and blocks are all cold, and (in the case of Sample PGO)
163 /// the total call edge count is cold.
164 /// If it returns false, it either means it is not cold or it is unknown
165 /// (for example, no profile data is available).
166 bool ProfileSummaryInfo::isFunctionColdInCallGraph(const Function *F,
167                                                    BlockFrequencyInfo &BFI) {
168   if (!F || !computeSummary())
169     return false;
170   if (auto FunctionCount = F->getEntryCount())
171     if (!isColdCount(FunctionCount.getCount()))
172       return false;
173 
174   if (hasSampleProfile()) {
175     uint64_t TotalCallCount = 0;
176     for (const auto &BB : *F)
177       for (const auto &I : BB)
178         if (isa<CallInst>(I) || isa<InvokeInst>(I))
179           if (auto CallCount = getProfileCount(&I, nullptr))
180             TotalCallCount += CallCount.getValue();
181     if (!isColdCount(TotalCallCount))
182       return false;
183   }
184   for (const auto &BB : *F)
185     if (!isColdBlock(&BB, &BFI))
186       return false;
187   return true;
188 }
189 
190 /// Returns true if the function's entry is a cold. If it returns false, it
191 /// either means it is not cold or it is unknown whether it is cold or not (for
192 /// example, no profile data is available).
193 bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) {
194   if (!F)
195     return false;
196   if (F->hasFnAttribute(Attribute::Cold))
197     return true;
198   if (!computeSummary())
199     return false;
200   auto FunctionCount = F->getEntryCount();
201   // FIXME: The heuristic used below for determining coldness is based on
202   // preliminary SPEC tuning for inliner. This will eventually be a
203   // convenience method that calls isHotCount.
204   return FunctionCount && isColdCount(FunctionCount.getCount());
205 }
206 
207 /// Compute the hot and cold thresholds.
208 void ProfileSummaryInfo::computeThresholds() {
209   if (!computeSummary())
210     return;
211   auto &DetailedSummary = Summary->getDetailedSummary();
212   auto &HotEntry =
213       getEntryForPercentile(DetailedSummary, ProfileSummaryCutoffHot);
214   HotCountThreshold = HotEntry.MinCount;
215   if (ProfileSummaryHotCount.getNumOccurrences() > 0)
216     HotCountThreshold = ProfileSummaryHotCount;
217   auto &ColdEntry =
218       getEntryForPercentile(DetailedSummary, ProfileSummaryCutoffCold);
219   ColdCountThreshold = ColdEntry.MinCount;
220   if (ProfileSummaryColdCount.getNumOccurrences() > 0)
221     ColdCountThreshold = ProfileSummaryColdCount;
222   assert(ColdCountThreshold <= HotCountThreshold &&
223          "Cold count threshold cannot exceed hot count threshold!");
224   HasHugeWorkingSetSize =
225       HotEntry.NumCounts > ProfileSummaryHugeWorkingSetSizeThreshold;
226 }
227 
228 bool ProfileSummaryInfo::hasHugeWorkingSetSize() {
229   if (!HasHugeWorkingSetSize)
230     computeThresholds();
231   return HasHugeWorkingSetSize && HasHugeWorkingSetSize.getValue();
232 }
233 
234 bool ProfileSummaryInfo::isHotCount(uint64_t C) {
235   if (!HotCountThreshold)
236     computeThresholds();
237   return HotCountThreshold && C >= HotCountThreshold.getValue();
238 }
239 
240 bool ProfileSummaryInfo::isColdCount(uint64_t C) {
241   if (!ColdCountThreshold)
242     computeThresholds();
243   return ColdCountThreshold && C <= ColdCountThreshold.getValue();
244 }
245 
246 uint64_t ProfileSummaryInfo::getOrCompHotCountThreshold() {
247   if (!HotCountThreshold)
248     computeThresholds();
249   return HotCountThreshold ? HotCountThreshold.getValue() : UINT64_MAX;
250 }
251 
252 uint64_t ProfileSummaryInfo::getOrCompColdCountThreshold() {
253   if (!ColdCountThreshold)
254     computeThresholds();
255   return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
256 }
257 
258 bool ProfileSummaryInfo::isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) {
259   auto Count = BFI->getBlockProfileCount(BB);
260   return Count && isHotCount(*Count);
261 }
262 
263 bool ProfileSummaryInfo::isColdBlock(const BasicBlock *BB,
264                                   BlockFrequencyInfo *BFI) {
265   auto Count = BFI->getBlockProfileCount(BB);
266   return Count && isColdCount(*Count);
267 }
268 
269 bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS,
270                                        BlockFrequencyInfo *BFI) {
271   auto C = getProfileCount(CS.getInstruction(), BFI);
272   return C && isHotCount(*C);
273 }
274 
275 bool ProfileSummaryInfo::isColdCallSite(const CallSite &CS,
276                                         BlockFrequencyInfo *BFI) {
277   auto C = getProfileCount(CS.getInstruction(), BFI);
278   if (C)
279     return isColdCount(*C);
280 
281   // In SamplePGO, if the caller has been sampled, and there is no profile
282   // annotated on the callsite, we consider the callsite as cold.
283   return hasSampleProfile() && CS.getCaller()->hasProfileData();
284 }
285 
286 INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info",
287                 "Profile summary info", false, true)
288 
289 ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass()
290     : ImmutablePass(ID) {
291   initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
292 }
293 
294 bool ProfileSummaryInfoWrapperPass::doInitialization(Module &M) {
295   PSI.reset(new ProfileSummaryInfo(M));
296   return false;
297 }
298 
299 bool ProfileSummaryInfoWrapperPass::doFinalization(Module &M) {
300   PSI.reset();
301   return false;
302 }
303 
304 AnalysisKey ProfileSummaryAnalysis::Key;
305 ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M,
306                                                ModuleAnalysisManager &) {
307   return ProfileSummaryInfo(M);
308 }
309 
310 PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M,
311                                                  ModuleAnalysisManager &AM) {
312   ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
313 
314   OS << "Functions in " << M.getName() << " with hot/cold annotations: \n";
315   for (auto &F : M) {
316     OS << F.getName();
317     if (PSI.isFunctionEntryHot(&F))
318       OS << " :hot entry ";
319     else if (PSI.isFunctionEntryCold(&F))
320       OS << " :cold entry ";
321     OS << "\n";
322   }
323   return PreservedAnalyses::all();
324 }
325 
326 char ProfileSummaryInfoWrapperPass::ID = 0;
327