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 // Check if there is a profile metadata on the instruction. If it is present, 79 // determine hotness solely based on that. 80 uint64_t TotalCount; 81 if (Inst->extractProfTotalWeight(TotalCount)) 82 return TotalCount; 83 if (BFI) 84 return BFI->getBlockProfileCount(Inst->getParent()); 85 return None; 86 } 87 88 /// Returns true if the function's entry is hot. If it returns false, it 89 /// either means it is not hot or it is unknown whether it is hot or not (for 90 /// example, no profile data is available). 91 bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) { 92 if (!F || !computeSummary()) 93 return false; 94 auto FunctionCount = F->getEntryCount(); 95 // FIXME: The heuristic used below for determining hotness is based on 96 // preliminary SPEC tuning for inliner. This will eventually be a 97 // convenience method that calls isHotCount. 98 return FunctionCount && isHotCount(FunctionCount.getValue()); 99 } 100 101 /// Returns true if the function's entry or total call edge count is hot. 102 /// If it returns false, it either means it is not hot or it is unknown 103 /// whether it is hot or not (for example, no profile data is available). 104 bool ProfileSummaryInfo::isFunctionHotInCallGraph(const Function *F) { 105 if (!F || !computeSummary()) 106 return false; 107 if (auto FunctionCount = F->getEntryCount()) 108 if (isHotCount(FunctionCount.getValue())) 109 return true; 110 111 uint64_t TotalCallCount = 0; 112 for (const auto &BB : *F) 113 for (const auto &I : BB) 114 if (isa<CallInst>(I) || isa<InvokeInst>(I)) 115 if (auto CallCount = getProfileCount(&I, nullptr)) 116 TotalCallCount += CallCount.getValue(); 117 return isHotCount(TotalCallCount); 118 } 119 120 /// Returns true if the function's entry and total call edge count is cold. 121 /// If it returns false, it either means it is not cold or it is unknown 122 /// whether it is cold or not (for example, no profile data is available). 123 bool ProfileSummaryInfo::isFunctionColdInCallGraph(const Function *F) { 124 if (!F || !computeSummary()) 125 return false; 126 if (auto FunctionCount = F->getEntryCount()) 127 if (!isColdCount(FunctionCount.getValue())) 128 return false; 129 130 uint64_t TotalCallCount = 0; 131 for (const auto &BB : *F) 132 for (const auto &I : BB) 133 if (isa<CallInst>(I) || isa<InvokeInst>(I)) 134 if (auto CallCount = getProfileCount(&I, nullptr)) 135 TotalCallCount += CallCount.getValue(); 136 return isColdCount(TotalCallCount); 137 } 138 139 /// Returns true if the function's entry is a cold. If it returns false, it 140 /// either means it is not cold or it is unknown whether it is cold or not (for 141 /// example, no profile data is available). 142 bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) { 143 if (!F) 144 return false; 145 if (F->hasFnAttribute(Attribute::Cold)) 146 return true; 147 if (!computeSummary()) 148 return false; 149 auto FunctionCount = F->getEntryCount(); 150 // FIXME: The heuristic used below for determining coldness is based on 151 // preliminary SPEC tuning for inliner. This will eventually be a 152 // convenience method that calls isHotCount. 153 return FunctionCount && isColdCount(FunctionCount.getValue()); 154 } 155 156 /// Compute the hot and cold thresholds. 157 void ProfileSummaryInfo::computeThresholds() { 158 if (!computeSummary()) 159 return; 160 auto &DetailedSummary = Summary->getDetailedSummary(); 161 HotCountThreshold = 162 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffHot); 163 ColdCountThreshold = 164 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffCold); 165 } 166 167 bool ProfileSummaryInfo::isHotCount(uint64_t C) { 168 if (!HotCountThreshold) 169 computeThresholds(); 170 return HotCountThreshold && C >= HotCountThreshold.getValue(); 171 } 172 173 bool ProfileSummaryInfo::isColdCount(uint64_t C) { 174 if (!ColdCountThreshold) 175 computeThresholds(); 176 return ColdCountThreshold && C <= ColdCountThreshold.getValue(); 177 } 178 179 bool ProfileSummaryInfo::isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI) { 180 auto Count = BFI->getBlockProfileCount(B); 181 return Count && isHotCount(*Count); 182 } 183 184 bool ProfileSummaryInfo::isColdBB(const BasicBlock *B, 185 BlockFrequencyInfo *BFI) { 186 auto Count = BFI->getBlockProfileCount(B); 187 return Count && isColdCount(*Count); 188 } 189 190 bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS, 191 BlockFrequencyInfo *BFI) { 192 auto C = getProfileCount(CS.getInstruction(), BFI); 193 return C && isHotCount(*C); 194 } 195 196 bool ProfileSummaryInfo::isColdCallSite(const CallSite &CS, 197 BlockFrequencyInfo *BFI) { 198 auto C = getProfileCount(CS.getInstruction(), BFI); 199 return C && isColdCount(*C); 200 } 201 202 INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info", 203 "Profile summary info", false, true) 204 205 ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass() 206 : ImmutablePass(ID) { 207 initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 208 } 209 210 bool ProfileSummaryInfoWrapperPass::doInitialization(Module &M) { 211 PSI.reset(new ProfileSummaryInfo(M)); 212 return false; 213 } 214 215 bool ProfileSummaryInfoWrapperPass::doFinalization(Module &M) { 216 PSI.reset(); 217 return false; 218 } 219 220 AnalysisKey ProfileSummaryAnalysis::Key; 221 ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M, 222 ModuleAnalysisManager &) { 223 return ProfileSummaryInfo(M); 224 } 225 226 PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M, 227 ModuleAnalysisManager &AM) { 228 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M); 229 230 OS << "Functions in " << M.getName() << " with hot/cold annotations: \n"; 231 for (auto &F : M) { 232 OS << F.getName(); 233 if (PSI.isFunctionEntryHot(&F)) 234 OS << " :hot entry "; 235 else if (PSI.isFunctionEntryCold(&F)) 236 OS << " :cold entry "; 237 OS << "\n"; 238 } 239 return PreservedAnalyses::all(); 240 } 241 242 char ProfileSummaryInfoWrapperPass::ID = 0; 243