1*b5893f02SDimitry Andric //==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric // The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric //
10*b5893f02SDimitry Andric // This file implements optimizations that are based on the module summaries.
11*b5893f02SDimitry Andric // These optimizations are performed during the thinlink phase of the
12*b5893f02SDimitry Andric // compilation.
13*b5893f02SDimitry Andric //
14*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
15*b5893f02SDimitry Andric
16*b5893f02SDimitry Andric #include "llvm/LTO/SummaryBasedOptimizations.h"
17*b5893f02SDimitry Andric #include "llvm/Analysis/SyntheticCountsUtils.h"
18*b5893f02SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
19*b5893f02SDimitry Andric
20*b5893f02SDimitry Andric using namespace llvm;
21*b5893f02SDimitry Andric
22*b5893f02SDimitry Andric cl::opt<bool> ThinLTOSynthesizeEntryCounts(
23*b5893f02SDimitry Andric "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden,
24*b5893f02SDimitry Andric cl::desc("Synthesize entry counts based on the summary"));
25*b5893f02SDimitry Andric
26*b5893f02SDimitry Andric extern cl::opt<int> InitialSyntheticCount;
27*b5893f02SDimitry Andric
initializeCounts(ModuleSummaryIndex & Index)28*b5893f02SDimitry Andric static void initializeCounts(ModuleSummaryIndex &Index) {
29*b5893f02SDimitry Andric auto Root = Index.calculateCallGraphRoot();
30*b5893f02SDimitry Andric // Root is a fake node. All its successors are the actual roots of the
31*b5893f02SDimitry Andric // callgraph.
32*b5893f02SDimitry Andric // FIXME: This initializes the entry counts of only the root nodes. This makes
33*b5893f02SDimitry Andric // sense when compiling a binary with ThinLTO, but for libraries any of the
34*b5893f02SDimitry Andric // non-root nodes could be called from outside.
35*b5893f02SDimitry Andric for (auto &C : Root.calls()) {
36*b5893f02SDimitry Andric auto &V = C.first;
37*b5893f02SDimitry Andric for (auto &GVS : V.getSummaryList()) {
38*b5893f02SDimitry Andric auto S = GVS.get()->getBaseObject();
39*b5893f02SDimitry Andric auto *F = cast<FunctionSummary>(S);
40*b5893f02SDimitry Andric F->setEntryCount(InitialSyntheticCount);
41*b5893f02SDimitry Andric }
42*b5893f02SDimitry Andric }
43*b5893f02SDimitry Andric }
44*b5893f02SDimitry Andric
computeSyntheticCounts(ModuleSummaryIndex & Index)45*b5893f02SDimitry Andric void llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) {
46*b5893f02SDimitry Andric if (!ThinLTOSynthesizeEntryCounts)
47*b5893f02SDimitry Andric return;
48*b5893f02SDimitry Andric
49*b5893f02SDimitry Andric using Scaled64 = ScaledNumber<uint64_t>;
50*b5893f02SDimitry Andric initializeCounts(Index);
51*b5893f02SDimitry Andric auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) {
52*b5893f02SDimitry Andric return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift);
53*b5893f02SDimitry Andric };
54*b5893f02SDimitry Andric auto GetEntryCount = [](ValueInfo V) {
55*b5893f02SDimitry Andric if (V.getSummaryList().size()) {
56*b5893f02SDimitry Andric auto S = V.getSummaryList().front().get()->getBaseObject();
57*b5893f02SDimitry Andric auto *F = cast<FunctionSummary>(S);
58*b5893f02SDimitry Andric return F->entryCount();
59*b5893f02SDimitry Andric } else {
60*b5893f02SDimitry Andric return UINT64_C(0);
61*b5893f02SDimitry Andric }
62*b5893f02SDimitry Andric };
63*b5893f02SDimitry Andric auto AddToEntryCount = [](ValueInfo V, Scaled64 New) {
64*b5893f02SDimitry Andric if (!V.getSummaryList().size())
65*b5893f02SDimitry Andric return;
66*b5893f02SDimitry Andric for (auto &GVS : V.getSummaryList()) {
67*b5893f02SDimitry Andric auto S = GVS.get()->getBaseObject();
68*b5893f02SDimitry Andric auto *F = cast<FunctionSummary>(S);
69*b5893f02SDimitry Andric F->setEntryCount(
70*b5893f02SDimitry Andric SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>()));
71*b5893f02SDimitry Andric }
72*b5893f02SDimitry Andric };
73*b5893f02SDimitry Andric
74*b5893f02SDimitry Andric auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) {
75*b5893f02SDimitry Andric auto RelFreq = GetCallSiteRelFreq(Edge);
76*b5893f02SDimitry Andric Scaled64 EC(GetEntryCount(V), 0);
77*b5893f02SDimitry Andric return RelFreq * EC;
78*b5893f02SDimitry Andric };
79*b5893f02SDimitry Andric // After initializing the counts in initializeCounts above, the counts have to
80*b5893f02SDimitry Andric // be propagated across the combined callgraph.
81*b5893f02SDimitry Andric // SyntheticCountsUtils::propagate takes care of this propagation on any
82*b5893f02SDimitry Andric // callgraph that specialized GraphTraits.
83*b5893f02SDimitry Andric SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount,
84*b5893f02SDimitry Andric AddToEntryCount);
85*b5893f02SDimitry Andric Index.setHasSyntheticEntryCounts();
86*b5893f02SDimitry Andric }
87