@@ -100,12 +100,6 @@ AllocationType llvm::memprof::getMIBAllocType(const MDNode *MIB) {
100100 return AllocationType::NotCold;
101101}
102102
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-
109103std::string llvm::memprof::getAllocTypeAttributeString (AllocationType Type) {
110104 switch (Type) {
111105 case AllocationType::NotCold:
@@ -136,22 +130,21 @@ bool llvm::memprof::hasSingleAllocType(uint8_t AllocTypes) {
136130 return NumAllocTypes == 1 ;
137131}
138132
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 ) {
142136 bool First = true ;
143137 CallStackTrieNode *Curr = nullptr ;
144138 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.
146140 if (First) {
147141 First = false ;
148142 if (Alloc) {
149143 assert (AllocStackId == StackId);
150144 Alloc->AllocTypes |= static_cast <uint8_t >(AllocType);
151- Alloc->TotalSize += TotalSize;
152145 } else {
153146 AllocStackId = StackId;
154- Alloc = new CallStackTrieNode (AllocType, TotalSize );
147+ Alloc = new CallStackTrieNode (AllocType);
155148 }
156149 Curr = Alloc;
157150 continue ;
@@ -161,15 +154,18 @@ void CallStackTrie::addCallStack(AllocationType AllocType,
161154 if (Next != Curr->Callers .end ()) {
162155 Curr = Next->second ;
163156 Curr->AllocTypes |= static_cast <uint8_t >(AllocType);
164- Curr->TotalSize += TotalSize;
165157 continue ;
166158 }
167159 // Otherwise add a new caller node.
168- auto *New = new CallStackTrieNode (AllocType, TotalSize );
160+ auto *New = new CallStackTrieNode (AllocType);
169161 Curr->Callers [StackId] = New;
170162 Curr = New;
171163 }
172164 assert (Curr);
165+ Curr->ContextSizeInfo .insert (Curr->ContextSizeInfo .end (),
166+ ContextSizeInfo.begin (), ContextSizeInfo.end ());
167+ std::vector<ContextTotalSize> AllContextSizeInfo;
168+ collectContextSizeInfo (Curr, AllContextSizeInfo);
173169}
174170
175171void CallStackTrie::addCallStack (MDNode *MIB) {
@@ -182,21 +178,52 @@ void CallStackTrie::addCallStack(MDNode *MIB) {
182178 assert (StackId);
183179 CallStack.push_back (StackId->getZExtValue ());
184180 }
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));
186197}
187198
188199static MDNode *createMIBNode (LLVMContext &Ctx, ArrayRef<uint64_t > MIBCallStack,
189- AllocationType AllocType, uint64_t TotalSize) {
200+ AllocationType AllocType,
201+ ArrayRef<ContextTotalSize> ContextSizeInfo) {
190202 SmallVector<Metadata *> MIBPayload (
191203 {buildCallstackMetadata (MIBCallStack, Ctx)});
192204 MIBPayload.push_back (
193205 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+ }
197216 return MDNode::get (Ctx, MIBPayload);
198217}
199218
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+
200227// Recursive helper to trim contexts and create metadata nodes.
201228// Caller should have pushed Node's loc to MIBCallStack. Doing this in the
202229// caller makes it simpler to handle the many early returns in this method.
@@ -207,8 +234,10 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
207234 // Trim context below the first node in a prefix with a single alloc type.
208235 // Add an MIB record for the current call stack prefix.
209236 if (hasSingleAllocType (Node->AllocTypes )) {
237+ std::vector<ContextTotalSize> ContextSizeInfo;
238+ collectContextSizeInfo (Node, ContextSizeInfo);
210239 MIBNodes.push_back (createMIBNode (
211- Ctx, MIBCallStack, (AllocationType)Node->AllocTypes , Node-> TotalSize ));
240+ Ctx, MIBCallStack, (AllocationType)Node->AllocTypes , ContextSizeInfo ));
212241 return true ;
213242 }
214243
@@ -244,8 +273,10 @@ bool CallStackTrie::buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
244273 // non-cold allocation type.
245274 if (!CalleeHasAmbiguousCallerContext)
246275 return false ;
276+ std::vector<ContextTotalSize> ContextSizeInfo;
277+ collectContextSizeInfo (Node, ContextSizeInfo);
247278 MIBNodes.push_back (createMIBNode (Ctx, MIBCallStack, AllocationType::NotCold,
248- Node-> TotalSize ));
279+ ContextSizeInfo ));
249280 return true ;
250281}
251282
@@ -257,11 +288,15 @@ bool CallStackTrie::buildAndAttachMIBMetadata(CallBase *CI) {
257288 if (hasSingleAllocType (Alloc->AllocTypes )) {
258289 addAllocTypeAttribute (Ctx, CI, (AllocationType)Alloc->AllocTypes );
259290 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+ }
265300 }
266301 return false ;
267302 }
0 commit comments