1343171Sdim//==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==//
2343171Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343171Sdim//
7343171Sdim//===----------------------------------------------------------------------===//
8343171Sdim//
9343171Sdim// This file implements optimizations that are based on the module summaries.
10343171Sdim// These optimizations are performed during the thinlink phase of the
11343171Sdim// compilation.
12343171Sdim//
13343171Sdim//===----------------------------------------------------------------------===//
14343171Sdim
15343171Sdim#include "llvm/LTO/SummaryBasedOptimizations.h"
16343171Sdim#include "llvm/Analysis/SyntheticCountsUtils.h"
17343171Sdim#include "llvm/IR/ModuleSummaryIndex.h"
18360784Sdim#include "llvm/Support/CommandLine.h"
19343171Sdim
20343171Sdimusing namespace llvm;
21343171Sdim
22360784Sdimstatic cl::opt<bool> ThinLTOSynthesizeEntryCounts(
23343171Sdim    "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden,
24343171Sdim    cl::desc("Synthesize entry counts based on the summary"));
25343171Sdim
26343171Sdimextern cl::opt<int> InitialSyntheticCount;
27343171Sdim
28343171Sdimstatic void initializeCounts(ModuleSummaryIndex &Index) {
29343171Sdim  auto Root = Index.calculateCallGraphRoot();
30343171Sdim  // Root is a fake node. All its successors are the actual roots of the
31343171Sdim  // callgraph.
32343171Sdim  // FIXME: This initializes the entry counts of only the root nodes. This makes
33343171Sdim  // sense when compiling a binary with ThinLTO, but for libraries any of the
34343171Sdim  // non-root nodes could be called from outside.
35343171Sdim  for (auto &C : Root.calls()) {
36343171Sdim    auto &V = C.first;
37343171Sdim    for (auto &GVS : V.getSummaryList()) {
38343171Sdim      auto S = GVS.get()->getBaseObject();
39343171Sdim      auto *F = cast<FunctionSummary>(S);
40343171Sdim      F->setEntryCount(InitialSyntheticCount);
41343171Sdim    }
42343171Sdim  }
43343171Sdim}
44343171Sdim
45343171Sdimvoid llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) {
46343171Sdim  if (!ThinLTOSynthesizeEntryCounts)
47343171Sdim    return;
48343171Sdim
49343171Sdim  using Scaled64 = ScaledNumber<uint64_t>;
50343171Sdim  initializeCounts(Index);
51343171Sdim  auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) {
52343171Sdim    return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift);
53343171Sdim  };
54343171Sdim  auto GetEntryCount = [](ValueInfo V) {
55343171Sdim    if (V.getSummaryList().size()) {
56343171Sdim      auto S = V.getSummaryList().front().get()->getBaseObject();
57343171Sdim      auto *F = cast<FunctionSummary>(S);
58343171Sdim      return F->entryCount();
59343171Sdim    } else {
60343171Sdim      return UINT64_C(0);
61343171Sdim    }
62343171Sdim  };
63343171Sdim  auto AddToEntryCount = [](ValueInfo V, Scaled64 New) {
64343171Sdim    if (!V.getSummaryList().size())
65343171Sdim      return;
66343171Sdim    for (auto &GVS : V.getSummaryList()) {
67343171Sdim      auto S = GVS.get()->getBaseObject();
68343171Sdim      auto *F = cast<FunctionSummary>(S);
69343171Sdim      F->setEntryCount(
70343171Sdim          SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>()));
71343171Sdim    }
72343171Sdim  };
73343171Sdim
74343171Sdim  auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) {
75343171Sdim    auto RelFreq = GetCallSiteRelFreq(Edge);
76343171Sdim    Scaled64 EC(GetEntryCount(V), 0);
77343171Sdim    return RelFreq * EC;
78343171Sdim  };
79343171Sdim  // After initializing the counts in initializeCounts above, the counts have to
80343171Sdim  // be propagated across the combined callgraph.
81343171Sdim  // SyntheticCountsUtils::propagate takes care of this propagation on any
82343171Sdim  // callgraph that specialized GraphTraits.
83343171Sdim  SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount,
84343171Sdim                                                        AddToEntryCount);
85343171Sdim  Index.setHasSyntheticEntryCounts();
86343171Sdim}
87