25 using namespace sampleprof;
27 #define DEBUG_TYPE "sample-context-tracker"
33 if (CalleeName.
empty())
34 return getHottestChildContext(CallSite);
37 auto It = AllChildContext.find(Hash);
38 if (It != AllChildContext.end())
50 for (
auto &It : AllChildContext) {
52 if (ChildNode.CallSiteLoc != CallSite)
58 ChildNodeRet = &ChildNode;
68 uint32_t ContextFramesToRemove,
bool DeleteNode) {
71 assert(!AllChildContext.count(Hash) &&
"Node to remove must exist");
74 AllChildContext[Hash] = NodeToMove;
76 NewNode.CallSiteLoc = CallSite;
81 std::queue<ContextTrieNode *> NodeToUpdate;
83 NodeToUpdate.push(&NewNode);
85 while (!NodeToUpdate.empty()) {
97 for (
auto &It : Node->getAllChildContext()) {
100 NodeToUpdate.push(ChildNode);
115 AllChildContext.erase(Hash);
119 return AllChildContext;
129 FuncSamples = FSamples;
135 if (!FuncSize.hasValue())
138 FuncSize = FuncSize.getValue() + FSize;
144 return ParentContext;
148 ParentContext = Parent;
152 dbgs() <<
"Node: " << FuncName <<
"\n"
153 <<
" Callsite: " << CallSiteLoc <<
"\n"
154 <<
" Size: " << FuncSize <<
"\n"
157 for (
auto &It : AllChildContext) {
158 dbgs() <<
" Node: " << It.second.getFuncName() <<
"\n";
163 dbgs() <<
"Context Profile Tree:\n";
164 std::queue<ContextTrieNode *> NodeQueue;
165 NodeQueue.push(
this);
167 while (!NodeQueue.empty()) {
172 for (
auto &It : Node->getAllChildContext()) {
174 NodeQueue.push(ChildNode);
182 auto It = AllChildContext.find(Hash);
183 if (It != AllChildContext.end()) {
184 assert(It->second.getFuncName() == CalleeName &&
185 "Hash collision for child context node");
192 AllChildContext[Hash] =
ContextTrieNode(
this, CalleeName,
nullptr, CallSite);
193 return &AllChildContext[Hash];
200 : GUIDToFuncNameMap(GUIDToFuncNameMap) {
201 for (
auto &FuncSample : Profiles) {
210 "New node can't have sample profile");
218 LLVM_DEBUG(
dbgs() <<
"Getting callee context for instr: " << Inst <<
"\n");
244 std::vector<const FunctionSamples *>
247 std::vector<const FunctionSamples *> R;
258 R.push_back(CalleeSamples);
266 assert(DIL &&
"Expect non-null location");
291 return Node->getFunctionSamples();
297 return FuncToCtxtProfiles[CanonName];
302 return FuncToCtxtProfiles[
Name];
331 for (
auto *CSamples : FuncToCtxtProfiles[
Name]) {
338 if (FromNode == Node)
342 assert((!Node || Node == &ToNode) &&
"Expect only one base profile");
351 return Node->getFunctionSamples();
356 assert(InlinedSamples &&
"Expect non-null inlined samples");
366 LLVM_DEBUG(
dbgs() <<
"Promoting and merging context tree for instr: \n"
379 if (CalleeName.
empty()) {
408 assert(FromSamples &&
"Shouldn't promote a context without profile");
413 "Shouldn't promote inlined context profile");
417 ContextFramesToRemove);
424 return Node->getFuncName();
425 assert(GUIDToFuncNameMap &&
"GUIDToFuncNameMap needs to be populated first");
426 return GUIDToFuncNameMap->lookup(std::stoull(Node->getFuncName().data()));
431 return getOrCreateContextPath(
Context,
false);
435 SampleContextTracker::getCalleeContextFor(
const DILocation *DIL,
437 assert(DIL &&
"Expect non-null location");
450 assert(DIL &&
"Expect non-null location");
455 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
456 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
458 Name = PrevDIL->getScope()->getSubprogram()->getName();
466 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
467 if (RootName.
empty())
468 RootName = PrevDIL->getScope()->getSubprogram()->getName();
473 std::list<std::string> MD5Names;
475 for (
auto &Location :
S) {
476 MD5Names.emplace_back();
484 while (--
I >= 0 && ContextNode) {
502 for (
auto &Callsite :
Context.getContextFrames()) {
511 CallSiteLoc = Callsite.Location;
514 assert((!AllowCreate || ContextNode) &&
515 "Node must exist if creation is allowed");
520 assert(!FName.
empty() &&
"Top level node query must provide valid name");
525 assert(!getTopLevelContextNode(FName) &&
"Node to add must not exist");
534 if (FromSamples && ToSamples) {
536 ToSamples->
merge(*FromSamples);
541 }
else if (FromSamples) {
553 assert(ContextFramesToRemove &&
"Context to remove can't be empty");
560 bool MoveToRoot = (&ToNodeParent == &RootContext);
562 NewCallSiteLoc = OldCallSiteLoc;
571 NewCallSiteLoc,
std::move(FromNode), ContextFramesToRemove,
false);
574 mergeContextNode(FromNode, *ToNode, ContextFramesToRemove);
577 dbgs() <<
" Context promoted and merged to: "
585 ContextFramesToRemove);