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