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