//===- ProfileSummaryInfo.cpp - Global profile summary information --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that provides access to the global profile summary
// information.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/InitializePasses.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

// The following two parameters determine the threshold for a count to be
// considered hot/cold. These two parameters are percentile values (multiplied
// by 10000). If the counts are sorted in descending order, the minimum count to
// reach ProfileSummaryCutoffHot gives the threshold to determine a hot count.
// Similarly, the minimum count to reach ProfileSummaryCutoffCold gives the
// threshold for determining cold count (everything <= this threshold is
// considered cold).

static cl::opt<int> ProfileSummaryCutoffHot(
    "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."));

static cl::opt<int> ProfileSummaryCutoffCold(
    "profile-summary-cutoff-cold", cl::Hidden, cl::init(999999), cl::ZeroOrMore,
    cl::desc("A count is cold if it is below the minimum count"
             " to reach this percentile of total counts."));

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."));

static cl::opt<unsigned> ProfileSummaryLargeWorkingSetSizeThreshold(
    "profile-summary-large-working-set-size-threshold", cl::Hidden,
    cl::init(12500), cl::ZeroOrMore,
    cl::desc("The code working set size is considered large if the number of"
             " blocks required to reach the -profile-summary-cutoff-hot"
             " percentile exceeds this count."));

// The next two options override the counts derived from summary computation and
// are useful for debugging purposes.
static cl::opt<int> ProfileSummaryHotCount(
    "profile-summary-hot-count", cl::ReallyHidden, cl::ZeroOrMore,
    cl::desc("A fixed hot count that overrides the count derived from"
             " profile-summary-cutoff-hot"));

static cl::opt<int> ProfileSummaryColdCount(
    "profile-summary-cold-count", cl::ReallyHidden, cl::ZeroOrMore,
    cl::desc("A fixed cold count that overrides the count derived from"
             " profile-summary-cutoff-cold"));

static cl::opt<bool> PartialProfile(
    "partial-profile", cl::Hidden, cl::init(false),
    cl::desc("Specify the current profile is used as a partial profile."));

cl::opt<bool> ScalePartialSampleProfileWorkingSetSize(
    "scale-partial-sample-profile-working-set-size", cl::Hidden, cl::init(true),
    cl::desc(
        "If true, scale the working set size of the partial sample profile "
        "by the partial profile ratio to reflect the size of the program "
        "being compiled."));

static cl::opt<double> PartialSampleProfileWorkingSetSizeScaleFactor(
    "partial-sample-profile-working-set-size-scale-factor", cl::Hidden,
    cl::init(0.008),
    cl::desc("The scale factor used to scale the working set size of the "
             "partial sample profile along with the partial profile ratio. "
             "This includes the factor of the profile counter per block "
             "and the factor to scale the working set size to use the same "
             "shared thresholds as PGO."));

// 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::refresh() {
  if (hasProfileSummary())
    return;
  // First try to get context sensitive ProfileSummary.
  auto *SummaryMD = M->getProfileSummary(/* IsCS */ true);
  if (SummaryMD)
    Summary.reset(ProfileSummary::getFromMD(SummaryMD));

  if (!hasProfileSummary()) {
    // This will actually return PSK_Instr or PSK_Sample summary.
    SummaryMD = M->getProfileSummary(/* IsCS */ false);
    if (SummaryMD)
      Summary.reset(ProfileSummary::getFromMD(SummaryMD));
  }
  if (!hasProfileSummary())
    return;
  computeThresholds();
}

Optional<uint64_t> ProfileSummaryInfo::getProfileCount(
    const CallBase &Call, BlockFrequencyInfo *BFI, bool AllowSynthetic) const {
  assert((isa<CallInst>(Call) || isa<InvokeInst>(Call)) &&
         "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 (Call.extractProfTotalWeight(TotalCount))
      return TotalCount;
    return None;
  }
  if (BFI)
    return BFI->getBlockProfileCount(Call.getParent(), AllowSynthetic);
  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) const {
  if (!F || !hasProfileSummary())
    return false;
  auto FunctionCount = F->getEntryCount();
  // FIXME: The heuristic used below for determining hotness is based on
  // preliminary SPEC tuning for inliner. This will eventually be a
  // convenience method that calls isHotCount.
  return FunctionCount && isHotCount(FunctionCount.getCount());
}

/// Returns true if the function contains hot code. This can include a hot
/// function entry count, hot basic block, or (in the case of Sample PGO)
/// hot total call edge count.
/// If it returns false, it either means it is not hot or it is unknown
/// (for example, no profile data is available).
bool ProfileSummaryInfo::isFunctionHotInCallGraph(
    const Function *F, BlockFrequencyInfo &BFI) const {
  if (!F || !hasProfileSummary())
    return false;
  if (auto FunctionCount = F->getEntryCount())
    if (isHotCount(FunctionCount.getCount()))
      return true;

  if (hasSampleProfile()) {
    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(cast<CallBase>(I), nullptr))
            TotalCallCount += CallCount.getValue();
    if (isHotCount(TotalCallCount))
      return true;
  }
  for (const auto &BB : *F)
    if (isHotBlock(&BB, &BFI))
      return true;
  return false;
}

/// Returns true if the function only contains cold code. This means that
/// the function entry and blocks are all cold, and (in the case of Sample PGO)
/// the total call edge count is cold.
/// If it returns false, it either means it is not cold or it is unknown
/// (for example, no profile data is available).
bool ProfileSummaryInfo::isFunctionColdInCallGraph(
    const Function *F, BlockFrequencyInfo &BFI) const {
  if (!F || !hasProfileSummary())
    return false;
  if (auto FunctionCount = F->getEntryCount())
    if (!isColdCount(FunctionCount.getCount()))
      return false;

  if (hasSampleProfile()) {
    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(cast<CallBase>(I), nullptr))
            TotalCallCount += CallCount.getValue();
    if (!isColdCount(TotalCallCount))
      return false;
  }
  for (const auto &BB : *F)
    if (!isColdBlock(&BB, &BFI))
      return false;
  return true;
}

bool ProfileSummaryInfo::isFunctionHotnessUnknown(const Function &F) const {
  assert(hasPartialSampleProfile() && "Expect partial sample profile");
  return !F.getEntryCount().hasValue();
}

template <bool isHot>
bool ProfileSummaryInfo::isFunctionHotOrColdInCallGraphNthPercentile(
    int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const {
  if (!F || !hasProfileSummary())
    return false;
  if (auto FunctionCount = F->getEntryCount()) {
    if (isHot &&
        isHotCountNthPercentile(PercentileCutoff, FunctionCount.getCount()))
      return true;
    if (!isHot &&
        !isColdCountNthPercentile(PercentileCutoff, FunctionCount.getCount()))
      return false;
  }
  if (hasSampleProfile()) {
    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(cast<CallBase>(I), nullptr))
            TotalCallCount += CallCount.getValue();
    if (isHot && isHotCountNthPercentile(PercentileCutoff, TotalCallCount))
      return true;
    if (!isHot && !isColdCountNthPercentile(PercentileCutoff, TotalCallCount))
      return false;
  }
  for (const auto &BB : *F) {
    if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &BFI))
      return true;
    if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &BFI))
      return false;
  }
  return !isHot;
}

// Like isFunctionHotInCallGraph but for a given cutoff.
bool ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile(
    int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const {
  return isFunctionHotOrColdInCallGraphNthPercentile<true>(
      PercentileCutoff, F, BFI);
}

bool ProfileSummaryInfo::isFunctionColdInCallGraphNthPercentile(
    int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const {
  return isFunctionHotOrColdInCallGraphNthPercentile<false>(
      PercentileCutoff, F, BFI);
}

/// 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) const {
  if (!F)
    return false;
  if (F->hasFnAttribute(Attribute::Cold))
    return true;
  if (!hasProfileSummary())
    return false;
  auto FunctionCount = F->getEntryCount();
  // FIXME: The heuristic used below for determining coldness is based on
  // preliminary SPEC tuning for inliner. This will eventually be a
  // convenience method that calls isHotCount.
  return FunctionCount && isColdCount(FunctionCount.getCount());
}

/// Compute the hot and cold thresholds.
void ProfileSummaryInfo::computeThresholds() {
  auto &DetailedSummary = Summary->getDetailedSummary();
  auto &HotEntry = ProfileSummaryBuilder::getEntryForPercentile(
      DetailedSummary, ProfileSummaryCutoffHot);
  HotCountThreshold = HotEntry.MinCount;
  if (ProfileSummaryHotCount.getNumOccurrences() > 0)
    HotCountThreshold = ProfileSummaryHotCount;
  auto &ColdEntry = ProfileSummaryBuilder::getEntryForPercentile(
      DetailedSummary, ProfileSummaryCutoffCold);
  ColdCountThreshold = ColdEntry.MinCount;
  if (ProfileSummaryColdCount.getNumOccurrences() > 0)
    ColdCountThreshold = ProfileSummaryColdCount;
  assert(ColdCountThreshold <= HotCountThreshold &&
         "Cold count threshold cannot exceed hot count threshold!");
  if (!hasPartialSampleProfile() || !ScalePartialSampleProfileWorkingSetSize) {
    HasHugeWorkingSetSize =
        HotEntry.NumCounts > ProfileSummaryHugeWorkingSetSizeThreshold;
    HasLargeWorkingSetSize =
        HotEntry.NumCounts > ProfileSummaryLargeWorkingSetSizeThreshold;
  } else {
    // Scale the working set size of the partial sample profile to reflect the
    // size of the program being compiled.
    double PartialProfileRatio = Summary->getPartialProfileRatio();
    uint64_t ScaledHotEntryNumCounts =
        static_cast<uint64_t>(HotEntry.NumCounts * PartialProfileRatio *
                              PartialSampleProfileWorkingSetSizeScaleFactor);
    HasHugeWorkingSetSize =
        ScaledHotEntryNumCounts > ProfileSummaryHugeWorkingSetSizeThreshold;
    HasLargeWorkingSetSize =
        ScaledHotEntryNumCounts > ProfileSummaryLargeWorkingSetSizeThreshold;
  }
}

Optional<uint64_t>
ProfileSummaryInfo::computeThreshold(int PercentileCutoff) const {
  if (!hasProfileSummary())
    return None;
  auto iter = ThresholdCache.find(PercentileCutoff);
  if (iter != ThresholdCache.end()) {
    return iter->second;
  }
  auto &DetailedSummary = Summary->getDetailedSummary();
  auto &Entry = ProfileSummaryBuilder::getEntryForPercentile(DetailedSummary,
                                                             PercentileCutoff);
  uint64_t CountThreshold = Entry.MinCount;
  ThresholdCache[PercentileCutoff] = CountThreshold;
  return CountThreshold;
}

bool ProfileSummaryInfo::hasHugeWorkingSetSize() const {
  return HasHugeWorkingSetSize && HasHugeWorkingSetSize.getValue();
}

bool ProfileSummaryInfo::hasLargeWorkingSetSize() const {
  return HasLargeWorkingSetSize && HasLargeWorkingSetSize.getValue();
}

bool ProfileSummaryInfo::isHotCount(uint64_t C) const {
  return HotCountThreshold && C >= HotCountThreshold.getValue();
}

bool ProfileSummaryInfo::isColdCount(uint64_t C) const {
  return ColdCountThreshold && C <= ColdCountThreshold.getValue();
}

template <bool isHot>
bool ProfileSummaryInfo::isHotOrColdCountNthPercentile(int PercentileCutoff,
                                                       uint64_t C) const {
  auto CountThreshold = computeThreshold(PercentileCutoff);
  if (isHot)
    return CountThreshold && C >= CountThreshold.getValue();
  else
    return CountThreshold && C <= CountThreshold.getValue();
}

bool ProfileSummaryInfo::isHotCountNthPercentile(int PercentileCutoff,
                                                 uint64_t C) const {
  return isHotOrColdCountNthPercentile<true>(PercentileCutoff, C);
}

bool ProfileSummaryInfo::isColdCountNthPercentile(int PercentileCutoff,
                                                  uint64_t C) const {
  return isHotOrColdCountNthPercentile<false>(PercentileCutoff, C);
}

uint64_t ProfileSummaryInfo::getOrCompHotCountThreshold() const {
  return HotCountThreshold ? HotCountThreshold.getValue() : UINT64_MAX;
}

uint64_t ProfileSummaryInfo::getOrCompColdCountThreshold() const {
  return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
}

bool ProfileSummaryInfo::isHotBlock(const BasicBlock *BB,
                                    BlockFrequencyInfo *BFI) const {
  auto Count = BFI->getBlockProfileCount(BB);
  return Count && isHotCount(*Count);
}

bool ProfileSummaryInfo::isColdBlock(const BasicBlock *BB,
                                     BlockFrequencyInfo *BFI) const {
  auto Count = BFI->getBlockProfileCount(BB);
  return Count && isColdCount(*Count);
}

template <bool isHot>
bool ProfileSummaryInfo::isHotOrColdBlockNthPercentile(
    int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI) const {
  auto Count = BFI->getBlockProfileCount(BB);
  if (isHot)
    return Count && isHotCountNthPercentile(PercentileCutoff, *Count);
  else
    return Count && isColdCountNthPercentile(PercentileCutoff, *Count);
}

bool ProfileSummaryInfo::isHotBlockNthPercentile(
    int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI) const {
  return isHotOrColdBlockNthPercentile<true>(PercentileCutoff, BB, BFI);
}

bool ProfileSummaryInfo::isColdBlockNthPercentile(
    int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI) const {
  return isHotOrColdBlockNthPercentile<false>(PercentileCutoff, BB, BFI);
}

bool ProfileSummaryInfo::isHotCallSite(const CallBase &CB,
                                       BlockFrequencyInfo *BFI) const {
  auto C = getProfileCount(CB, BFI);
  return C && isHotCount(*C);
}

bool ProfileSummaryInfo::isColdCallSite(const CallBase &CB,
                                        BlockFrequencyInfo *BFI) const {
  auto C = getProfileCount(CB, BFI);
  if (C)
    return isColdCount(*C);

  // In SamplePGO, if the caller has been sampled, and there is no profile
  // annotated on the callsite, we consider the callsite as cold.
  return hasSampleProfile() && CB.getCaller()->hasProfileData();
}

bool ProfileSummaryInfo::hasPartialSampleProfile() const {
  return hasProfileSummary() &&
         Summary->getKind() == ProfileSummary::PSK_Sample &&
         (PartialProfile || Summary->isPartialProfile());
}

INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info",
                "Profile summary info", false, true)

ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass()
    : ImmutablePass(ID) {
  initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
}

bool ProfileSummaryInfoWrapperPass::doInitialization(Module &M) {
  PSI.reset(new ProfileSummaryInfo(M));
  return false;
}

bool ProfileSummaryInfoWrapperPass::doFinalization(Module &M) {
  PSI.reset();
  return false;
}

AnalysisKey ProfileSummaryAnalysis::Key;
ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M,
                                               ModuleAnalysisManager &) {
  return ProfileSummaryInfo(M);
}

PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M,
                                                 ModuleAnalysisManager &AM) {
  ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);

  OS << "Functions in " << M.getName() << " with hot/cold annotations: \n";
  for (auto &F : M) {
    OS << F.getName();
    if (PSI.isFunctionEntryHot(&F))
      OS << " :hot entry ";
    else if (PSI.isFunctionEntryCold(&F))
      OS << " :cold entry ";
    OS << "\n";
  }
  return PreservedAnalyses::all();
}

char ProfileSummaryInfoWrapperPass::ID = 0;
