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