blob: 386396bcff364f3cf0222a3f7994fd4c46023686 [file] [log] [blame]
Easwaran Ramanbdf20262018-01-09 19:39:35 +00001//===--- SyntheticCountsUtils.cpp - synthetic counts propagation utils ---===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines utilities for propagating synthetic counts.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Analysis/SyntheticCountsUtils.h"
15#include "llvm/ADT/DenseSet.h"
16#include "llvm/ADT/SCCIterator.h"
Easwaran Ramanbdf20262018-01-09 19:39:35 +000017#include "llvm/Analysis/CallGraph.h"
18#include "llvm/IR/CallSite.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/InstIterator.h"
21#include "llvm/IR/Instructions.h"
Easwaran Raman5a7056f2018-12-13 19:54:27 +000022#include "llvm/IR/ModuleSummaryIndex.h"
Easwaran Ramanbdf20262018-01-09 19:39:35 +000023
24using namespace llvm;
25
Easwaran Raman8410c372018-01-25 22:02:29 +000026// Given an SCC, propagate entry counts along the edge of the SCC nodes.
27template <typename CallGraphType>
28void SyntheticCountsUtils<CallGraphType>::propagateFromSCC(
29 const SccTy &SCC, GetRelBBFreqTy GetRelBBFreq, GetCountTy GetCount,
30 AddCountTy AddCount) {
Easwaran Ramanbdf20262018-01-09 19:39:35 +000031
Easwaran Raman5a7056f2018-12-13 19:54:27 +000032 DenseSet<NodeRef> SCCNodes;
Easwaran Raman8410c372018-01-25 22:02:29 +000033 SmallVector<std::pair<NodeRef, EdgeRef>, 8> SCCEdges, NonSCCEdges;
Easwaran Ramanbdf20262018-01-09 19:39:35 +000034
Easwaran Raman8410c372018-01-25 22:02:29 +000035 for (auto &Node : SCC)
36 SCCNodes.insert(Node);
37
38 // Partition the edges coming out of the SCC into those whose destination is
39 // in the SCC and the rest.
40 for (const auto &Node : SCCNodes) {
Easwaran Raman06a71532018-02-01 19:40:35 +000041 for (auto &E : children_edges<CallGraphType>(Node)) {
Easwaran Raman8410c372018-01-25 22:02:29 +000042 if (SCCNodes.count(CGT::edge_dest(E)))
43 SCCEdges.emplace_back(Node, E);
44 else
45 NonSCCEdges.emplace_back(Node, E);
Easwaran Ramanbdf20262018-01-09 19:39:35 +000046 }
Easwaran Raman8410c372018-01-25 22:02:29 +000047 }
Easwaran Ramanbdf20262018-01-09 19:39:35 +000048
Easwaran Raman8410c372018-01-25 22:02:29 +000049 // For nodes in the same SCC, update the counts in two steps:
50 // 1. Compute the additional count for each node by propagating the counts
51 // along all incoming edges to the node that originate from within the same
52 // SCC and summing them up.
53 // 2. Add the additional counts to the nodes in the SCC.
Easwaran Ramanbdf20262018-01-09 19:39:35 +000054 // This ensures that the order of
Easwaran Raman8410c372018-01-25 22:02:29 +000055 // traversal of nodes within the SCC doesn't affect the final result.
Easwaran Ramanbdf20262018-01-09 19:39:35 +000056
Easwaran Raman8410c372018-01-25 22:02:29 +000057 DenseMap<NodeRef, uint64_t> AdditionalCounts;
58 for (auto &E : SCCEdges) {
59 auto OptRelFreq = GetRelBBFreq(E.second);
60 if (!OptRelFreq)
61 continue;
62 Scaled64 RelFreq = OptRelFreq.getValue();
63 auto Caller = E.first;
64 auto Callee = CGT::edge_dest(E.second);
Easwaran Ramanbdf20262018-01-09 19:39:35 +000065 RelFreq *= Scaled64(GetCount(Caller), 0);
66 uint64_t AdditionalCount = RelFreq.toInt<uint64_t>();
67 AdditionalCounts[Callee] += AdditionalCount;
68 }
69
Easwaran Raman8410c372018-01-25 22:02:29 +000070 // Update the counts for the nodes in the SCC.
Easwaran Ramanbdf20262018-01-09 19:39:35 +000071 for (auto &Entry : AdditionalCounts)
Easwaran Raman8410c372018-01-25 22:02:29 +000072 AddCount(Entry.first, Entry.second);
Easwaran Ramanbdf20262018-01-09 19:39:35 +000073
Easwaran Raman8410c372018-01-25 22:02:29 +000074 // Now update the counts for nodes outside the SCC.
75 for (auto &E : NonSCCEdges) {
76 auto OptRelFreq = GetRelBBFreq(E.second);
77 if (!OptRelFreq)
78 continue;
79 Scaled64 RelFreq = OptRelFreq.getValue();
80 auto Caller = E.first;
81 auto Callee = CGT::edge_dest(E.second);
82 RelFreq *= Scaled64(GetCount(Caller), 0);
83 AddCount(Callee, RelFreq.toInt<uint64_t>());
Easwaran Ramanbdf20262018-01-09 19:39:35 +000084 }
85}
86
Easwaran Raman8410c372018-01-25 22:02:29 +000087/// Propgate synthetic entry counts on a callgraph \p CG.
Easwaran Ramanbdf20262018-01-09 19:39:35 +000088///
89/// This performs a reverse post-order traversal of the callgraph SCC. For each
Easwaran Raman8410c372018-01-25 22:02:29 +000090/// SCC, it first propagates the entry counts to the nodes within the SCC
Easwaran Ramanbdf20262018-01-09 19:39:35 +000091/// through call edges and updates them in one shot. Then the entry counts are
Easwaran Raman06a71532018-02-01 19:40:35 +000092/// propagated to nodes outside the SCC. This requires \p GraphTraits
Easwaran Raman8410c372018-01-25 22:02:29 +000093/// to have a specialization for \p CallGraphType.
Easwaran Ramanbdf20262018-01-09 19:39:35 +000094
Easwaran Raman8410c372018-01-25 22:02:29 +000095template <typename CallGraphType>
96void SyntheticCountsUtils<CallGraphType>::propagate(const CallGraphType &CG,
97 GetRelBBFreqTy GetRelBBFreq,
98 GetCountTy GetCount,
99 AddCountTy AddCount) {
100 std::vector<SccTy> SCCs;
Easwaran Ramanbdf20262018-01-09 19:39:35 +0000101
Easwaran Raman8410c372018-01-25 22:02:29 +0000102 // Collect all the SCCs.
103 for (auto I = scc_begin(CG); !I.isAtEnd(); ++I)
104 SCCs.push_back(*I);
Easwaran Ramanbdf20262018-01-09 19:39:35 +0000105
Easwaran Raman8410c372018-01-25 22:02:29 +0000106 // The callgraph-scc needs to be visited in top-down order for propagation.
107 // The scc iterator returns the scc in bottom-up order, so reverse the SCCs
108 // and call propagateFromSCC.
109 for (auto &SCC : reverse(SCCs))
110 propagateFromSCC(SCC, GetRelBBFreq, GetCount, AddCount);
Easwaran Ramanbdf20262018-01-09 19:39:35 +0000111}
Easwaran Raman8410c372018-01-25 22:02:29 +0000112
113template class llvm::SyntheticCountsUtils<const CallGraph *>;
Easwaran Raman5a7056f2018-12-13 19:54:27 +0000114template class llvm::SyntheticCountsUtils<ModuleSummaryIndex *>;