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