//==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==//
//
// 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 implements optimizations that are based on the module summaries.
// These optimizations are performed during the thinlink phase of the
// compilation.
//
//===----------------------------------------------------------------------===//

#include "llvm/LTO/SummaryBasedOptimizations.h"
#include "llvm/Analysis/SyntheticCountsUtils.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/Support/CommandLine.h"

using namespace llvm;

static cl::opt<bool> ThinLTOSynthesizeEntryCounts(
    "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden,
    cl::desc("Synthesize entry counts based on the summary"));

namespace llvm {
extern cl::opt<int> InitialSyntheticCount;
}

static void initializeCounts(ModuleSummaryIndex &Index) {
  auto Root = Index.calculateCallGraphRoot();
  // Root is a fake node. All its successors are the actual roots of the
  // callgraph.
  // FIXME: This initializes the entry counts of only the root nodes. This makes
  // sense when compiling a binary with ThinLTO, but for libraries any of the
  // non-root nodes could be called from outside.
  for (auto &C : Root.calls()) {
    auto &V = C.first;
    for (auto &GVS : V.getSummaryList()) {
      auto S = GVS.get()->getBaseObject();
      auto *F = cast<FunctionSummary>(S);
      F->setEntryCount(InitialSyntheticCount);
    }
  }
}

void llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) {
  if (!ThinLTOSynthesizeEntryCounts)
    return;

  using Scaled64 = ScaledNumber<uint64_t>;
  initializeCounts(Index);
  auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) {
    return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift);
  };
  auto GetEntryCount = [](ValueInfo V) {
    if (V.getSummaryList().size()) {
      auto S = V.getSummaryList().front().get()->getBaseObject();
      auto *F = cast<FunctionSummary>(S);
      return F->entryCount();
    } else {
      return UINT64_C(0);
    }
  };
  auto AddToEntryCount = [](ValueInfo V, Scaled64 New) {
    if (!V.getSummaryList().size())
      return;
    for (auto &GVS : V.getSummaryList()) {
      auto S = GVS.get()->getBaseObject();
      auto *F = cast<FunctionSummary>(S);
      F->setEntryCount(
          SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>()));
    }
  };

  auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) {
    auto RelFreq = GetCallSiteRelFreq(Edge);
    Scaled64 EC(GetEntryCount(V), 0);
    return RelFreq * EC;
  };
  // After initializing the counts in initializeCounts above, the counts have to
  // be propagated across the combined callgraph.
  // SyntheticCountsUtils::propagate takes care of this propagation on any
  // callgraph that specialized GraphTraits.
  SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount,
                                                        AddToEntryCount);
  Index.setHasSyntheticEntryCounts();
}
