1 //===- SampleContextTracker.cpp - Context-sensitive Profile Tracker -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the SampleContextTracker used by CSSPGO.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Transforms/IPO/SampleContextTracker.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/IR/DebugInfoMetadata.h"
17 #include "llvm/IR/InstrTypes.h"
18 #include "llvm/IR/Instruction.h"
19 #include "llvm/ProfileData/SampleProf.h"
20 #include <map>
21 #include <queue>
22 #include <vector>
23 
24 using namespace llvm;
25 using namespace sampleprof;
26 
27 #define DEBUG_TYPE "sample-context-tracker"
28 
29 namespace llvm {
30 
31 ContextTrieNode *ContextTrieNode::getChildContext(const LineLocation &CallSite,
32                                                   StringRef CalleeName) {
33   if (CalleeName.empty())
34     return getHottestChildContext(CallSite);
35 
36   uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
37   auto It = AllChildContext.find(Hash);
38   if (It != AllChildContext.end())
39     return &It->second;
40   return nullptr;
41 }
42 
43 ContextTrieNode *
44 ContextTrieNode::getHottestChildContext(const LineLocation &CallSite) {
45   // CSFDO-TODO: This could be slow, change AllChildContext so we can
46   // do point look up for child node by call site alone.
47   // Retrieve the child node with max count for indirect call
48   ContextTrieNode *ChildNodeRet = nullptr;
49   uint64_t MaxCalleeSamples = 0;
50   for (auto &It : AllChildContext) {
51     ContextTrieNode &ChildNode = It.second;
52     if (ChildNode.CallSiteLoc != CallSite)
53       continue;
54     FunctionSamples *Samples = ChildNode.getFunctionSamples();
55     if (!Samples)
56       continue;
57     if (Samples->getTotalSamples() > MaxCalleeSamples) {
58       ChildNodeRet = &ChildNode;
59       MaxCalleeSamples = Samples->getTotalSamples();
60     }
61   }
62 
63   return ChildNodeRet;
64 }
65 
66 ContextTrieNode &ContextTrieNode::moveToChildContext(
67     const LineLocation &CallSite, ContextTrieNode &&NodeToMove,
68     uint32_t ContextFramesToRemove, bool DeleteNode) {
69   uint64_t Hash =
70       FunctionSamples::getCallSiteHash(NodeToMove.getFuncName(), CallSite);
71   assert(!AllChildContext.count(Hash) && "Node to remove must exist");
72   LineLocation OldCallSite = NodeToMove.CallSiteLoc;
73   ContextTrieNode &OldParentContext = *NodeToMove.getParentContext();
74   AllChildContext[Hash] = NodeToMove;
75   ContextTrieNode &NewNode = AllChildContext[Hash];
76   NewNode.CallSiteLoc = CallSite;
77 
78   // Walk through nodes in the moved the subtree, and update
79   // FunctionSamples' context as for the context promotion.
80   // We also need to set new parant link for all children.
81   std::queue<ContextTrieNode *> NodeToUpdate;
82   NewNode.setParentContext(this);
83   NodeToUpdate.push(&NewNode);
84 
85   while (!NodeToUpdate.empty()) {
86     ContextTrieNode *Node = NodeToUpdate.front();
87     NodeToUpdate.pop();
88     FunctionSamples *FSamples = Node->getFunctionSamples();
89 
90     if (FSamples) {
91       FSamples->getContext().promoteOnPath(ContextFramesToRemove);
92       FSamples->getContext().setState(SyntheticContext);
93       LLVM_DEBUG(dbgs() << "  Context promoted to: "
94                         << FSamples->getContext().toString() << "\n");
95     }
96 
97     for (auto &It : Node->getAllChildContext()) {
98       ContextTrieNode *ChildNode = &It.second;
99       ChildNode->setParentContext(Node);
100       NodeToUpdate.push(ChildNode);
101     }
102   }
103 
104   // Original context no longer needed, destroy if requested.
105   if (DeleteNode)
106     OldParentContext.removeChildContext(OldCallSite, NewNode.getFuncName());
107 
108   return NewNode;
109 }
110 
111 void ContextTrieNode::removeChildContext(const LineLocation &CallSite,
112                                          StringRef CalleeName) {
113   uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
114   // Note this essentially calls dtor and destroys that child context
115   AllChildContext.erase(Hash);
116 }
117 
118 std::map<uint64_t, ContextTrieNode> &ContextTrieNode::getAllChildContext() {
119   return AllChildContext;
120 }
121 
122 StringRef ContextTrieNode::getFuncName() const { return FuncName; }
123 
124 FunctionSamples *ContextTrieNode::getFunctionSamples() const {
125   return FuncSamples;
126 }
127 
128 void ContextTrieNode::setFunctionSamples(FunctionSamples *FSamples) {
129   FuncSamples = FSamples;
130 }
131 
132 Optional<uint32_t> ContextTrieNode::getFunctionSize() const { return FuncSize; }
133 
134 void ContextTrieNode::addFunctionSize(uint32_t FSize) {
135   if (!FuncSize.hasValue())
136     FuncSize = 0;
137 
138   FuncSize = FuncSize.getValue() + FSize;
139 }
140 
141 LineLocation ContextTrieNode::getCallSiteLoc() const { return CallSiteLoc; }
142 
143 ContextTrieNode *ContextTrieNode::getParentContext() const {
144   return ParentContext;
145 }
146 
147 void ContextTrieNode::setParentContext(ContextTrieNode *Parent) {
148   ParentContext = Parent;
149 }
150 
151 void ContextTrieNode::dumpNode() {
152   dbgs() << "Node: " << FuncName << "\n"
153          << "  Callsite: " << CallSiteLoc << "\n"
154          << "  Size: " << FuncSize << "\n"
155          << "  Children:\n";
156 
157   for (auto &It : AllChildContext) {
158     dbgs() << "    Node: " << It.second.getFuncName() << "\n";
159   }
160 }
161 
162 void ContextTrieNode::dumpTree() {
163   dbgs() << "Context Profile Tree:\n";
164   std::queue<ContextTrieNode *> NodeQueue;
165   NodeQueue.push(this);
166 
167   while (!NodeQueue.empty()) {
168     ContextTrieNode *Node = NodeQueue.front();
169     NodeQueue.pop();
170     Node->dumpNode();
171 
172     for (auto &It : Node->getAllChildContext()) {
173       ContextTrieNode *ChildNode = &It.second;
174       NodeQueue.push(ChildNode);
175     }
176   }
177 }
178 
179 ContextTrieNode *ContextTrieNode::getOrCreateChildContext(
180     const LineLocation &CallSite, StringRef CalleeName, bool AllowCreate) {
181   uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
182   auto It = AllChildContext.find(Hash);
183   if (It != AllChildContext.end()) {
184     assert(It->second.getFuncName() == CalleeName &&
185            "Hash collision for child context node");
186     return &It->second;
187   }
188 
189   if (!AllowCreate)
190     return nullptr;
191 
192   AllChildContext[Hash] = ContextTrieNode(this, CalleeName, nullptr, CallSite);
193   return &AllChildContext[Hash];
194 }
195 
196 // Profiler tracker than manages profiles and its associated context
197 SampleContextTracker::SampleContextTracker(
198     SampleProfileMap &Profiles,
199     const DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap)
200     : GUIDToFuncNameMap(GUIDToFuncNameMap) {
201   for (auto &FuncSample : Profiles) {
202     FunctionSamples *FSamples = &FuncSample.second;
203     SampleContext Context = FuncSample.first;
204     LLVM_DEBUG(dbgs() << "Tracking Context for function: " << Context.toString()
205                       << "\n");
206     if (!Context.isBaseContext())
207       FuncToCtxtProfiles[Context.getName()].insert(FSamples);
208     ContextTrieNode *NewNode = getOrCreateContextPath(Context, true);
209     assert(!NewNode->getFunctionSamples() &&
210            "New node can't have sample profile");
211     NewNode->setFunctionSamples(FSamples);
212   }
213 }
214 
215 FunctionSamples *
216 SampleContextTracker::getCalleeContextSamplesFor(const CallBase &Inst,
217                                                  StringRef CalleeName) {
218   LLVM_DEBUG(dbgs() << "Getting callee context for instr: " << Inst << "\n");
219   DILocation *DIL = Inst.getDebugLoc();
220   if (!DIL)
221     return nullptr;
222 
223   CalleeName = FunctionSamples::getCanonicalFnName(CalleeName);
224   // Convert real function names to MD5 names, if the input profile is
225   // MD5-based.
226   std::string FGUID;
227   CalleeName = getRepInFormat(CalleeName, FunctionSamples::UseMD5, FGUID);
228 
229   // For indirect call, CalleeName will be empty, in which case the context
230   // profile for callee with largest total samples will be returned.
231   ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, CalleeName);
232   if (CalleeContext) {
233     FunctionSamples *FSamples = CalleeContext->getFunctionSamples();
234     LLVM_DEBUG(if (FSamples) {
235       dbgs() << "  Callee context found: " << FSamples->getContext().toString()
236              << "\n";
237     });
238     return FSamples;
239   }
240 
241   return nullptr;
242 }
243 
244 std::vector<const FunctionSamples *>
245 SampleContextTracker::getIndirectCalleeContextSamplesFor(
246     const DILocation *DIL) {
247   std::vector<const FunctionSamples *> R;
248   if (!DIL)
249     return R;
250 
251   ContextTrieNode *CallerNode = getContextFor(DIL);
252   LineLocation CallSite = FunctionSamples::getCallSiteIdentifier(DIL);
253   for (auto &It : CallerNode->getAllChildContext()) {
254     ContextTrieNode &ChildNode = It.second;
255     if (ChildNode.getCallSiteLoc() != CallSite)
256       continue;
257     if (FunctionSamples *CalleeSamples = ChildNode.getFunctionSamples())
258       R.push_back(CalleeSamples);
259   }
260 
261   return R;
262 }
263 
264 FunctionSamples *
265 SampleContextTracker::getContextSamplesFor(const DILocation *DIL) {
266   assert(DIL && "Expect non-null location");
267 
268   ContextTrieNode *ContextNode = getContextFor(DIL);
269   if (!ContextNode)
270     return nullptr;
271 
272   // We may have inlined callees during pre-LTO compilation, in which case
273   // we need to rely on the inline stack from !dbg to mark context profile
274   // as inlined, instead of `MarkContextSamplesInlined` during inlining.
275   // Sample profile loader walks through all instructions to get profile,
276   // which calls this function. So once that is done, all previously inlined
277   // context profile should be marked properly.
278   FunctionSamples *Samples = ContextNode->getFunctionSamples();
279   if (Samples && ContextNode->getParentContext() != &RootContext)
280     Samples->getContext().setState(InlinedContext);
281 
282   return Samples;
283 }
284 
285 FunctionSamples *
286 SampleContextTracker::getContextSamplesFor(const SampleContext &Context) {
287   ContextTrieNode *Node = getContextFor(Context);
288   if (!Node)
289     return nullptr;
290 
291   return Node->getFunctionSamples();
292 }
293 
294 SampleContextTracker::ContextSamplesTy &
295 SampleContextTracker::getAllContextSamplesFor(const Function &Func) {
296   StringRef CanonName = FunctionSamples::getCanonicalFnName(Func);
297   return FuncToCtxtProfiles[CanonName];
298 }
299 
300 SampleContextTracker::ContextSamplesTy &
301 SampleContextTracker::getAllContextSamplesFor(StringRef Name) {
302   return FuncToCtxtProfiles[Name];
303 }
304 
305 FunctionSamples *SampleContextTracker::getBaseSamplesFor(const Function &Func,
306                                                          bool MergeContext) {
307   StringRef CanonName = FunctionSamples::getCanonicalFnName(Func);
308   return getBaseSamplesFor(CanonName, MergeContext);
309 }
310 
311 FunctionSamples *SampleContextTracker::getBaseSamplesFor(StringRef Name,
312                                                          bool MergeContext) {
313   LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");
314   // Convert real function names to MD5 names, if the input profile is
315   // MD5-based.
316   std::string FGUID;
317   Name = getRepInFormat(Name, FunctionSamples::UseMD5, FGUID);
318 
319   // Base profile is top-level node (child of root node), so try to retrieve
320   // existing top-level node for given function first. If it exists, it could be
321   // that we've merged base profile before, or there's actually context-less
322   // profile from the input (e.g. due to unreliable stack walking).
323   ContextTrieNode *Node = getTopLevelContextNode(Name);
324   if (MergeContext) {
325     LLVM_DEBUG(dbgs() << "  Merging context profile into base profile: " << Name
326                       << "\n");
327 
328     // We have profile for function under different contexts,
329     // create synthetic base profile and merge context profiles
330     // into base profile.
331     for (auto *CSamples : FuncToCtxtProfiles[Name]) {
332       SampleContext &Context = CSamples->getContext();
333       // Skip inlined context profile and also don't re-merge any context
334       if (Context.hasState(InlinedContext) || Context.hasState(MergedContext))
335         continue;
336 
337       ContextTrieNode *FromNode = getContextFor(Context);
338       if (FromNode == Node)
339         continue;
340 
341       ContextTrieNode &ToNode = promoteMergeContextSamplesTree(*FromNode);
342       assert((!Node || Node == &ToNode) && "Expect only one base profile");
343       Node = &ToNode;
344     }
345   }
346 
347   // Still no profile even after merge/promotion (if allowed)
348   if (!Node)
349     return nullptr;
350 
351   return Node->getFunctionSamples();
352 }
353 
354 void SampleContextTracker::markContextSamplesInlined(
355     const FunctionSamples *InlinedSamples) {
356   assert(InlinedSamples && "Expect non-null inlined samples");
357   LLVM_DEBUG(dbgs() << "Marking context profile as inlined: "
358                     << InlinedSamples->getContext().toString() << "\n");
359   InlinedSamples->getContext().setState(InlinedContext);
360 }
361 
362 ContextTrieNode &SampleContextTracker::getRootContext() { return RootContext; }
363 
364 void SampleContextTracker::promoteMergeContextSamplesTree(
365     const Instruction &Inst, StringRef CalleeName) {
366   LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"
367                     << Inst << "\n");
368   // Get the caller context for the call instruction, we don't use callee
369   // name from call because there can be context from indirect calls too.
370   DILocation *DIL = Inst.getDebugLoc();
371   ContextTrieNode *CallerNode = getContextFor(DIL);
372   if (!CallerNode)
373     return;
374 
375   // Get the context that needs to be promoted
376   LineLocation CallSite = FunctionSamples::getCallSiteIdentifier(DIL);
377   // For indirect call, CalleeName will be empty, in which case we need to
378   // promote all non-inlined child context profiles.
379   if (CalleeName.empty()) {
380     for (auto &It : CallerNode->getAllChildContext()) {
381       ContextTrieNode *NodeToPromo = &It.second;
382       if (CallSite != NodeToPromo->getCallSiteLoc())
383         continue;
384       FunctionSamples *FromSamples = NodeToPromo->getFunctionSamples();
385       if (FromSamples && FromSamples->getContext().hasState(InlinedContext))
386         continue;
387       promoteMergeContextSamplesTree(*NodeToPromo);
388     }
389     return;
390   }
391 
392   // Get the context for the given callee that needs to be promoted
393   ContextTrieNode *NodeToPromo =
394       CallerNode->getChildContext(CallSite, CalleeName);
395   if (!NodeToPromo)
396     return;
397 
398   promoteMergeContextSamplesTree(*NodeToPromo);
399 }
400 
401 ContextTrieNode &SampleContextTracker::promoteMergeContextSamplesTree(
402     ContextTrieNode &NodeToPromo) {
403   // Promote the input node to be directly under root. This can happen
404   // when we decided to not inline a function under context represented
405   // by the input node. The promote and merge is then needed to reflect
406   // the context profile in the base (context-less) profile.
407   FunctionSamples *FromSamples = NodeToPromo.getFunctionSamples();
408   assert(FromSamples && "Shouldn't promote a context without profile");
409   LLVM_DEBUG(dbgs() << "  Found context tree root to promote: "
410                     << FromSamples->getContext().toString() << "\n");
411 
412   assert(!FromSamples->getContext().hasState(InlinedContext) &&
413          "Shouldn't promote inlined context profile");
414   uint32_t ContextFramesToRemove =
415       FromSamples->getContext().getContextFrames().size() - 1;
416   return promoteMergeContextSamplesTree(NodeToPromo, RootContext,
417                                         ContextFramesToRemove);
418 }
419 
420 void SampleContextTracker::dump() { RootContext.dumpTree(); }
421 
422 StringRef SampleContextTracker::getFuncNameFor(ContextTrieNode *Node) const {
423   if (!FunctionSamples::UseMD5)
424     return Node->getFuncName();
425   assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
426   return GUIDToFuncNameMap->lookup(std::stoull(Node->getFuncName().data()));
427 }
428 
429 ContextTrieNode *
430 SampleContextTracker::getContextFor(const SampleContext &Context) {
431   return getOrCreateContextPath(Context, false);
432 }
433 
434 ContextTrieNode *
435 SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
436                                           StringRef CalleeName) {
437   assert(DIL && "Expect non-null location");
438 
439   ContextTrieNode *CallContext = getContextFor(DIL);
440   if (!CallContext)
441     return nullptr;
442 
443   // When CalleeName is empty, the child context profile with max
444   // total samples will be returned.
445   return CallContext->getChildContext(
446       FunctionSamples::getCallSiteIdentifier(DIL), CalleeName);
447 }
448 
449 ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
450   assert(DIL && "Expect non-null location");
451   SmallVector<std::pair<LineLocation, StringRef>, 10> S;
452 
453   // Use C++ linkage name if possible.
454   const DILocation *PrevDIL = DIL;
455   for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
456     StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
457     if (Name.empty())
458       Name = PrevDIL->getScope()->getSubprogram()->getName();
459     S.push_back(
460         std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL), Name));
461     PrevDIL = DIL;
462   }
463 
464   // Push root node, note that root node like main may only
465   // a name, but not linkage name.
466   StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
467   if (RootName.empty())
468     RootName = PrevDIL->getScope()->getSubprogram()->getName();
469   S.push_back(std::make_pair(LineLocation(0, 0), RootName));
470 
471   // Convert real function names to MD5 names, if the input profile is
472   // MD5-based.
473   std::list<std::string> MD5Names;
474   if (FunctionSamples::UseMD5) {
475     for (auto &Location : S) {
476       MD5Names.emplace_back();
477       getRepInFormat(Location.second, FunctionSamples::UseMD5, MD5Names.back());
478       Location.second = MD5Names.back();
479     }
480   }
481 
482   ContextTrieNode *ContextNode = &RootContext;
483   int I = S.size();
484   while (--I >= 0 && ContextNode) {
485     LineLocation &CallSite = S[I].first;
486     StringRef CalleeName = S[I].second;
487     ContextNode = ContextNode->getChildContext(CallSite, CalleeName);
488   }
489 
490   if (I < 0)
491     return ContextNode;
492 
493   return nullptr;
494 }
495 
496 ContextTrieNode *
497 SampleContextTracker::getOrCreateContextPath(const SampleContext &Context,
498                                              bool AllowCreate) {
499   ContextTrieNode *ContextNode = &RootContext;
500   LineLocation CallSiteLoc(0, 0);
501 
502   for (auto &Callsite : Context.getContextFrames()) {
503     // Create child node at parent line/disc location
504     if (AllowCreate) {
505       ContextNode =
506           ContextNode->getOrCreateChildContext(CallSiteLoc, Callsite.FuncName);
507     } else {
508       ContextNode =
509           ContextNode->getChildContext(CallSiteLoc, Callsite.FuncName);
510     }
511     CallSiteLoc = Callsite.Location;
512   }
513 
514   assert((!AllowCreate || ContextNode) &&
515          "Node must exist if creation is allowed");
516   return ContextNode;
517 }
518 
519 ContextTrieNode *SampleContextTracker::getTopLevelContextNode(StringRef FName) {
520   assert(!FName.empty() && "Top level node query must provide valid name");
521   return RootContext.getChildContext(LineLocation(0, 0), FName);
522 }
523 
524 ContextTrieNode &SampleContextTracker::addTopLevelContextNode(StringRef FName) {
525   assert(!getTopLevelContextNode(FName) && "Node to add must not exist");
526   return *RootContext.getOrCreateChildContext(LineLocation(0, 0), FName);
527 }
528 
529 void SampleContextTracker::mergeContextNode(ContextTrieNode &FromNode,
530                                             ContextTrieNode &ToNode,
531                                             uint32_t ContextFramesToRemove) {
532   FunctionSamples *FromSamples = FromNode.getFunctionSamples();
533   FunctionSamples *ToSamples = ToNode.getFunctionSamples();
534   if (FromSamples && ToSamples) {
535     // Merge/duplicate FromSamples into ToSamples
536     ToSamples->merge(*FromSamples);
537     ToSamples->getContext().setState(SyntheticContext);
538     FromSamples->getContext().setState(MergedContext);
539     if (FromSamples->getContext().hasAttribute(ContextShouldBeInlined))
540       ToSamples->getContext().setAttribute(ContextShouldBeInlined);
541   } else if (FromSamples) {
542     // Transfer FromSamples from FromNode to ToNode
543     ToNode.setFunctionSamples(FromSamples);
544     FromSamples->getContext().setState(SyntheticContext);
545     FromSamples->getContext().promoteOnPath(ContextFramesToRemove);
546     FromNode.setFunctionSamples(nullptr);
547   }
548 }
549 
550 ContextTrieNode &SampleContextTracker::promoteMergeContextSamplesTree(
551     ContextTrieNode &FromNode, ContextTrieNode &ToNodeParent,
552     uint32_t ContextFramesToRemove) {
553   assert(ContextFramesToRemove && "Context to remove can't be empty");
554 
555   // Ignore call site location if destination is top level under root
556   LineLocation NewCallSiteLoc = LineLocation(0, 0);
557   LineLocation OldCallSiteLoc = FromNode.getCallSiteLoc();
558   ContextTrieNode &FromNodeParent = *FromNode.getParentContext();
559   ContextTrieNode *ToNode = nullptr;
560   bool MoveToRoot = (&ToNodeParent == &RootContext);
561   if (!MoveToRoot) {
562     NewCallSiteLoc = OldCallSiteLoc;
563   }
564 
565   // Locate destination node, create/move if not existing
566   ToNode = ToNodeParent.getChildContext(NewCallSiteLoc, FromNode.getFuncName());
567   if (!ToNode) {
568     // Do not delete node to move from its parent here because
569     // caller is iterating over children of that parent node.
570     ToNode = &ToNodeParent.moveToChildContext(
571         NewCallSiteLoc, std::move(FromNode), ContextFramesToRemove, false);
572   } else {
573     // Destination node exists, merge samples for the context tree
574     mergeContextNode(FromNode, *ToNode, ContextFramesToRemove);
575     LLVM_DEBUG({
576       if (ToNode->getFunctionSamples())
577         dbgs() << "  Context promoted and merged to: "
578                << ToNode->getFunctionSamples()->getContext().toString() << "\n";
579     });
580 
581     // Recursively promote and merge children
582     for (auto &It : FromNode.getAllChildContext()) {
583       ContextTrieNode &FromChildNode = It.second;
584       promoteMergeContextSamplesTree(FromChildNode, *ToNode,
585                                      ContextFramesToRemove);
586     }
587 
588     // Remove children once they're all merged
589     FromNode.getAllChildContext().clear();
590   }
591 
592   // For root of subtree, remove itself from old parent too
593   if (MoveToRoot)
594     FromNodeParent.removeChildContext(OldCallSiteLoc, ToNode->getFuncName());
595 
596   return *ToNode;
597 }
598 } // namespace llvm
599