Mercurial > hg > CbC > CbC_llvm
diff lib/Analysis/ProfileSummaryInfo.cpp @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 1172e4bd9c6f |
children | 3a76565eade5 |
line wrap: on
line diff
--- a/lib/Analysis/ProfileSummaryInfo.cpp Fri Nov 25 19:14:25 2016 +0900 +++ b/lib/Analysis/ProfileSummaryInfo.cpp Fri Oct 27 17:07:41 2017 +0900 @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/BlockFrequencyInfo.h" -#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/ProfileSummary.h" @@ -29,7 +30,7 @@ // considered cold). static cl::opt<int> ProfileSummaryCutoffHot( - "profile-summary-cutoff-hot", cl::Hidden, cl::init(999000), cl::ZeroOrMore, + "profile-summary-cutoff-hot", cl::Hidden, cl::init(990000), cl::ZeroOrMore, cl::desc("A count is hot if it exceeds the minimum count to" " reach this percentile of total counts.")); @@ -38,9 +39,21 @@ cl::desc("A count is cold if it is below the minimum count" " to reach this percentile of total counts.")); -// Find the minimum count to reach a desired percentile of counts. -static uint64_t getMinCountForPercentile(SummaryEntryVector &DS, - uint64_t Percentile) { +static cl::opt<bool> ProfileSampleAccurate( + "profile-sample-accurate", cl::Hidden, cl::init(false), + cl::desc("If the sample profile is accurate, we will mark all un-sampled " + "callsite as cold. Otherwise, treat un-sampled callsites as if " + "we have no profile.")); +static cl::opt<unsigned> ProfileSummaryHugeWorkingSetSizeThreshold( + "profile-summary-huge-working-set-size-threshold", cl::Hidden, + cl::init(15000), cl::ZeroOrMore, + cl::desc("The code working set size is considered huge if the number of" + " blocks required to reach the -profile-summary-cutoff-hot" + " percentile exceeds this count.")); + +// Find the summary entry for a desired percentile of counts. +static const ProfileSummaryEntry &getEntryForPercentile(SummaryEntryVector &DS, + uint64_t Percentile) { auto Compare = [](const ProfileSummaryEntry &Entry, uint64_t Percentile) { return Entry.Cutoff < Percentile; }; @@ -49,28 +62,51 @@ // detailed summary. if (It == DS.end()) report_fatal_error("Desired percentile exceeds the maximum cutoff"); - return It->MinCount; + return *It; } // The profile summary metadata may be attached either by the frontend or by // any backend passes (IR level instrumentation, for example). This method // checks if the Summary is null and if so checks if the summary metadata is now -// available in the module and parses it to get the Summary object. -void ProfileSummaryInfo::computeSummary() { +// available in the module and parses it to get the Summary object. Returns true +// if a valid Summary is available. +bool ProfileSummaryInfo::computeSummary() { if (Summary) - return; + return true; auto *SummaryMD = M.getProfileSummary(); if (!SummaryMD) - return; + return false; Summary.reset(ProfileSummary::getFromMD(SummaryMD)); + return true; +} + +Optional<uint64_t> +ProfileSummaryInfo::getProfileCount(const Instruction *Inst, + BlockFrequencyInfo *BFI) { + if (!Inst) + return None; + assert((isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) && + "We can only get profile count for call/invoke instruction."); + if (hasSampleProfile()) { + // In sample PGO mode, check if there is a profile metadata on the + // instruction. If it is present, determine hotness solely based on that, + // since the sampled entry count may not be accurate. If there is no + // annotated on the instruction, return None. + uint64_t TotalCount; + if (Inst->extractProfTotalWeight(TotalCount)) + return TotalCount; + return None; + } + if (BFI) + return BFI->getBlockProfileCount(Inst->getParent()); + return None; } /// Returns true if the function's entry is hot. If it returns false, it /// either means it is not hot or it is unknown whether it is hot or not (for /// example, no profile data is available). bool ProfileSummaryInfo::isFunctionEntryHot(const Function *F) { - computeSummary(); - if (!F || !Summary) + if (!F || !computeSummary()) return false; auto FunctionCount = F->getEntryCount(); // FIXME: The heuristic used below for determining hotness is based on @@ -79,17 +115,53 @@ return FunctionCount && isHotCount(FunctionCount.getValue()); } +/// Returns true if the function's entry or total call edge count is hot. +/// If it returns false, it either means it is not hot or it is unknown +/// whether it is hot or not (for example, no profile data is available). +bool ProfileSummaryInfo::isFunctionHotInCallGraph(const Function *F) { + if (!F || !computeSummary()) + return false; + if (auto FunctionCount = F->getEntryCount()) + if (isHotCount(FunctionCount.getValue())) + return true; + + uint64_t TotalCallCount = 0; + for (const auto &BB : *F) + for (const auto &I : BB) + if (isa<CallInst>(I) || isa<InvokeInst>(I)) + if (auto CallCount = getProfileCount(&I, nullptr)) + TotalCallCount += CallCount.getValue(); + return isHotCount(TotalCallCount); +} + +/// Returns true if the function's entry and total call edge count is cold. +/// If it returns false, it either means it is not cold or it is unknown +/// whether it is cold or not (for example, no profile data is available). +bool ProfileSummaryInfo::isFunctionColdInCallGraph(const Function *F) { + if (!F || !computeSummary()) + return false; + if (auto FunctionCount = F->getEntryCount()) + if (!isColdCount(FunctionCount.getValue())) + return false; + + uint64_t TotalCallCount = 0; + for (const auto &BB : *F) + for (const auto &I : BB) + if (isa<CallInst>(I) || isa<InvokeInst>(I)) + if (auto CallCount = getProfileCount(&I, nullptr)) + TotalCallCount += CallCount.getValue(); + return isColdCount(TotalCallCount); +} + /// Returns true if the function's entry is a cold. If it returns false, it /// either means it is not cold or it is unknown whether it is cold or not (for /// example, no profile data is available). bool ProfileSummaryInfo::isFunctionEntryCold(const Function *F) { - computeSummary(); if (!F) return false; - if (F->hasFnAttribute(Attribute::Cold)) { + if (F->hasFnAttribute(Attribute::Cold)) return true; - } - if (!Summary) + if (!computeSummary()) return false; auto FunctionCount = F->getEntryCount(); // FIXME: The heuristic used below for determining coldness is based on @@ -100,15 +172,23 @@ /// Compute the hot and cold thresholds. void ProfileSummaryInfo::computeThresholds() { - if (!Summary) - computeSummary(); - if (!Summary) + if (!computeSummary()) return; auto &DetailedSummary = Summary->getDetailedSummary(); - HotCountThreshold = - getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffHot); - ColdCountThreshold = - getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffCold); + auto &HotEntry = + getEntryForPercentile(DetailedSummary, ProfileSummaryCutoffHot); + HotCountThreshold = HotEntry.MinCount; + auto &ColdEntry = + getEntryForPercentile(DetailedSummary, ProfileSummaryCutoffCold); + ColdCountThreshold = ColdEntry.MinCount; + HasHugeWorkingSetSize = + HotEntry.NumCounts > ProfileSummaryHugeWorkingSetSizeThreshold; +} + +bool ProfileSummaryInfo::hasHugeWorkingSetSize() { + if (!HasHugeWorkingSetSize) + computeThresholds(); + return HasHugeWorkingSetSize && HasHugeWorkingSetSize.getValue(); } bool ProfileSummaryInfo::isHotCount(uint64_t C) { @@ -125,20 +205,34 @@ bool ProfileSummaryInfo::isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI) { auto Count = BFI->getBlockProfileCount(B); - if (Count && isHotCount(*Count)) - return true; - // Use extractProfTotalWeight to get BB count. - // For Sample PGO, BFI may not provide accurate BB count due to errors - // magnified during sample count propagation. This serves as a backup plan - // to ensure all hot BB will not be missed. - // The query currently has false positives as branch instruction cloning does - // not update/scale branch weights. Unlike false negatives, this will not cause - // performance problem. - uint64_t TotalCount; - if (B->getTerminator()->extractProfTotalWeight(TotalCount) && - isHotCount(TotalCount)) - return true; - return false; + return Count && isHotCount(*Count); +} + +bool ProfileSummaryInfo::isColdBB(const BasicBlock *B, + BlockFrequencyInfo *BFI) { + auto Count = BFI->getBlockProfileCount(B); + return Count && isColdCount(*Count); +} + +bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS, + BlockFrequencyInfo *BFI) { + auto C = getProfileCount(CS.getInstruction(), BFI); + return C && isHotCount(*C); +} + +bool ProfileSummaryInfo::isColdCallSite(const CallSite &CS, + BlockFrequencyInfo *BFI) { + auto C = getProfileCount(CS.getInstruction(), BFI); + if (C) + return isColdCount(*C); + + // In SamplePGO, if the caller has been sampled, and there is no profile + // annotatedon the callsite, we consider the callsite as cold. + // If there is no profile for the caller, and we know the profile is + // accurate, we consider the callsite as cold. + return (hasSampleProfile() && + (CS.getCaller()->getEntryCount() || ProfileSampleAccurate || + CS.getCaller()->hasFnAttribute("profile-sample-accurate"))); } INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info",