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/BlockFrequencyInfo.h" 16 #include "llvm/Analysis/ProfileSummaryInfo.h" 17 #include "llvm/IR/BasicBlock.h" 18 #include "llvm/IR/Metadata.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/IR/ProfileSummary.h" 21 using namespace llvm; 22 23 // The following two parameters determine the threshold for a count to be 24 // considered hot/cold. These two parameters are percentile values (multiplied 25 // by 10000). If the counts are sorted in descending order, the minimum count to 26 // reach ProfileSummaryCutoffHot gives the threshold to determine a hot count. 27 // Similarly, the minimum count to reach ProfileSummaryCutoffCold gives the 28 // threshold for determining cold count (everything <= this threshold is 29 // considered cold). 30 31 static cl::opt<int> ProfileSummaryCutoffHot( 32 "profile-summary-cutoff-hot", cl::Hidden, cl::init(999000), cl::ZeroOrMore, 33 cl::desc("A count is hot if it exceeds the minimum count to" 34 " reach this percentile of total counts.")); 35 36 static cl::opt<int> ProfileSummaryCutoffCold( 37 "profile-summary-cutoff-cold", cl::Hidden, cl::init(999999), cl::ZeroOrMore, 38 cl::desc("A count is cold if it is below the minimum count" 39 " to reach this percentile of total counts.")); 40 41 // Find the minimum count to reach a desired percentile of counts. 42 static uint64_t getMinCountForPercentile(SummaryEntryVector &DS, 43 uint64_t Percentile) { 44 auto Compare = [](const ProfileSummaryEntry &Entry, uint64_t Percentile) { 45 return Entry.Cutoff < Percentile; 46 }; 47 auto It = std::lower_bound(DS.begin(), DS.end(), Percentile, Compare); 48 // The required percentile has to be <= one of the percentiles in the 49 // detailed summary. 50 if (It == DS.end()) 51 report_fatal_error("Desired percentile exceeds the maximum cutoff"); 52 return It->MinCount; 53 } 54 55 // The profile summary metadata may be attached either by the frontend or by 56 // any backend passes (IR level instrumentation, for example). This method 57 // checks if the Summary is null and if so checks if the summary metadata is now 58 // available in the module and parses it to get the Summary object. 59 void ProfileSummaryInfo::computeSummary() { 60 if (Summary) 61 return; 62 auto *SummaryMD = M.getProfileSummary(); 63 if (!SummaryMD) 64 return; 65 Summary.reset(ProfileSummary::getFromMD(SummaryMD)); 66 } 67 68 /// Returns true if the function's entry is hot. If it returns false, it 69 /// either means it is not hot or it is unknown whether it is hot or not (for 70 /// example, no profile data is available). 71 bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) { 72 computeSummary(); 73 if (!F || !Summary) 74 return false; 75 auto FunctionCount = F->getEntryCount(); 76 // FIXME: The heuristic used below for determining hotness is based on 77 // preliminary SPEC tuning for inliner. This will eventually be a 78 // convenience method that calls isHotCount. 79 return FunctionCount && isHotCount(FunctionCount.getValue()); 80 } 81 82 /// Returns true if the function's entry is a cold. If it returns false, it 83 /// either means it is not cold or it is unknown whether it is cold or not (for 84 /// example, no profile data is available). 85 bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) { 86 computeSummary(); 87 if (!F) 88 return false; 89 if (F->hasFnAttribute(Attribute::Cold)) { 90 return true; 91 } 92 if (!Summary) 93 return false; 94 auto FunctionCount = F->getEntryCount(); 95 // FIXME: The heuristic used below for determining coldness is based on 96 // preliminary SPEC tuning for inliner. This will eventually be a 97 // convenience method that calls isHotCount. 98 return FunctionCount && isColdCount(FunctionCount.getValue()); 99 } 100 101 /// Compute the hot and cold thresholds. 102 void ProfileSummaryInfo::computeThresholds() { 103 if (!Summary) 104 computeSummary(); 105 if (!Summary) 106 return; 107 auto &DetailedSummary = Summary->getDetailedSummary(); 108 HotCountThreshold = 109 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffHot); 110 ColdCountThreshold = 111 getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffCold); 112 } 113 114 bool ProfileSummaryInfo::isHotCount(uint64_t C) { 115 if (!HotCountThreshold) 116 computeThresholds(); 117 return HotCountThreshold && C >= HotCountThreshold.getValue(); 118 } 119 120 bool ProfileSummaryInfo::isColdCount(uint64_t C) { 121 if (!ColdCountThreshold) 122 computeThresholds(); 123 return ColdCountThreshold && C <= ColdCountThreshold.getValue(); 124 } 125 126 bool ProfileSummaryInfo::isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI) { 127 auto Count = BFI->getBlockProfileCount(B); 128 if (Count && isHotCount(*Count)) 129 return true; 130 // Use extractProfTotalWeight to get BB count. 131 // For Sample PGO, BFI may not provide accurate BB count due to errors 132 // magnified during sample count propagation. This serves as a backup plan 133 // to ensure all hot BB will not be missed. 134 // The query currently has false positives as branch instruction cloning does 135 // not update/scale branch weights. Unlike false negatives, this will not cause 136 // performance problem. 137 uint64_t TotalCount; 138 if (B->getTerminator()->extractProfTotalWeight(TotalCount) && 139 isHotCount(TotalCount)) 140 return true; 141 return false; 142 } 143 144 INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info", 145 "Profile summary info", false, true) 146 147 ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass() 148 : ImmutablePass(ID) { 149 initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 150 } 151 152 bool ProfileSummaryInfoWrapperPass::doInitialization(Module &M) { 153 PSI.reset(new ProfileSummaryInfo(M)); 154 return false; 155 } 156 157 bool ProfileSummaryInfoWrapperPass::doFinalization(Module &M) { 158 PSI.reset(); 159 return false; 160 } 161 162 AnalysisKey ProfileSummaryAnalysis::Key; 163 ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M, 164 ModuleAnalysisManager &) { 165 return ProfileSummaryInfo(M); 166 } 167 168 PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M, 169 ModuleAnalysisManager &AM) { 170 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M); 171 172 OS << "Functions in " << M.getName() << " with hot/cold annotations: \n"; 173 for (auto &F : M) { 174 OS << F.getName(); 175 if (PSI.isFunctionEntryHot(&F)) 176 OS << " :hot entry "; 177 else if (PSI.isFunctionEntryCold(&F)) 178 OS << " :cold entry "; 179 OS << "\n"; 180 } 181 return PreservedAnalyses::all(); 182 } 183 184 char ProfileSummaryInfoWrapperPass::ID = 0; 185