@@ -100,12 +100,6 @@ AllocationType llvm::memprof::getMIBAllocType(const MDNode *MIB) {
100
100
return AllocationType::NotCold;
101
101
}
102
102
103
- uint64_t llvm::memprof::getMIBTotalSize (const MDNode *MIB) {
104
- if (MIB->getNumOperands () < 3 )
105
- return 0 ;
106
- return mdconst::dyn_extract<ConstantInt>(MIB->getOperand (2 ))->getZExtValue ();
107
- }
108
-
109
103
std::string llvm::memprof::getAllocTypeAttributeString (AllocationType Type) {
110
104
switch (Type) {
111
105
case AllocationType::NotCold:
@@ -136,22 +130,21 @@ bool llvm::memprof::hasSingleAllocType(uint8_t AllocTypes) {
136
130
return NumAllocTypes == 1 ;
137
131
}
138
132
139
- void CallStackTrie::addCallStack (AllocationType AllocType,
140
- ArrayRef<uint64_t > StackIds,
141
- uint64_t TotalSize ) {
133
+ void CallStackTrie::addCallStack (
134
+ AllocationType AllocType, ArrayRef<uint64_t > StackIds,
135
+ std::vector<ContextTotalSize> ContextSizeInfo ) {
142
136
bool First = true ;
143
137
CallStackTrieNode *Curr = nullptr ;
144
138
for (auto StackId : StackIds) {
145
- // If this is the first stack frame, add or update alloc node.
139
+ // If this is the first stack frame, add or update alloc node.
146
140
if (First) {
147
141
First = false ;
148
142
if (Alloc) {
149
143
assert (AllocStackId == StackId);
150
144
Alloc->AllocTypes |= static_cast <uint8_t >(AllocType);
151
- Alloc->TotalSize += TotalSize;
152
145
} else {
153
146
AllocStackId = StackId;
154
- Alloc = new CallStackTrieNode (AllocType, TotalSize );
147
+ Alloc = new CallStackTrieNode (AllocType);
155
148
}
156
149
Curr = Alloc;
157
150
continue ;
@@ -161,15 +154,18 @@ void CallStackTrie::addCallStack(AllocationType AllocType,
161
154
if (Next != Curr->Callers .end ()) {
162
155
Curr = Next->second ;
163
156
Curr->AllocTypes |= static_cast <uint8_t >(AllocType);
164
- Curr->TotalSize += TotalSize;
165
157
continue ;
166
158
}
167
159
// Otherwise add a new caller node.
168
- auto *New = new CallStackTrieNode (AllocType, TotalSize );
160
+ auto *New = new CallStackTrieNode (AllocType);
169
161
Curr->Callers [StackId] = New;
170
162
Curr = New;
171
163
}
172
164
assert (Curr);
165
+ Curr->ContextSizeInfo .insert (Curr->ContextSizeInfo .end (),
166
+ ContextSizeInfo.begin (), ContextSizeInfo.end ());
167
+ std::vector<ContextTotalSize> AllContextSizeInfo;
168
+ collectContextSizeInfo (Curr, AllContextSizeInfo);
173
169
}
174
170
175
171
void CallStackTrie::addCallStack (MDNode *MIB) {
@@ -182,21 +178,52 @@ void CallStackTrie::addCallStack(MDNode *MIB) {
182
178
assert (StackId);
183
179
CallStack.push_back (StackId->getZExtValue ());
184
180
}
185
- addCallStack (getMIBAllocType (MIB), CallStack, getMIBTotalSize (MIB));
181
+ std::vector<ContextTotalSize> ContextSizeInfo;
182
+ // Collect the context size information if it exists.
183
+ if (MIB->getNumOperands () > 2 ) {
184
+ for (unsigned I = 2 ; I < MIB->getNumOperands (); I++) {
185
+ MDNode *ContextSizePair = dyn_cast<MDNode>(MIB->getOperand (I));
186
+ assert (ContextSizePair->getNumOperands () == 2 );
187
+ uint64_t FullStackId =
188
+ mdconst::dyn_extract<ConstantInt>(ContextSizePair->getOperand (0 ))
189
+ ->getZExtValue ();
190
+ uint64_t TotalSize =
191
+ mdconst::dyn_extract<ConstantInt>(ContextSizePair->getOperand (1 ))
192
+ ->getZExtValue ();
193
+ ContextSizeInfo.push_back ({FullStackId, TotalSize});
194
+ }
195
+ }
196
+ addCallStack (getMIBAllocType (MIB), CallStack, std::move (ContextSizeInfo));
186
197
}
187
198
188
199
static MDNode *createMIBNode (LLVMContext &Ctx, ArrayRef<uint64_t > MIBCallStack,
189
- AllocationType AllocType, uint64_t TotalSize) {
200
+ AllocationType AllocType,
201
+ ArrayRef<ContextTotalSize> ContextSizeInfo) {
190
202
SmallVector<Metadata *> MIBPayload (
191
203
{buildCallstackMetadata (MIBCallStack, Ctx)});
192
204
MIBPayload.push_back (
193
205
MDString::get (Ctx, getAllocTypeAttributeString (AllocType)));
194
- if (TotalSize)
195
- MIBPayload.push_back (ValueAsMetadata::get (
196
- ConstantInt::get (Type::getInt64Ty (Ctx), TotalSize)));
206
+ if (!ContextSizeInfo.empty ()) {
207
+ for (const auto &[FullStackId, TotalSize] : ContextSizeInfo) {
208
+ auto *FullStackIdMD = ValueAsMetadata::get (
209
+ ConstantInt::get (Type::getInt64Ty (Ctx), FullStackId));
210
+ auto *TotalSizeMD = ValueAsMetadata::get (
211
+ ConstantInt::get (Type::getInt64Ty (Ctx), TotalSize));
212
+ auto *ContextSizeMD = MDNode::get (Ctx, {FullStackIdMD, TotalSizeMD});
213
+ MIBPayload.push_back (ContextSizeMD);
214
+ }
215
+ }
197
216
return MDNode::get (Ctx, MIBPayload);
198
217
}
199
218
219
+ void CallStackTrie::collectContextSizeInfo (
220
+ CallStackTrieNode *Node, std::vector<ContextTotalSize> &ContextSizeInfo) {
221
+ ContextSizeInfo.insert (ContextSizeInfo.end (), Node->ContextSizeInfo .begin (),
222
+ Node->ContextSizeInfo .end ());
223
+ for (auto &Caller : Node->Callers )
224
+ collectContextSizeInfo (Caller.second , ContextSizeInfo);
225
+ }
226
+
200
227
// Recursive helper to trim contexts and create metadata nodes.
201
228
// Caller should have pushed Node's loc to MIBCallStack. Doing this in the
202
229
// caller makes it simpler to handle the many early returns in this method.
@@ -207,8 +234,10 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
207
234
// Trim context below the first node in a prefix with a single alloc type.
208
235
// Add an MIB record for the current call stack prefix.
209
236
if (hasSingleAllocType (Node->AllocTypes )) {
237
+ std::vector<ContextTotalSize> ContextSizeInfo;
238
+ collectContextSizeInfo (Node, ContextSizeInfo);
210
239
MIBNodes.push_back (createMIBNode (
211
- Ctx, MIBCallStack, (AllocationType)Node->AllocTypes , Node-> TotalSize ));
240
+ Ctx, MIBCallStack, (AllocationType)Node->AllocTypes , ContextSizeInfo ));
212
241
return true ;
213
242
}
214
243
@@ -244,8 +273,10 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
244
273
// non-cold allocation type.
245
274
if (!CalleeHasAmbiguousCallerContext)
246
275
return false ;
276
+ std::vector<ContextTotalSize> ContextSizeInfo;
277
+ collectContextSizeInfo (Node, ContextSizeInfo);
247
278
MIBNodes.push_back (createMIBNode (Ctx, MIBCallStack, AllocationType::NotCold,
248
- Node-> TotalSize ));
279
+ ContextSizeInfo ));
249
280
return true ;
250
281
}
251
282
@@ -257,11 +288,15 @@ bool CallStackTrie::buildAndAttachMIBMetadata(CallBase *CI) {
257
288
if (hasSingleAllocType (Alloc->AllocTypes )) {
258
289
addAllocTypeAttribute (Ctx, CI, (AllocationType)Alloc->AllocTypes );
259
290
if (MemProfReportHintedSizes) {
260
- assert (Alloc->TotalSize );
261
- errs () << " Total size for allocation with location hash " << AllocStackId
262
- << " and single alloc type "
263
- << getAllocTypeAttributeString ((AllocationType)Alloc->AllocTypes )
264
- << " : " << Alloc->TotalSize << " \n " ;
291
+ std::vector<ContextTotalSize> ContextSizeInfo;
292
+ collectContextSizeInfo (Alloc, ContextSizeInfo);
293
+ for (const auto &[FullStackId, TotalSize] : ContextSizeInfo) {
294
+ errs ()
295
+ << " MemProf hinting: Total size for full allocation context hash "
296
+ << FullStackId << " and single alloc type "
297
+ << getAllocTypeAttributeString ((AllocationType)Alloc->AllocTypes )
298
+ << " : " << TotalSize << " \n " ;
299
+ }
265
300
}
266
301
return false ;
267
302
}
0 commit comments