/src/llvm-project/llvm/lib/LTO/SummaryBasedOptimizations.cpp
Line | Count | Source (jump to first uncovered line) |
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(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 | 0 | static void initializeCounts(ModuleSummaryIndex &Index) { |
31 | 0 | 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 | 0 | for (auto &C : Root.calls()) { |
38 | 0 | auto &V = C.first; |
39 | 0 | for (auto &GVS : V.getSummaryList()) { |
40 | 0 | auto S = GVS.get()->getBaseObject(); |
41 | 0 | auto *F = cast<FunctionSummary>(S); |
42 | 0 | F->setEntryCount(InitialSyntheticCount); |
43 | 0 | } |
44 | 0 | } |
45 | 0 | } |
46 | | |
47 | 0 | void llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) { |
48 | 0 | if (!ThinLTOSynthesizeEntryCounts) |
49 | 0 | return; |
50 | | |
51 | 0 | using Scaled64 = ScaledNumber<uint64_t>; |
52 | 0 | initializeCounts(Index); |
53 | 0 | auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) { |
54 | 0 | return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift); |
55 | 0 | }; |
56 | 0 | auto GetEntryCount = [](ValueInfo V) { |
57 | 0 | if (V.getSummaryList().size()) { |
58 | 0 | auto S = V.getSummaryList().front()->getBaseObject(); |
59 | 0 | auto *F = cast<FunctionSummary>(S); |
60 | 0 | return F->entryCount(); |
61 | 0 | } else { |
62 | 0 | return UINT64_C(0); |
63 | 0 | } |
64 | 0 | }; |
65 | 0 | auto AddToEntryCount = [](ValueInfo V, Scaled64 New) { |
66 | 0 | if (!V.getSummaryList().size()) |
67 | 0 | return; |
68 | 0 | for (auto &GVS : V.getSummaryList()) { |
69 | 0 | auto S = GVS.get()->getBaseObject(); |
70 | 0 | auto *F = cast<FunctionSummary>(S); |
71 | 0 | F->setEntryCount( |
72 | 0 | SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>())); |
73 | 0 | } |
74 | 0 | }; |
75 | |
|
76 | 0 | auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) { |
77 | 0 | auto RelFreq = GetCallSiteRelFreq(Edge); |
78 | 0 | Scaled64 EC(GetEntryCount(V), 0); |
79 | 0 | return RelFreq * EC; |
80 | 0 | }; |
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 | 0 | SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount, |
86 | 0 | AddToEntryCount); |
87 | 0 | Index.setHasSyntheticEntryCounts(); |
88 | 0 | } |