25using namespace sampleprof;
27#define DEBUG_TYPE "sample-context-tracker"
33 if (CalleeName.
empty())
37 auto It = AllChildContext.find(Hash);
38 if (It != AllChildContext.end())
50 for (
auto &It : AllChildContext) {
52 if (ChildNode.CallSiteLoc != CallSite)
58 ChildNodeRet = &ChildNode;
72 std::map<uint64_t, ContextTrieNode> &AllChildContext =
74 assert(!AllChildContext.count(Hash) &&
"Node to remove must exist");
75 AllChildContext[Hash] = NodeToMove;
82 std::queue<ContextTrieNode *> NodeToUpdate;
84 NodeToUpdate.push(&NewNode);
86 while (!NodeToUpdate.empty()) {
92 setContextNode(FSamples, Node);
96 for (
auto &It :
Node->getAllChildContext()) {
99 NodeToUpdate.push(ChildNode);
110 AllChildContext.erase(Hash);
114 return AllChildContext;
124 FuncSamples = FSamples;
135 FuncSize = *FuncSize + FSize;
141 return ParentContext;
145 ParentContext = Parent;
153 dbgs() <<
"Node: " << FuncName <<
"\n"
154 <<
" Callsite: " << CallSiteLoc <<
"\n"
155 <<
" Size: " << FuncSize <<
"\n"
158 for (
auto &It : AllChildContext) {
159 dbgs() <<
" Node: " << It.second.getFuncName() <<
"\n";
164 dbgs() <<
"Context Profile Tree:\n";
165 std::queue<ContextTrieNode *> NodeQueue;
166 NodeQueue.push(
this);
168 while (!NodeQueue.empty()) {
173 for (
auto &It : Node->getAllChildContext()) {
175 NodeQueue.push(ChildNode);
183 auto It = AllChildContext.find(Hash);
184 if (It != AllChildContext.end()) {
185 assert(It->second.getFuncName() == CalleeName &&
186 "Hash collision for child context node");
193 AllChildContext[Hash] =
ContextTrieNode(
this, CalleeName,
nullptr, CallSite);
194 return &AllChildContext[Hash];
201 : GUIDToFuncNameMap(GUIDToFuncNameMap) {
202 for (
auto &FuncSample : Profiles) {
209 "New node can't have sample profile");
216 for (
auto *Node : *
this) {
220 setContextNode(FSamples, Node);
221 FuncToCtxtProfiles[Node->getFuncName()].push_back(FSamples);
229 LLVM_DEBUG(
dbgs() <<
"Getting callee context for instr: " << Inst <<
"\n");
255std::vector<const FunctionSamples *>
258 std::vector<const FunctionSamples *> R;
269 R.push_back(CalleeSamples);
277 assert(DIL &&
"Expect non-null location");
302 return Node->getFunctionSamples();
308 return FuncToCtxtProfiles[CanonName];
313 return FuncToCtxtProfiles[
Name];
342 for (
auto *CSamples : FuncToCtxtProfiles[
Name]) {
349 if (FromNode == Node)
353 assert((!Node || Node == &ToNode) &&
"Expect only one base profile");
362 return Node->getFunctionSamples();
367 assert(InlinedSamples &&
"Expect non-null inlined samples");
377 LLVM_DEBUG(
dbgs() <<
"Promoting and merging context tree for instr: \n"
390 if (CalleeName.
empty()) {
419 assert(FromSamples &&
"Shouldn't promote a context without profile");
426 "Shouldn't promote inlined context profile");
439 if (Node == &RootContext)
440 return std::string();
444 Node = Node->getParentContext();
445 while (Node && Node != &RootContext) {
448 Node = Node->getParentContext();
451 std::reverse(Res.
begin(), Res.
end());
461 return Node->getFuncName();
462 assert(GUIDToFuncNameMap &&
"GUIDToFuncNameMap needs to be populated first");
463 return GUIDToFuncNameMap->lookup(std::stoull(Node->getFuncName().data()));
472SampleContextTracker::getCalleeContextFor(
const DILocation *DIL,
474 assert(DIL &&
"Expect non-null location");
487 assert(DIL &&
"Expect non-null location");
492 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
493 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
495 Name = PrevDIL->getScope()->getSubprogram()->getName();
503 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
504 if (RootName.
empty())
505 RootName = PrevDIL->getScope()->getSubprogram()->getName();
510 std::list<std::string> MD5Names;
512 for (
auto &Location : S) {
513 MD5Names.emplace_back();
521 while (--
I >= 0 && ContextNode) {
539 for (
const auto &Callsite :
Context.getContextFrames()) {
548 CallSiteLoc = Callsite.Location;
551 assert((!AllowCreate || ContextNode) &&
552 "Node must exist if creation is allowed");
557 assert(!FName.
empty() &&
"Top level node query must provide valid name");
562 assert(!getTopLevelContextNode(FName) &&
"Node to add must not exist");
570 if (FromSamples && ToSamples) {
572 ToSamples->
merge(*FromSamples);
577 }
else if (FromSamples) {
580 setContextNode(FromSamples, &ToNode);
593 bool MoveToRoot = (&ToNodeParent == &RootContext);
595 NewCallSiteLoc = OldCallSiteLoc;
604 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));
611 mergeContextNode(FromNode, *ToNode);
614 dbgs() <<
" Context promoted and merged to: "
637 for (
auto *Node : *
this) {
641 ContextLessProfiles.
Create(Node->getFuncName()).
merge(*FProfile);
This file defines the StringMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file provides the interface for context-sensitive profile tracker used by CSSPGO.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
std::map< uint64_t, ContextTrieNode > & getAllChildContext()
ContextTrieNode * getOrCreateChildContext(const LineLocation &CallSite, StringRef ChildName, bool AllowCreate=true)
StringRef getFuncName() const
void setCallSiteLoc(const LineLocation &Loc)
LineLocation getCallSiteLoc() const
FunctionSamples * getFunctionSamples() const
std::optional< uint32_t > getFunctionSize() const
void removeChildContext(const LineLocation &CallSite, StringRef ChildName)
ContextTrieNode * getHottestChildContext(const LineLocation &CallSite)
void setParentContext(ContextTrieNode *Parent)
void addFunctionSize(uint32_t FSize)
ContextTrieNode * getParentContext() const
void setFunctionSamples(FunctionSamples *FSamples)
ContextTrieNode * getChildContext(const LineLocation &CallSite, StringRef ChildName)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
FunctionSamples * getBaseSamplesFor(const Function &Func, bool MergeContext=true)
ContextTrieNode * getOrCreateContextPath(const SampleContext &Context, bool AllowCreate)
StringRef getFuncNameFor(ContextTrieNode *Node) const
void populateFuncToCtxtMap()
ContextTrieNode & getRootContext()
std::string getContextString(const FunctionSamples &FSamples) const
void promoteMergeContextSamplesTree(const Instruction &Inst, StringRef CalleeName)
ContextTrieNode * getContextNodeForProfile(const FunctionSamples *FSamples) const
FunctionSamples * getContextSamplesFor(const DILocation *DIL)
std::vector< FunctionSamples * > ContextSamplesTy
ContextSamplesTy & getAllContextSamplesFor(const Function &Func)
void markContextSamplesInlined(const FunctionSamples *InlinedSamples)
void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles)
std::vector< const FunctionSamples * > getIndirectCalleeContextSamplesFor(const DILocation *DIL)
SampleContextTracker()=default
FunctionSamples * getCalleeContextSamplesFor(const CallBase &Inst, StringRef CalleeName)
ContextTrieNode * getContextFor(const SampleContext &Context)
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
Representation of the samples collected for a function.
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
static uint64_t getCallSiteHash(StringRef CalleeName, const LineLocation &Callsite)
Returns a unique hash code for a combination of a callsite location and the callee function name.
SampleContext & getContext() const
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
static LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
static bool UseMD5
Whether the profile uses MD5 to represent string.
bool hasState(ContextStateMask S)
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
void setState(ContextStateMask S)
void setAttribute(ContextAttributeMask A)
bool hasAttribute(ContextAttributeMask A)
This class provides operator overloads to the map container using MD5 as the key type,...
mapped_type & Create(const SampleContext &Ctx)
static StringRef getRepInFormat(StringRef Name, bool UseMD5, std::string &GUIDBuf)
Get the proper representation of a string according to whether the current Format uses MD5 to represe...
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Represents the relative location of an instruction.