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_PROFILE_SUMMARY_INFO_H
15 #define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/SmallSet.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/PassManager.h"
23 #include "llvm/IR/ProfileSummary.h"
24 #include "llvm/IR/ValueHandle.h"
25 #include "llvm/Pass.h"
26 #include <memory>
27 
28 namespace llvm {
29 class BasicBlock;
30 class BlockFrequencyInfo;
31 class CallSite;
32 class ProfileSummary;
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.
43 class ProfileSummaryInfo {
44 private:
45   Module &M;
46   std::unique_ptr<ProfileSummary> Summary;
47   bool computeSummary();
48   void computeThresholds();
49   // Count thresholds to answer isHotCount and isColdCount queries.
50   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   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   Optional<bool> HasLargeWorkingSetSize;
59   // Compute the threshold for a given cutoff.
60   Optional<uint64_t> computeThreshold(int PercentileCutoff);
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   DenseMap<int, uint64_t> ThresholdCache;
64 
65 public:
66   ProfileSummaryInfo(Module &M) : M(M) {}
67   ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
68       : M(Arg.M), Summary(std::move(Arg.Summary)) {}
69 
70   /// Returns true if profile summary is available.
71   bool hasProfileSummary() { return computeSummary(); }
72 
73   /// Returns true if module \c M has sample profile.
74   bool hasSampleProfile() {
75     return hasProfileSummary() &&
76            Summary->getKind() == ProfileSummary::PSK_Sample;
77   }
78 
79   /// Returns true if module \c M has instrumentation profile.
80   bool hasInstrumentationProfile() {
81     return hasProfileSummary() &&
82            Summary->getKind() == ProfileSummary::PSK_Instr;
83   }
84 
85   /// Returns true if module \c M has context sensitive instrumentation profile.
86   bool hasCSInstrumentationProfile() {
87     return hasProfileSummary() &&
88            Summary->getKind() == ProfileSummary::PSK_CSInstr;
89   }
90 
91   /// Handle the invalidation of this information.
92   ///
93   /// When used as a result of \c ProfileSummaryAnalysis this method will be
94   /// called when the module this was computed for changes. Since profile
95   /// summary is immutable after it is annotated on the module, we return false
96   /// here.
97   bool invalidate(Module &, const PreservedAnalyses &,
98                   ModuleAnalysisManager::Invalidator &) {
99     return false;
100   }
101 
102   /// Returns the profile count for \p CallInst.
103   Optional<uint64_t> getProfileCount(const Instruction *CallInst,
104                                      BlockFrequencyInfo *BFI,
105                                      bool AllowSynthetic = false);
106   /// Returns true if the working set size of the code is considered huge.
107   bool hasHugeWorkingSetSize();
108   /// Returns true if the working set size of the code is considered large.
109   bool hasLargeWorkingSetSize();
110   /// Returns true if \p F has hot function entry.
111   bool isFunctionEntryHot(const Function *F);
112   /// Returns true if \p F contains hot code.
113   bool isFunctionHotInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
114   /// Returns true if \p F has cold function entry.
115   bool isFunctionEntryCold(const Function *F);
116   /// Returns true if \p F contains only cold code.
117   bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
118   /// Returns true if \p F contains hot code with regard to a given hot
119   /// percentile cutoff value.
120   bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff,
121                                              const Function *F,
122                                              BlockFrequencyInfo &BFI);
123   /// Returns true if count \p C is considered hot.
124   bool isHotCount(uint64_t C);
125   /// Returns true if count \p C is considered cold.
126   bool isColdCount(uint64_t C);
127   /// Returns true if count \p C is considered hot with regard to a given
128   /// hot percentile cutoff value.
129   bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C);
130   /// Returns true if BasicBlock \p BB is considered hot.
131   bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI);
132   /// Returns true if BasicBlock \p BB is considered cold.
133   bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI);
134   /// Returns true if BasicBlock \p BB is considered hot with regard to a given
135   /// hot percentile cutoff value.
136   bool isHotBlockNthPercentile(int PercentileCutoff,
137                                const BasicBlock *BB, BlockFrequencyInfo *BFI);
138   /// Returns true if CallSite \p CS is considered hot.
139   bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
140   /// Returns true if Callsite \p CS is considered cold.
141   bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
142   /// Returns HotCountThreshold if set. Recompute HotCountThreshold
143   /// if not set.
144   uint64_t getOrCompHotCountThreshold();
145   /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
146   /// if not set.
147   uint64_t getOrCompColdCountThreshold();
148   /// Returns HotCountThreshold if set.
149   uint64_t getHotCountThreshold() {
150     return HotCountThreshold ? HotCountThreshold.getValue() : 0;
151   }
152   /// Returns ColdCountThreshold if set.
153   uint64_t getColdCountThreshold() {
154     return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
155   }
156 };
157 
158 /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
159 class ProfileSummaryInfoWrapperPass : public ImmutablePass {
160   std::unique_ptr<ProfileSummaryInfo> PSI;
161 
162 public:
163   static char ID;
164   ProfileSummaryInfoWrapperPass();
165 
166   ProfileSummaryInfo &getPSI() { return *PSI; }
167   const ProfileSummaryInfo &getPSI() const { return *PSI; }
168 
169   bool doInitialization(Module &M) override;
170   bool doFinalization(Module &M) override;
171   void getAnalysisUsage(AnalysisUsage &AU) const override {
172     AU.setPreservesAll();
173   }
174 };
175 
176 /// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
177 class ProfileSummaryAnalysis
178     : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
179 public:
180   typedef ProfileSummaryInfo Result;
181 
182   Result run(Module &M, ModuleAnalysisManager &);
183 
184 private:
185   friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
186   static AnalysisKey Key;
187 };
188 
189 /// Printer pass that uses \c ProfileSummaryAnalysis.
190 class ProfileSummaryPrinterPass
191     : public PassInfoMixin<ProfileSummaryPrinterPass> {
192   raw_ostream &OS;
193 
194 public:
195   explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
196   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
197 };
198 
199 } // end namespace llvm
200 
201 #endif
202