Path: blob/main/contrib/llvm-project/llvm/lib/ProfileData/ProfileSummaryBuilder.cpp
35233 views
//=-- ProfilesummaryBuilder.cpp - Profile summary computation ---------------=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains support for computing profile summary data.9//10//===----------------------------------------------------------------------===//1112#include "llvm/IR/ProfileSummary.h"13#include "llvm/ProfileData/InstrProf.h"14#include "llvm/ProfileData/ProfileCommon.h"15#include "llvm/ProfileData/SampleProf.h"16#include "llvm/Support/CommandLine.h"1718using namespace llvm;1920namespace llvm {21cl::opt<bool> UseContextLessSummary(22"profile-summary-contextless", cl::Hidden,23cl::desc("Merge context profiles before calculating thresholds."));2425// The following two parameters determine the threshold for a count to be26// considered hot/cold. These two parameters are percentile values (multiplied27// by 10000). If the counts are sorted in descending order, the minimum count to28// reach ProfileSummaryCutoffHot gives the threshold to determine a hot count.29// Similarly, the minimum count to reach ProfileSummaryCutoffCold gives the30// threshold for determining cold count (everything <= this threshold is31// considered cold).32cl::opt<int> ProfileSummaryCutoffHot(33"profile-summary-cutoff-hot", cl::Hidden, cl::init(990000),34cl::desc("A count is hot if it exceeds the minimum count to"35" reach this percentile of total counts."));3637cl::opt<int> ProfileSummaryCutoffCold(38"profile-summary-cutoff-cold", cl::Hidden, cl::init(999999),39cl::desc("A count is cold if it is below the minimum count"40" to reach this percentile of total counts."));4142cl::opt<unsigned> ProfileSummaryHugeWorkingSetSizeThreshold(43"profile-summary-huge-working-set-size-threshold", cl::Hidden,44cl::init(15000),45cl::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."));4849cl::opt<unsigned> ProfileSummaryLargeWorkingSetSizeThreshold(50"profile-summary-large-working-set-size-threshold", cl::Hidden,51cl::init(12500),52cl::desc("The code working set size is considered large if the number of"53" blocks required to reach the -profile-summary-cutoff-hot"54" percentile exceeds this count."));5556// The next two options override the counts derived from summary computation and57// are useful for debugging purposes.58cl::opt<uint64_t> ProfileSummaryHotCount(59"profile-summary-hot-count", cl::ReallyHidden,60cl::desc("A fixed hot count that overrides the count derived from"61" profile-summary-cutoff-hot"));6263cl::opt<uint64_t> ProfileSummaryColdCount(64"profile-summary-cold-count", cl::ReallyHidden,65cl::desc("A fixed cold count that overrides the count derived from"66" profile-summary-cutoff-cold"));67} // namespace llvm6869// A set of cutoff values. Each value, when divided by ProfileSummary::Scale70// (which is 1000000) is a desired percentile of total counts.71static const uint32_t DefaultCutoffsData[] = {7210000, /* 1% */73100000, /* 10% */74200000, 300000, 400000, 500000, 600000, 700000, 800000,75900000, 950000, 990000, 999000, 999900, 999990, 999999};76const ArrayRef<uint32_t> ProfileSummaryBuilder::DefaultCutoffs =77DefaultCutoffsData;7879const ProfileSummaryEntry &80ProfileSummaryBuilder::getEntryForPercentile(const SummaryEntryVector &DS,81uint64_t Percentile) {82auto It = partition_point(DS, [=](const ProfileSummaryEntry &Entry) {83return Entry.Cutoff < Percentile;84});85// The required percentile has to be <= one of the percentiles in the86// detailed summary.87if (It == DS.end())88report_fatal_error("Desired percentile exceeds the maximum cutoff");89return *It;90}9192void InstrProfSummaryBuilder::addRecord(const InstrProfRecord &R) {93// The first counter is not necessarily an entry count for IR94// instrumentation profiles.95// Eventually MaxFunctionCount will become obsolete and this can be96// removed.9798if (R.getCountPseudoKind() != InstrProfRecord::NotPseudo)99return;100101addEntryCount(R.Counts[0]);102for (size_t I = 1, E = R.Counts.size(); I < E; ++I)103addInternalCount(R.Counts[I]);104}105106// To compute the detailed summary, we consider each line containing samples as107// equivalent to a block with a count in the instrumented profile.108void SampleProfileSummaryBuilder::addRecord(109const sampleprof::FunctionSamples &FS, bool isCallsiteSample) {110if (!isCallsiteSample) {111NumFunctions++;112if (FS.getHeadSamples() > MaxFunctionCount)113MaxFunctionCount = FS.getHeadSamples();114} else if (FS.getContext().hasAttribute(115sampleprof::ContextDuplicatedIntoBase)) {116// Do not recount callee samples if they are already merged into their base117// profiles. This can happen to CS nested profile.118return;119}120121for (const auto &I : FS.getBodySamples()) {122uint64_t Count = I.second.getSamples();123addCount(Count);124}125for (const auto &I : FS.getCallsiteSamples())126for (const auto &CS : I.second)127addRecord(CS.second, true);128}129130// The argument to this method is a vector of cutoff percentages and the return131// value is a vector of (Cutoff, MinCount, NumCounts) triplets.132void ProfileSummaryBuilder::computeDetailedSummary() {133if (DetailedSummaryCutoffs.empty())134return;135llvm::sort(DetailedSummaryCutoffs);136auto Iter = CountFrequencies.begin();137const auto End = CountFrequencies.end();138139uint32_t CountsSeen = 0;140uint64_t CurrSum = 0, Count = 0;141142for (const uint32_t Cutoff : DetailedSummaryCutoffs) {143assert(Cutoff <= 999999);144APInt Temp(128, TotalCount);145APInt N(128, Cutoff);146APInt D(128, ProfileSummary::Scale);147Temp *= N;148Temp = Temp.sdiv(D);149uint64_t DesiredCount = Temp.getZExtValue();150assert(DesiredCount <= TotalCount);151while (CurrSum < DesiredCount && Iter != End) {152Count = Iter->first;153uint32_t Freq = Iter->second;154CurrSum += (Count * Freq);155CountsSeen += Freq;156Iter++;157}158assert(CurrSum >= DesiredCount);159ProfileSummaryEntry PSE = {Cutoff, Count, CountsSeen};160DetailedSummary.push_back(PSE);161}162}163164uint64_t165ProfileSummaryBuilder::getHotCountThreshold(const SummaryEntryVector &DS) {166auto &HotEntry =167ProfileSummaryBuilder::getEntryForPercentile(DS, ProfileSummaryCutoffHot);168uint64_t HotCountThreshold = HotEntry.MinCount;169if (ProfileSummaryHotCount.getNumOccurrences() > 0)170HotCountThreshold = ProfileSummaryHotCount;171return HotCountThreshold;172}173174uint64_t175ProfileSummaryBuilder::getColdCountThreshold(const SummaryEntryVector &DS) {176auto &ColdEntry = ProfileSummaryBuilder::getEntryForPercentile(177DS, ProfileSummaryCutoffCold);178uint64_t ColdCountThreshold = ColdEntry.MinCount;179if (ProfileSummaryColdCount.getNumOccurrences() > 0)180ColdCountThreshold = ProfileSummaryColdCount;181return ColdCountThreshold;182}183184std::unique_ptr<ProfileSummary> SampleProfileSummaryBuilder::getSummary() {185computeDetailedSummary();186return std::make_unique<ProfileSummary>(187ProfileSummary::PSK_Sample, DetailedSummary, TotalCount, MaxCount, 0,188MaxFunctionCount, NumCounts, NumFunctions);189}190191std::unique_ptr<ProfileSummary>192SampleProfileSummaryBuilder::computeSummaryForProfiles(193const SampleProfileMap &Profiles) {194assert(NumFunctions == 0 &&195"This can only be called on an empty summary builder");196sampleprof::SampleProfileMap ContextLessProfiles;197const sampleprof::SampleProfileMap *ProfilesToUse = &Profiles;198// For CSSPGO, context-sensitive profile effectively split a function profile199// into many copies each representing the CFG profile of a particular calling200// context. That makes the count distribution looks more flat as we now have201// more function profiles each with lower counts, which in turn leads to lower202// hot thresholds. To compensate for that, by default we merge context203// profiles before computing profile summary.204if (UseContextLessSummary || (sampleprof::FunctionSamples::ProfileIsCS &&205!UseContextLessSummary.getNumOccurrences())) {206ProfileConverter::flattenProfile(Profiles, ContextLessProfiles, true);207ProfilesToUse = &ContextLessProfiles;208}209210for (const auto &I : *ProfilesToUse) {211const sampleprof::FunctionSamples &Profile = I.second;212addRecord(Profile);213}214215return getSummary();216}217218std::unique_ptr<ProfileSummary> InstrProfSummaryBuilder::getSummary() {219computeDetailedSummary();220return std::make_unique<ProfileSummary>(221ProfileSummary::PSK_Instr, DetailedSummary, TotalCount, MaxCount,222MaxInternalBlockCount, MaxFunctionCount, NumCounts, NumFunctions);223}224225void InstrProfSummaryBuilder::addEntryCount(uint64_t Count) {226assert(Count <= getInstrMaxCountValue() &&227"Count value should be less than the max count value.");228NumFunctions++;229addCount(Count);230if (Count > MaxFunctionCount)231MaxFunctionCount = Count;232}233234void InstrProfSummaryBuilder::addInternalCount(uint64_t Count) {235assert(Count <= getInstrMaxCountValue() &&236"Count value should be less than the max count value.");237addCount(Count);238if (Count > MaxInternalBlockCount)239MaxInternalBlockCount = Count;240}241242243