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 |