@@ -41,6 +41,10 @@ cl::opt<unsigned> MemProfMinAveLifetimeAccessDensityHotThreshold(
41
41
cl::desc(" The minimum TotalLifetimeAccessDensity / AllocCount for an "
42
42
" allocation to be considered hot" ));
43
43
44
+ cl::opt<bool > MemProfReportHintedSizes (
45
+ " memprof-report-hinted-sizes" , cl::init(false ), cl::Hidden,
46
+ cl::desc(" Report total allocation sizes of hinted allocations" ));
47
+
44
48
AllocationType llvm::memprof::getAllocType (uint64_t TotalLifetimeAccessDensity,
45
49
uint64_t AllocCount,
46
50
uint64_t TotalLifetime) {
@@ -74,13 +78,13 @@ MDNode *llvm::memprof::buildCallstackMetadata(ArrayRef<uint64_t> CallStack,
74
78
}
75
79
76
80
MDNode *llvm::memprof::getMIBStackNode (const MDNode *MIB) {
77
- assert (MIB->getNumOperands () = = 2 );
81
+ assert (MIB->getNumOperands () > = 2 );
78
82
// The stack metadata is the first operand of each memprof MIB metadata.
79
83
return cast<MDNode>(MIB->getOperand (0 ));
80
84
}
81
85
82
86
AllocationType llvm::memprof::getMIBAllocType (const MDNode *MIB) {
83
- assert (MIB->getNumOperands () = = 2 );
87
+ assert (MIB->getNumOperands () > = 2 );
84
88
// The allocation type is currently the second operand of each memprof
85
89
// MIB metadata. This will need to change as we add additional allocation
86
90
// types that can be applied based on the allocation profile data.
@@ -94,6 +98,12 @@ AllocationType llvm::memprof::getMIBAllocType(const MDNode *MIB) {
94
98
return AllocationType::NotCold;
95
99
}
96
100
101
+ uint64_t llvm::memprof::getMIBTotalSize (const MDNode *MIB) {
102
+ if (MIB->getNumOperands () < 3 )
103
+ return 0 ;
104
+ return mdconst::dyn_extract<ConstantInt>(MIB->getOperand (2 ))->getZExtValue ();
105
+ }
106
+
97
107
std::string llvm::memprof::getAllocTypeAttributeString (AllocationType Type) {
98
108
switch (Type) {
99
109
case AllocationType::NotCold:
@@ -125,7 +135,8 @@ bool llvm::memprof::hasSingleAllocType(uint8_t AllocTypes) {
125
135
}
126
136
127
137
void CallStackTrie::addCallStack (AllocationType AllocType,
128
- ArrayRef<uint64_t > StackIds) {
138
+ ArrayRef<uint64_t > StackIds,
139
+ uint64_t TotalSize) {
129
140
bool First = true ;
130
141
CallStackTrieNode *Curr = nullptr ;
131
142
for (auto StackId : StackIds) {
@@ -135,9 +146,10 @@ void CallStackTrie::addCallStack(AllocationType AllocType,
135
146
if (Alloc) {
136
147
assert (AllocStackId == StackId);
137
148
Alloc->AllocTypes |= static_cast <uint8_t >(AllocType);
149
+ Alloc->TotalSize += TotalSize;
138
150
} else {
139
151
AllocStackId = StackId;
140
- Alloc = new CallStackTrieNode (AllocType);
152
+ Alloc = new CallStackTrieNode (AllocType, TotalSize );
141
153
}
142
154
Curr = Alloc;
143
155
continue ;
@@ -147,10 +159,11 @@ void CallStackTrie::addCallStack(AllocationType AllocType,
147
159
if (Next != Curr->Callers .end ()) {
148
160
Curr = Next->second ;
149
161
Curr->AllocTypes |= static_cast <uint8_t >(AllocType);
162
+ Curr->TotalSize += TotalSize;
150
163
continue ;
151
164
}
152
165
// Otherwise add a new caller node.
153
- auto *New = new CallStackTrieNode (AllocType);
166
+ auto *New = new CallStackTrieNode (AllocType, TotalSize );
154
167
Curr->Callers [StackId] = New;
155
168
Curr = New;
156
169
}
@@ -167,16 +180,19 @@ void CallStackTrie::addCallStack(MDNode *MIB) {
167
180
assert (StackId);
168
181
CallStack.push_back (StackId->getZExtValue ());
169
182
}
170
- addCallStack (getMIBAllocType (MIB), CallStack);
183
+ addCallStack (getMIBAllocType (MIB), CallStack, getMIBTotalSize (MIB) );
171
184
}
172
185
173
186
static MDNode *createMIBNode (LLVMContext &Ctx,
174
187
std::vector<uint64_t > &MIBCallStack,
175
- AllocationType AllocType) {
188
+ AllocationType AllocType, uint64_t TotalSize ) {
176
189
std::vector<Metadata *> MIBPayload (
177
190
{buildCallstackMetadata (MIBCallStack, Ctx)});
178
191
MIBPayload.push_back (
179
192
MDString::get (Ctx, getAllocTypeAttributeString (AllocType)));
193
+ if (TotalSize)
194
+ MIBPayload.push_back (ValueAsMetadata::get (
195
+ ConstantInt::get (Type::getInt64Ty (Ctx), TotalSize)));
180
196
return MDNode::get (Ctx, MIBPayload);
181
197
}
182
198
@@ -190,8 +206,8 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
190
206
// Trim context below the first node in a prefix with a single alloc type.
191
207
// Add an MIB record for the current call stack prefix.
192
208
if (hasSingleAllocType (Node->AllocTypes )) {
193
- MIBNodes.push_back (
194
- createMIBNode ( Ctx, MIBCallStack, (AllocationType)Node->AllocTypes ));
209
+ MIBNodes.push_back (createMIBNode (
210
+ Ctx, MIBCallStack, (AllocationType)Node->AllocTypes , Node-> TotalSize ));
195
211
return true ;
196
212
}
197
213
@@ -227,7 +243,8 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
227
243
// non-cold allocation type.
228
244
if (!CalleeHasAmbiguousCallerContext)
229
245
return false ;
230
- MIBNodes.push_back (createMIBNode (Ctx, MIBCallStack, AllocationType::NotCold));
246
+ MIBNodes.push_back (createMIBNode (Ctx, MIBCallStack, AllocationType::NotCold,
247
+ Node->TotalSize ));
231
248
return true ;
232
249
}
233
250
@@ -238,6 +255,13 @@ bool CallStackTrie::buildAndAttachMIBMetadata(CallBase *CI) {
238
255
auto &Ctx = CI->getContext ();
239
256
if (hasSingleAllocType (Alloc->AllocTypes )) {
240
257
addAllocTypeAttribute (Ctx, CI, (AllocationType)Alloc->AllocTypes );
258
+ if (MemProfReportHintedSizes) {
259
+ assert (Alloc->TotalSize );
260
+ errs () << " Total size for allocation with location hash " << AllocStackId
261
+ << " and single alloc type "
262
+ << getAllocTypeAttributeString ((AllocationType)Alloc->AllocTypes )
263
+ << " : " << Alloc->TotalSize << " \n " ;
264
+ }
241
265
return false ;
242
266
}
243
267
std::vector<uint64_t > MIBCallStack;
0 commit comments