//===-- ProfileGenerator.cpp - Profile Generator  ---------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "ProfileGenerator.h"

static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
                                           cl::Required,
                                           cl::desc("Output profile file"));
static cl::alias OutputA("o", cl::desc("Alias for --output"),
                         cl::aliasopt(OutputFilename));

static cl::opt<SampleProfileFormat> OutputFormat(
    "format", cl::desc("Format of output profile"), cl::init(SPF_Text),
    cl::values(
        clEnumValN(SPF_Binary, "binary", "Binary encoding (default)"),
        clEnumValN(SPF_Compact_Binary, "compbinary", "Compact binary encoding"),
        clEnumValN(SPF_Ext_Binary, "extbinary", "Extensible binary encoding"),
        clEnumValN(SPF_Text, "text", "Text encoding"),
        clEnumValN(SPF_GCC, "gcc",
                   "GCC encoding (only meaningful for -sample)")));

static cl::opt<int32_t, true> RecursionCompression(
    "compress-recursion",
    cl::desc("Compressing recursion by deduplicating adjacent frame "
             "sequences up to the specified size. -1 means no size limit."),
    cl::Hidden,
    cl::location(llvm::sampleprof::CSProfileGenerator::MaxCompressionSize));

static cl::opt<uint64_t> CSProfColdThres(
    "csprof-cold-thres", cl::init(100), cl::ZeroOrMore,
    cl::desc("Specify the total samples threshold for a context profile to "
             "be considered cold, any cold profiles will be merged into "
             "context-less base profiles"));

static cl::opt<bool> CSProfKeepCold(
    "csprof-keep-cold", cl::init(false), cl::ZeroOrMore,
    cl::desc("This works together with --csprof-cold-thres. If the total count "
             "of the profile after all merge is done is still smaller than the "
             "csprof-cold-thres, it will be trimmed unless csprof-keep-cold "
             "flag is specified."));

using namespace llvm;
using namespace sampleprof;

namespace llvm {
namespace sampleprof {

// Initialize the MaxCompressionSize to -1 which means no size limit
int32_t CSProfileGenerator::MaxCompressionSize = -1;

static bool
usePseudoProbes(const BinarySampleCounterMap &BinarySampleCounters) {
  return BinarySampleCounters.size() &&
         BinarySampleCounters.begin()->first->usePseudoProbes();
}

std::unique_ptr<ProfileGenerator>
ProfileGenerator::create(const BinarySampleCounterMap &BinarySampleCounters,
                         enum PerfScriptType SampleType) {
  std::unique_ptr<ProfileGenerator> ProfileGenerator;
  if (SampleType == PERF_LBR_STACK) {
    if (usePseudoProbes(BinarySampleCounters)) {
      ProfileGenerator.reset(
          new PseudoProbeCSProfileGenerator(BinarySampleCounters));
    } else {
      ProfileGenerator.reset(new CSProfileGenerator(BinarySampleCounters));
    }
  } else {
    // TODO:
    llvm_unreachable("Unsupported perfscript!");
  }

  return ProfileGenerator;
}

void ProfileGenerator::write(std::unique_ptr<SampleProfileWriter> Writer,
                             StringMap<FunctionSamples> &ProfileMap) {
  Writer->write(ProfileMap);
}

void ProfileGenerator::write() {
  auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
  if (std::error_code EC = WriterOrErr.getError())
    exitWithError(EC, OutputFilename);
  write(std::move(WriterOrErr.get()), ProfileMap);
}

void ProfileGenerator::findDisjointRanges(RangeSample &DisjointRanges,
                                          const RangeSample &Ranges) {

  /*
  Regions may overlap with each other. Using the boundary info, find all
  disjoint ranges and their sample count. BoundaryPoint contains the count
  multiple samples begin/end at this points.

  |<--100-->|           Sample1
  |<------200------>|   Sample2
  A         B       C

  In the example above,
  Sample1 begins at A, ends at B, its value is 100.
  Sample2 beings at A, ends at C, its value is 200.
  For A, BeginCount is the sum of sample begins at A, which is 300 and no
  samples ends at A, so EndCount is 0.
  Then boundary points A, B, and C with begin/end counts are:
  A: (300, 0)
  B: (0, 100)
  C: (0, 200)
  */
  struct BoundaryPoint {
    // Sum of sample counts beginning at this point
    uint64_t BeginCount;
    // Sum of sample counts ending at this point
    uint64_t EndCount;

    BoundaryPoint() : BeginCount(0), EndCount(0){};

    void addBeginCount(uint64_t Count) { BeginCount += Count; }

    void addEndCount(uint64_t Count) { EndCount += Count; }
  };

  /*
  For the above example. With boundary points, follwing logic finds two
  disjoint region of

  [A,B]:   300
  [B+1,C]: 200

  If there is a boundary point that both begin and end, the point itself
  becomes a separate disjoint region. For example, if we have original
  ranges of

  |<--- 100 --->|
                |<--- 200 --->|
  A             B             C

  there are three boundary points with their begin/end counts of

  A: (100, 0)
  B: (200, 100)
  C: (0, 200)

  the disjoint ranges would be

  [A, B-1]: 100
  [B, B]:   300
  [B+1, C]: 200.
  */
  std::map<uint64_t, BoundaryPoint> Boundaries;

  for (auto Item : Ranges) {
    uint64_t Begin = Item.first.first;
    uint64_t End = Item.first.second;
    uint64_t Count = Item.second;
    if (Boundaries.find(Begin) == Boundaries.end())
      Boundaries[Begin] = BoundaryPoint();
    Boundaries[Begin].addBeginCount(Count);

    if (Boundaries.find(End) == Boundaries.end())
      Boundaries[End] = BoundaryPoint();
    Boundaries[End].addEndCount(Count);
  }

  uint64_t BeginAddress = 0;
  int Count = 0;
  for (auto Item : Boundaries) {
    uint64_t Address = Item.first;
    BoundaryPoint &Point = Item.second;
    if (Point.BeginCount) {
      if (BeginAddress)
        DisjointRanges[{BeginAddress, Address - 1}] = Count;
      Count += Point.BeginCount;
      BeginAddress = Address;
    }
    if (Point.EndCount) {
      assert(BeginAddress && "First boundary point cannot be 'end' point");
      DisjointRanges[{BeginAddress, Address}] = Count;
      Count -= Point.EndCount;
      BeginAddress = Address + 1;
    }
  }
}

FunctionSamples &
CSProfileGenerator::getFunctionProfileForContext(StringRef ContextStr) {
  auto Ret = ProfileMap.try_emplace(ContextStr, FunctionSamples());
  if (Ret.second) {
    SampleContext FContext(Ret.first->first(), RawContext);
    FunctionSamples &FProfile = Ret.first->second;
    FProfile.setContext(FContext);
  }
  return Ret.first->second;
}

void CSProfileGenerator::updateBodySamplesforFunctionProfile(
    FunctionSamples &FunctionProfile, const FrameLocation &LeafLoc,
    uint64_t Count) {
  // Filter out invalid negative(int type) lineOffset
  if (LeafLoc.second.LineOffset & 0x80000000)
    return;
  // Use the maximum count of samples with same line location
  ErrorOr<uint64_t> R = FunctionProfile.findSamplesAt(
      LeafLoc.second.LineOffset, LeafLoc.second.Discriminator);
  uint64_t PreviousCount = R ? R.get() : 0;
  if (PreviousCount < Count) {
    FunctionProfile.addBodySamples(LeafLoc.second.LineOffset,
                                   LeafLoc.second.Discriminator,
                                   Count - PreviousCount);
  }
}

void CSProfileGenerator::populateFunctionBodySamples(
    FunctionSamples &FunctionProfile, const RangeSample &RangeCounter,
    ProfiledBinary *Binary) {
  // Compute disjoint ranges first, so we can use MAX
  // for calculating count for each location.
  RangeSample Ranges;
  findDisjointRanges(Ranges, RangeCounter);
  for (auto Range : Ranges) {
    uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
    uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
    uint64_t Count = Range.second;
    // Disjoint ranges have introduce zero-filled gap that
    // doesn't belong to current context, filter them out.
    if (Count == 0)
      continue;

    InstructionPointer IP(Binary, RangeBegin, true);

    // Disjoint ranges may have range in the middle of two instr,
    // e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
    // can be Addr1+1 to Addr2-1. We should ignore such range.
    if (IP.Address > RangeEnd)
      continue;

    while (IP.Address <= RangeEnd) {
      uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
      auto LeafLoc = Binary->getInlineLeafFrameLoc(Offset);
      if (LeafLoc.hasValue()) {
        // Recording body sample for this specific context
        updateBodySamplesforFunctionProfile(FunctionProfile, *LeafLoc, Count);
      }
      // Accumulate total sample count even it's a line with invalid debug info
      FunctionProfile.addTotalSamples(Count);
      // Move to next IP within the range
      IP.advance();
    }
  }
}

void CSProfileGenerator::populateFunctionBoundarySamples(
    StringRef ContextId, FunctionSamples &FunctionProfile,
    const BranchSample &BranchCounters, ProfiledBinary *Binary) {

  for (auto Entry : BranchCounters) {
    uint64_t SourceOffset = Entry.first.first;
    uint64_t TargetOffset = Entry.first.second;
    uint64_t Count = Entry.second;
    // Get the callee name by branch target if it's a call branch
    StringRef CalleeName = FunctionSamples::getCanonicalFnName(
        Binary->getFuncFromStartOffset(TargetOffset));
    if (CalleeName.size() == 0)
      continue;

    // Record called target sample and its count
    auto LeafLoc = Binary->getInlineLeafFrameLoc(SourceOffset);
    if (!LeafLoc.hasValue())
      continue;
    FunctionProfile.addCalledTargetSamples(LeafLoc->second.LineOffset,
                                           LeafLoc->second.Discriminator,
                                           CalleeName, Count);

    // Record head sample for called target(callee)
    std::ostringstream OCalleeCtxStr;
    if (ContextId.find(" @ ") != StringRef::npos) {
      OCalleeCtxStr << ContextId.rsplit(" @ ").first.str();
      OCalleeCtxStr << " @ ";
    }
    OCalleeCtxStr << getCallSite(*LeafLoc) << " @ " << CalleeName.str();

    FunctionSamples &CalleeProfile =
        getFunctionProfileForContext(OCalleeCtxStr.str());
    assert(Count != 0 && "Unexpected zero weight branch");
    CalleeProfile.addHeadSamples(Count);
  }
}

static FrameLocation getCallerContext(StringRef CalleeContext,
                                      StringRef &CallerNameWithContext) {
  StringRef CallerContext = CalleeContext.rsplit(" @ ").first;
  CallerNameWithContext = CallerContext.rsplit(':').first;
  auto ContextSplit = CallerContext.rsplit(" @ ");
  StringRef CallerFrameStr = ContextSplit.second.size() == 0
                                 ? ContextSplit.first
                                 : ContextSplit.second;
  FrameLocation LeafFrameLoc = {"", {0, 0}};
  StringRef Funcname;
  SampleContext::decodeContextString(CallerFrameStr, Funcname,
                                     LeafFrameLoc.second);
  LeafFrameLoc.first = Funcname.str();
  return LeafFrameLoc;
}

void CSProfileGenerator::populateInferredFunctionSamples() {
  for (const auto &Item : ProfileMap) {
    const StringRef CalleeContext = Item.first();
    const FunctionSamples &CalleeProfile = Item.second;

    // If we already have head sample counts, we must have value profile
    // for call sites added already. Skip to avoid double counting.
    if (CalleeProfile.getHeadSamples())
      continue;
    // If we don't have context, nothing to do for caller's call site.
    // This could happen for entry point function.
    if (CalleeContext.find(" @ ") == StringRef::npos)
      continue;

    // Infer Caller's frame loc and context ID through string splitting
    StringRef CallerContextId;
    FrameLocation &&CallerLeafFrameLoc =
        getCallerContext(CalleeContext, CallerContextId);

    // It's possible that we haven't seen any sample directly in the caller,
    // in which case CallerProfile will not exist. But we can't modify
    // ProfileMap while iterating it.
    // TODO: created function profile for those callers too
    if (ProfileMap.find(CallerContextId) == ProfileMap.end())
      continue;
    FunctionSamples &CallerProfile = ProfileMap[CallerContextId];

    // Since we don't have call count for inlined functions, we
    // estimate it from inlinee's profile using entry body sample.
    uint64_t EstimatedCallCount = CalleeProfile.getEntrySamples();
    // If we don't have samples with location, use 1 to indicate live.
    if (!EstimatedCallCount && !CalleeProfile.getBodySamples().size())
      EstimatedCallCount = 1;
    CallerProfile.addCalledTargetSamples(
        CallerLeafFrameLoc.second.LineOffset,
        CallerLeafFrameLoc.second.Discriminator,
        CalleeProfile.getContext().getNameWithoutContext(), EstimatedCallCount);
    CallerProfile.addBodySamples(CallerLeafFrameLoc.second.LineOffset,
                                 CallerLeafFrameLoc.second.Discriminator,
                                 EstimatedCallCount);
    CallerProfile.addTotalSamples(EstimatedCallCount);
  }
}

void CSProfileGenerator::mergeAndTrimColdProfile(
    StringMap<FunctionSamples> &ProfileMap) {
  // Nothing to merge if sample threshold is zero
  if (!CSProfColdThres)
    return;

  // Filter the cold profiles from ProfileMap and move them into a tmp
  // container
  std::vector<std::pair<StringRef, const FunctionSamples *>> ToRemoveVec;
  for (const auto &I : ProfileMap) {
    const FunctionSamples &FunctionProfile = I.second;
    if (FunctionProfile.getTotalSamples() >= CSProfColdThres)
      continue;
    ToRemoveVec.emplace_back(I.getKey(), &I.second);
  }

  // Remove the code profile from ProfileMap and merge them into BaseProileMap
  StringMap<FunctionSamples> BaseProfileMap;
  for (const auto &I : ToRemoveVec) {
    auto Ret = BaseProfileMap.try_emplace(
        I.second->getContext().getNameWithoutContext(), FunctionSamples());
    FunctionSamples &BaseProfile = Ret.first->second;
    BaseProfile.merge(*I.second);
    ProfileMap.erase(I.first);
  }

  // Merge the base profiles into ProfileMap;
  for (const auto &I : BaseProfileMap) {
    // Filter the cold base profile
    if (!CSProfKeepCold && I.second.getTotalSamples() < CSProfColdThres &&
        ProfileMap.find(I.getKey()) == ProfileMap.end())
      continue;
    // Merge the profile if the original profile exists, otherwise just insert
    // as a new profile
    FunctionSamples &OrigProfile = getFunctionProfileForContext(I.getKey());
    OrigProfile.merge(I.second);
  }
}

void CSProfileGenerator::write(std::unique_ptr<SampleProfileWriter> Writer,
                               StringMap<FunctionSamples> &ProfileMap) {
  mergeAndTrimColdProfile(ProfileMap);
  // Add bracket for context key to support different profile binary format
  StringMap<FunctionSamples> CxtWithBracketPMap;
  for (const auto &Item : ProfileMap) {
    std::string ContextWithBracket = "[" + Item.first().str() + "]";
    auto Ret = CxtWithBracketPMap.try_emplace(ContextWithBracket, Item.second);
    assert(Ret.second && "Must be a unique context");
    SampleContext FContext(Ret.first->first(), RawContext);
    FunctionSamples &FProfile = Ret.first->second;
    FProfile.setName(FContext.getNameWithContext(true));
    FProfile.setContext(FContext);
  }
  Writer->write(CxtWithBracketPMap);
}

// Helper function to extract context prefix string stack
// Extract context stack for reusing, leaf context stack will
// be added compressed while looking up function profile
static void
extractPrefixContextStack(SmallVectorImpl<std::string> &ContextStrStack,
                          const SmallVectorImpl<const PseudoProbe *> &Probes,
                          ProfiledBinary *Binary) {
  for (const auto *P : Probes) {
    Binary->getInlineContextForProbe(P, ContextStrStack, true);
  }
}

void PseudoProbeCSProfileGenerator::generateProfile() {
  // Enable pseudo probe functionalities in SampleProf
  FunctionSamples::ProfileIsProbeBased = true;
  for (const auto &BI : BinarySampleCounters) {
    ProfiledBinary *Binary = BI.first;
    for (const auto &CI : BI.second) {
      const ProbeBasedCtxKey *CtxKey =
          dyn_cast<ProbeBasedCtxKey>(CI.first.getPtr());
      SmallVector<std::string, 16> ContextStrStack;
      extractPrefixContextStack(ContextStrStack, CtxKey->Probes, Binary);
      // Fill in function body samples from probes, also infer caller's samples
      // from callee's probe
      populateBodySamplesWithProbes(CI.second.RangeCounter, ContextStrStack,
                                    Binary);
      // Fill in boundary samples for a call probe
      populateBoundarySamplesWithProbes(CI.second.BranchCounter,
                                        ContextStrStack, Binary);
    }
  }
}

void PseudoProbeCSProfileGenerator::extractProbesFromRange(
    const RangeSample &RangeCounter, ProbeCounterMap &ProbeCounter,
    ProfiledBinary *Binary) {
  RangeSample Ranges;
  findDisjointRanges(Ranges, RangeCounter);
  for (const auto &Range : Ranges) {
    uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
    uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
    uint64_t Count = Range.second;
    // Disjoint ranges have introduce zero-filled gap that
    // doesn't belong to current context, filter them out.
    if (Count == 0)
      continue;

    InstructionPointer IP(Binary, RangeBegin, true);

    // Disjoint ranges may have range in the middle of two instr,
    // e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
    // can be Addr1+1 to Addr2-1. We should ignore such range.
    if (IP.Address > RangeEnd)
      continue;

    while (IP.Address <= RangeEnd) {
      const AddressProbesMap &Address2ProbesMap =
          Binary->getAddress2ProbesMap();
      auto It = Address2ProbesMap.find(IP.Address);
      if (It != Address2ProbesMap.end()) {
        for (const auto &Probe : It->second) {
          if (!Probe.isBlock())
            continue;
          ProbeCounter[&Probe] += Count;
        }
      }

      IP.advance();
    }
  }
}

void PseudoProbeCSProfileGenerator::populateBodySamplesWithProbes(
    const RangeSample &RangeCounter,
    SmallVectorImpl<std::string> &ContextStrStack, ProfiledBinary *Binary) {
  ProbeCounterMap ProbeCounter;
  // Extract the top frame probes by looking up each address among the range in
  // the Address2ProbeMap
  extractProbesFromRange(RangeCounter, ProbeCounter, Binary);
  for (auto PI : ProbeCounter) {
    const PseudoProbe *Probe = PI.first;
    uint64_t Count = PI.second;
    FunctionSamples &FunctionProfile =
        getFunctionProfileForLeafProbe(ContextStrStack, Probe, Binary);

    FunctionProfile.addBodySamples(Probe->Index, 0, Count);
    FunctionProfile.addTotalSamples(Count);
    if (Probe->isEntry()) {
      FunctionProfile.addHeadSamples(Count);
      // Look up for the caller's function profile
      const auto *InlinerDesc = Binary->getInlinerDescForProbe(Probe);
      if (InlinerDesc != nullptr) {
        // Since the context id will be compressed, we have to use callee's
        // context id to infer caller's context id to ensure they share the
        // same context prefix.
        StringRef CalleeContextId =
            FunctionProfile.getContext().getNameWithContext(true);
        StringRef CallerContextId;
        FrameLocation &&CallerLeafFrameLoc =
            getCallerContext(CalleeContextId, CallerContextId);
        uint64_t CallerIndex = CallerLeafFrameLoc.second.LineOffset;
        assert(CallerIndex &&
               "Inferred caller's location index shouldn't be zero!");
        FunctionSamples &CallerProfile =
            getFunctionProfileForContext(CallerContextId);
        CallerProfile.setFunctionHash(InlinerDesc->FuncHash);
        CallerProfile.addBodySamples(CallerIndex, 0, Count);
        CallerProfile.addTotalSamples(Count);
        CallerProfile.addCalledTargetSamples(
            CallerIndex, 0,
            FunctionProfile.getContext().getNameWithoutContext(), Count);
      }
    }
  }
}

void PseudoProbeCSProfileGenerator::populateBoundarySamplesWithProbes(
    const BranchSample &BranchCounter,
    SmallVectorImpl<std::string> &ContextStrStack, ProfiledBinary *Binary) {
  for (auto BI : BranchCounter) {
    uint64_t SourceOffset = BI.first.first;
    uint64_t TargetOffset = BI.first.second;
    uint64_t Count = BI.second;
    uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
    const PseudoProbe *CallProbe = Binary->getCallProbeForAddr(SourceAddress);
    if (CallProbe == nullptr)
      continue;
    FunctionSamples &FunctionProfile =
        getFunctionProfileForLeafProbe(ContextStrStack, CallProbe, Binary);
    FunctionProfile.addBodySamples(CallProbe->Index, 0, Count);
    FunctionProfile.addTotalSamples(Count);
    StringRef CalleeName = FunctionSamples::getCanonicalFnName(
        Binary->getFuncFromStartOffset(TargetOffset));
    if (CalleeName.size() == 0)
      continue;
    FunctionProfile.addCalledTargetSamples(CallProbe->Index, 0, CalleeName,
                                           Count);
  }
}

FunctionSamples &PseudoProbeCSProfileGenerator::getFunctionProfileForLeafProbe(
    SmallVectorImpl<std::string> &ContextStrStack,
    const PseudoProbeFuncDesc *LeafFuncDesc) {
  assert(ContextStrStack.size() && "Profile context must have the leaf frame");
  // Compress the context string except for the leaf frame
  std::string LeafFrame = ContextStrStack.back();
  ContextStrStack.pop_back();
  CSProfileGenerator::compressRecursionContext(ContextStrStack);

  std::ostringstream OContextStr;
  for (uint32_t I = 0; I < ContextStrStack.size(); I++) {
    if (OContextStr.str().size())
      OContextStr << " @ ";
    OContextStr << ContextStrStack[I];
  }
  // For leaf inlined context with the top frame, we should strip off the top
  // frame's probe id, like:
  // Inlined stack: [foo:1, bar:2], the ContextId will be "foo:1 @ bar"
  if (OContextStr.str().size())
    OContextStr << " @ ";
  OContextStr << StringRef(LeafFrame).split(":").first.str();

  FunctionSamples &FunctionProile =
      getFunctionProfileForContext(OContextStr.str());
  FunctionProile.setFunctionHash(LeafFuncDesc->FuncHash);
  return FunctionProile;
}

FunctionSamples &PseudoProbeCSProfileGenerator::getFunctionProfileForLeafProbe(
    SmallVectorImpl<std::string> &ContextStrStack, const PseudoProbe *LeafProbe,
    ProfiledBinary *Binary) {
  // Explicitly copy the context for appending the leaf context
  SmallVector<std::string, 16> ContextStrStackCopy(ContextStrStack.begin(),
                                                   ContextStrStack.end());
  Binary->getInlineContextForProbe(LeafProbe, ContextStrStackCopy);
  // Note that the context from probe doesn't include leaf frame,
  // hence we need to retrieve and append the leaf frame.
  const auto *FuncDesc = Binary->getFuncDescForGUID(LeafProbe->GUID);
  ContextStrStackCopy.emplace_back(FuncDesc->FuncName + ":" +
                                   Twine(LeafProbe->Index).str());
  return getFunctionProfileForLeafProbe(ContextStrStackCopy, FuncDesc);
}

} // end namespace sampleprof
} // end namespace llvm
