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(999000), 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 // Find the minimum count to reach a desired percentile of counts. 43 static uint64_t getMinCountForPercentile(SummaryEntryVector &DS, 44 uint64_t Percentile) { 45 auto Compare = [](const ProfileSummaryEntry &Entry, uint64_t Percentile) { 46 return Entry.Cutoff < Percentile; 47 }; 48 auto It = std::lower_bound(DS.begin(), DS.end(), Percentile, Compare); 49 // The required percentile has to be <= one of the percentiles in the 50 // detailed summary. 51 if (It == DS.end()) 52 report_fatal_error("Desired percentile exceeds the maximum cutoff"); 53 return It->MinCount; 54 } 55 56 // The profile summary metadata may be attached either by the frontend or by 57 // any backend passes (IR level instrumentation, for example). This method 58 // checks if the Summary is null and if so checks if the summary metadata is now 59 // available in the module and parses it to get the Summary object. Returns true 60 // if a valid Summary is available. 61 bool ProfileSummaryInfo::computeSummary() { 62 if (Summary) 63 return true; 64 auto *SummaryMD = M.getProfileSummary(); 65 if (!SummaryMD) 66 return false; 67 Summary.reset(ProfileSummary::getFromMD(SummaryMD)); 68 return true; 69 } 70 71 Optional<uint64_t> 72 ProfileSummaryInfo::getProfileCount(const Instruction *Inst, 73 BlockFrequencyInfo *BFI) { 74 if (!Inst) 75 return None; 76 assert((isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) && 77 "We can only get profile count for call/invoke instruction."); 78 if (hasSampleProfile()) { 79 // In sample PGO mode, check if there is a profile metadata on the 80 // instruction. If it is present, determine hotness solely based on that, 81 // since the sampled entry count may not be accurate. 82 uint64_t TotalCount; 83 if (Inst->extractProfTotalWeight(TotalCount)) 84 return TotalCount; 85 } 86 if (BFI) 87 return BFI->getBlockProfileCount(Inst->getParent()); 88 return None; 89 } 90 91 /// Returns true if the function's entry is hot. If it returns false, it 92 /// either means it is not hot or it is unknown whether it is hot or not (for 93 /// example, no profile data is available). 94 bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) { 95 if (!F || !computeSummary()) 96 return false; 97 auto FunctionCount = F->getEntryCount(); 98 // FIXME: The heuristic used below for determining hotness is based on 99 // preliminary SPEC tuning for inliner. This will eventually be a 100 // convenience method that calls isHotCount. 101 return FunctionCount && isHotCount(FunctionCount.getValue()); 102 } 103 104 /// Returns true if the function's entry or total call edge count is hot. 105 /// If it returns false, it either means it is not hot or it is unknown 106 /// whether it is hot or not (for example, no profile data is available). 107 bool ProfileSummaryInfo::isFunctionHotInCallGraph(const Function *F) { 108 if (!F || !computeSummary()) 109 return false; 110 if (auto FunctionCount = F->getEntryCount()) 111 if (isHotCount(FunctionCount.getValue())) 112 return true; 113 114 uint64_t TotalCallCount = 0; 115 for (const auto &BB : *F) 116 for (const auto &I : BB) 117 if (isa<CallInst>(I) || isa<InvokeInst>(I)) 118 if (auto CallCount = getProfileCount(&I, nullptr)) 119 TotalCallCount += CallCount.getValue(); 120 return isHotCount(TotalCallCount); 121 } 122 123 /// Returns true if the function's entry and total call edge count is cold. 124 /// If it returns false, it either means it is not cold or it is unknown 125 /// whether it is cold or not (for example, no profile data is available). 126 bool ProfileSummaryInfo::isFunctionColdInCallGraph(const Function *F) { 127 if (!F || !computeSummary()) 128 return false; 129 if (auto FunctionCount = F->getEntryCount()) 130 if (!isColdCount(FunctionCount.getValue())) 131 return false; 132 133 uint64_t TotalCallCount = 0; 134 for (const auto &BB : *F) 135 for (const auto &I : BB) 136 if (isa<CallInst>(I) || isa<InvokeInst>(I)) 137 if (auto CallCount = getProfileCount(&I, nullptr)) 138 TotalCallCount += CallCount.getValue(); 139 return isColdCount(TotalCallCount); 140 } 141 142 /// Returns true if the function's entry is a cold. If it returns false, it 143 /// either means it is not cold or it is unknown whether it is cold or not (for 144 /// example, no profile data is available). 145 bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) { 146 if (!F) 147 return false; 148 if (F->hasFnAttribute(Attribute::Cold)) 149 return true; 150 if (!computeSummary()) 151 return false; 152 auto FunctionCount = F->getEntryCount(); 153 // FIXME: The heuristic used below for determining coldness is based on 154 // preliminary SPEC tuning for inliner. This will eventually be a 155 // convenience method that calls isHotCount. 156 return FunctionCount && isColdCount(FunctionCount.getValue()); 157 } 158 159 /// Compute the hot and cold thresholds. 160 void ProfileSummaryInfo::computeThresholds() { 161 if (!computeSummary()) 162 return; 163 auto &DetailedSummary = Summary->getDetailedSummary(); 164 HotCountThreshold = 165 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffHot); 166 ColdCountThreshold = 167 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffCold); 168 } 169 170 bool ProfileSummaryInfo::isHotCount(uint64_t C) { 171 if (!HotCountThreshold) 172 computeThresholds(); 173 return HotCountThreshold && C >= HotCountThreshold.getValue(); 174 } 175 176 bool ProfileSummaryInfo::isColdCount(uint64_t C) { 177 if (!ColdCountThreshold) 178 computeThresholds(); 179 return ColdCountThreshold && C <= ColdCountThreshold.getValue(); 180 } 181 182 bool ProfileSummaryInfo::isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI) { 183 auto Count = BFI->getBlockProfileCount(B); 184 return Count && isHotCount(*Count); 185 } 186 187 bool ProfileSummaryInfo::isColdBB(const BasicBlock *B, 188 BlockFrequencyInfo *BFI) { 189 auto Count = BFI->getBlockProfileCount(B); 190 return Count && isColdCount(*Count); 191 } 192 193 bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS, 194 BlockFrequencyInfo *BFI) { 195 auto C = getProfileCount(CS.getInstruction(), BFI); 196 return C && isHotCount(*C); 197 } 198 199 bool ProfileSummaryInfo::isColdCallSite(const CallSite &CS, 200 BlockFrequencyInfo *BFI) { 201 auto C = getProfileCount(CS.getInstruction(), BFI); 202 return C && isColdCount(*C); 203 } 204 205 INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info", 206 "Profile summary info", false, true) 207 208 ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass() 209 : ImmutablePass(ID) { 210 initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 211 } 212 213 bool ProfileSummaryInfoWrapperPass::doInitialization(Module &M) { 214 PSI.reset(new ProfileSummaryInfo(M)); 215 return false; 216 } 217 218 bool ProfileSummaryInfoWrapperPass::doFinalization(Module &M) { 219 PSI.reset(); 220 return false; 221 } 222 223 AnalysisKey ProfileSummaryAnalysis::Key; 224 ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M, 225 ModuleAnalysisManager &) { 226 return ProfileSummaryInfo(M); 227 } 228 229 PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M, 230 ModuleAnalysisManager &AM) { 231 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M); 232 233 OS << "Functions in " << M.getName() << " with hot/cold annotations: \n"; 234 for (auto &F : M) { 235 OS << F.getName(); 236 if (PSI.isFunctionEntryHot(&F)) 237 OS << " :hot entry "; 238 else if (PSI.isFunctionEntryCold(&F)) 239 OS << " :cold entry "; 240 OS << "\n"; 241 } 242 return PreservedAnalyses::all(); 243 } 244 245 char ProfileSummaryInfoWrapperPass::ID = 0; 246