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