@@ -134,6 +134,8 @@ cl::opt<bool> SupportsHotColdNew(
134
134
cl::desc(" Linking with hot/cold operator new interfaces" ));
135
135
} // namespace llvm
136
136
137
+ extern cl::opt<bool > MemProfReportHintedSizes;
138
+
137
139
namespace {
138
140
// / CRTP base for graphs built from either IR or ThinLTO summary index.
139
141
// /
@@ -172,6 +174,7 @@ class CallsiteContextGraph {
172
174
173
175
void dump () const ;
174
176
void print (raw_ostream &OS) const ;
177
+ void printTotalSizes (raw_ostream &OS) const ;
175
178
176
179
friend raw_ostream &operator <<(raw_ostream &OS,
177
180
const CallsiteContextGraph &CCG) {
@@ -439,7 +442,7 @@ class CallsiteContextGraph {
439
442
void addStackNodesForMIB (ContextNode *AllocNode,
440
443
CallStack<NodeT, IteratorT> &StackContext,
441
444
CallStack<NodeT, IteratorT> &CallsiteContext,
442
- AllocationType AllocType);
445
+ AllocationType AllocType, uint64_t TotalSize );
443
446
444
447
// / Matches all callsite metadata (or summary) to the nodes created for
445
448
// / allocation memprof MIB metadata, synthesizing new nodes to reflect any
@@ -611,6 +614,10 @@ class CallsiteContextGraph {
611
614
// / Map from each context ID to the AllocationType assigned to that context.
612
615
DenseMap<uint32_t , AllocationType> ContextIdToAllocationType;
613
616
617
+ // / Map from each contextID to the profiled aggregate allocation size,
618
+ // / optionally populated when requested (via MemProfReportHintedSizes).
619
+ DenseMap<uint32_t , uint64_t > ContextIdToTotalSize;
620
+
614
621
// / Identifies the context node created for a stack id when adding the MIB
615
622
// / contexts to the graph. This is used to locate the context nodes when
616
623
// / trying to assign the corresponding callsites with those stack ids to these
@@ -1004,18 +1011,36 @@ CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::addAllocNode(
1004
1011
return AllocNode;
1005
1012
}
1006
1013
1014
+ static std::string getAllocTypeString (uint8_t AllocTypes) {
1015
+ if (!AllocTypes)
1016
+ return " None" ;
1017
+ std::string Str;
1018
+ if (AllocTypes & (uint8_t )AllocationType::NotCold)
1019
+ Str += " NotCold" ;
1020
+ if (AllocTypes & (uint8_t )AllocationType::Cold)
1021
+ Str += " Cold" ;
1022
+ return Str;
1023
+ }
1024
+
1007
1025
template <typename DerivedCCG, typename FuncTy, typename CallTy>
1008
1026
template <class NodeT , class IteratorT >
1009
1027
void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::addStackNodesForMIB(
1010
1028
ContextNode *AllocNode, CallStack<NodeT, IteratorT> &StackContext,
1011
- CallStack<NodeT, IteratorT> &CallsiteContext, AllocationType AllocType) {
1029
+ CallStack<NodeT, IteratorT> &CallsiteContext, AllocationType AllocType,
1030
+ uint64_t TotalSize) {
1031
+ assert (!MemProfReportHintedSizes || TotalSize > 0 );
1012
1032
// Treating the hot alloc type as NotCold before the disambiguation for "hot"
1013
1033
// is done.
1014
1034
if (AllocType == AllocationType::Hot)
1015
1035
AllocType = AllocationType::NotCold;
1016
1036
1017
1037
ContextIdToAllocationType[++LastContextId] = AllocType;
1018
1038
1039
+ if (MemProfReportHintedSizes) {
1040
+ assert (TotalSize);
1041
+ ContextIdToTotalSize[LastContextId] = TotalSize;
1042
+ }
1043
+
1019
1044
// Update alloc type and context ids for this MIB.
1020
1045
AllocNode->AllocTypes |= (uint8_t )AllocType;
1021
1046
@@ -1060,6 +1085,10 @@ CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::duplicateContextIds(
1060
1085
assert (ContextIdToAllocationType.count (OldId));
1061
1086
// The new context has the same allocation type as original.
1062
1087
ContextIdToAllocationType[LastContextId] = ContextIdToAllocationType[OldId];
1088
+ // For now set this to 0 so we don't duplicate sizes. Not clear how to divvy
1089
+ // up the size. Assume that if we are able to duplicate context ids that we
1090
+ // will be able to disambiguate all copies.
1091
+ ContextIdToTotalSize[LastContextId] = 0 ;
1063
1092
}
1064
1093
return NewContextIds;
1065
1094
}
@@ -1663,7 +1692,7 @@ ModuleCallsiteContextGraph::ModuleCallsiteContextGraph(
1663
1692
CallStack<MDNode, MDNode::op_iterator> StackContext (StackNode);
1664
1693
addStackNodesForMIB<MDNode, MDNode::op_iterator>(
1665
1694
AllocNode, StackContext, CallsiteContext,
1666
- getMIBAllocType (MIBMD));
1695
+ getMIBAllocType (MIBMD), getMIBTotalSize (MIBMD) );
1667
1696
}
1668
1697
assert (AllocNode->AllocTypes != (uint8_t )AllocationType::None);
1669
1698
// Memprof and callsite metadata on memory allocations no longer
@@ -1735,12 +1764,20 @@ IndexCallsiteContextGraph::IndexCallsiteContextGraph(
1735
1764
// stack ids on the allocation call during ModuleSummaryAnalysis.
1736
1765
CallStack<MIBInfo, SmallVector<unsigned >::const_iterator>
1737
1766
EmptyContext;
1767
+ unsigned I = 0 ;
1768
+ assert (!MemProfReportHintedSizes ||
1769
+ AN.TotalSizes .size () == AN.MIBs .size ());
1738
1770
// Now add all of the MIBs and their stack nodes.
1739
1771
for (auto &MIB : AN.MIBs ) {
1740
1772
CallStack<MIBInfo, SmallVector<unsigned >::const_iterator>
1741
1773
StackContext (&MIB);
1774
+ uint64_t TotalSize = 0 ;
1775
+ if (MemProfReportHintedSizes)
1776
+ TotalSize = AN.TotalSizes [I];
1742
1777
addStackNodesForMIB<MIBInfo, SmallVector<unsigned >::const_iterator>(
1743
- AllocNode, StackContext, EmptyContext, MIB.AllocType );
1778
+ AllocNode, StackContext, EmptyContext, MIB.AllocType ,
1779
+ TotalSize);
1780
+ I++;
1744
1781
}
1745
1782
assert (AllocNode->AllocTypes != (uint8_t )AllocationType::None);
1746
1783
// Initialize version 0 on the summary alloc node to the current alloc
@@ -2171,17 +2208,6 @@ bool IndexCallsiteContextGraph::calleeMatchesFunc(
2171
2208
return true ;
2172
2209
}
2173
2210
2174
- static std::string getAllocTypeString (uint8_t AllocTypes) {
2175
- if (!AllocTypes)
2176
- return " None" ;
2177
- std::string Str;
2178
- if (AllocTypes & (uint8_t )AllocationType::NotCold)
2179
- Str += " NotCold" ;
2180
- if (AllocTypes & (uint8_t )AllocationType::Cold)
2181
- Str += " Cold" ;
2182
- return Str;
2183
- }
2184
-
2185
2211
template <typename DerivedCCG, typename FuncTy, typename CallTy>
2186
2212
void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::dump()
2187
2213
const {
@@ -2261,6 +2287,30 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::print(
2261
2287
}
2262
2288
}
2263
2289
2290
+ template <typename DerivedCCG, typename FuncTy, typename CallTy>
2291
+ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::printTotalSizes(
2292
+ raw_ostream &OS) const {
2293
+ using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
2294
+ for (const auto Node : nodes<GraphType>(this )) {
2295
+ if (Node->isRemoved ())
2296
+ continue ;
2297
+ if (!Node->IsAllocation )
2298
+ continue ;
2299
+ DenseSet<uint32_t > ContextIds = Node->getContextIds ();
2300
+ std::vector<uint32_t > SortedIds (ContextIds.begin (), ContextIds.end ());
2301
+ std::sort (SortedIds.begin (), SortedIds.end ());
2302
+ for (auto Id : SortedIds) {
2303
+ auto SizeI = ContextIdToTotalSize.find (Id);
2304
+ assert (SizeI != ContextIdToTotalSize.end ());
2305
+ auto TypeI = ContextIdToAllocationType.find (Id);
2306
+ assert (TypeI != ContextIdToAllocationType.end ());
2307
+ OS << getAllocTypeString ((uint8_t )TypeI->second ) << " context " << Id
2308
+ << " with total size " << SizeI->second << " is "
2309
+ << getAllocTypeString (Node->AllocTypes ) << " after cloning\n " ;
2310
+ }
2311
+ }
2312
+ }
2313
+
2264
2314
template <typename DerivedCCG, typename FuncTy, typename CallTy>
2265
2315
void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::check() const {
2266
2316
using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
@@ -3797,6 +3847,9 @@ bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::process() {
3797
3847
if (ExportToDot)
3798
3848
exportToDot (" clonefuncassign" );
3799
3849
3850
+ if (MemProfReportHintedSizes)
3851
+ printTotalSizes (errs ());
3852
+
3800
3853
return Changed;
3801
3854
}
3802
3855
0 commit comments