24using namespace sampleprof;
26#define DEBUG_TYPE "sample-context-tracker"
32 if (CalleeName.
empty())
36 auto It = AllChildContext.find(Hash);
37 if (It != AllChildContext.end())
49 for (
auto &It : AllChildContext) {
51 if (ChildNode.CallSiteLoc != CallSite)
57 ChildNodeRet = &ChildNode;
71 std::map<uint64_t, ContextTrieNode> &AllChildContext =
73 assert(!AllChildContext.count(Hash) &&
"Node to remove must exist");
74 AllChildContext[Hash] = NodeToMove;
81 std::queue<ContextTrieNode *> NodeToUpdate;
83 NodeToUpdate.push(&NewNode);
85 while (!NodeToUpdate.empty()) {
91 setContextNode(FSamples, Node);
95 for (
auto &It :
Node->getAllChildContext()) {
98 NodeToUpdate.push(ChildNode);
109 AllChildContext.erase(Hash);
113 return AllChildContext;
123 FuncSamples = FSamples;
134 FuncSize = *FuncSize + FSize;
140 return ParentContext;
144 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) {
208 "New node can't have sample profile");
215 for (
auto *Node : *
this) {
219 setContextNode(FSamples, Node);
220 FuncToCtxtProfiles[Node->getFuncName()].push_back(FSamples);
228 LLVM_DEBUG(
dbgs() <<
"Getting callee context for instr: " << Inst <<
"\n");
252std::vector<const FunctionSamples *>
255 std::vector<const FunctionSamples *> R;
266 R.push_back(CalleeSamples);
274 assert(DIL &&
"Expect non-null location");
299 return Node->getFunctionSamples();
335 for (
auto *CSamples : FuncToCtxtProfiles[
Name]) {
342 if (FromNode == Node)
346 assert((!Node || Node == &ToNode) &&
"Expect only one base profile");
355 return Node->getFunctionSamples();
360 assert(InlinedSamples &&
"Expect non-null inlined samples");
370 LLVM_DEBUG(
dbgs() <<
"Promoting and merging context tree for instr: \n"
383 if (CalleeName.
empty()) {
412 assert(FromSamples &&
"Shouldn't promote a context without profile");
419 "Shouldn't promote inlined context profile");
432 if (Node == &RootContext)
433 return std::string();
437 Node = Node->getParentContext();
438 while (Node && Node != &RootContext) {
441 Node = Node->getParentContext();
444 std::reverse(Res.
begin(), Res.
end());
454 return Node->getFuncName().stringRef();
455 assert(GUIDToFuncNameMap &&
"GUIDToFuncNameMap needs to be populated first");
456 return GUIDToFuncNameMap->lookup(Node->getFuncName().getHashCode());
465SampleContextTracker::getCalleeContextFor(
const DILocation *DIL,
467 assert(DIL &&
"Expect non-null location");
480 assert(DIL &&
"Expect non-null location");
485 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
486 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
488 Name = PrevDIL->getScope()->getSubprogram()->getName();
497 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
498 if (RootName.
empty())
499 RootName = PrevDIL->getScope()->getSubprogram()->getName();
505 while (--
I >= 0 && ContextNode) {
532 CallSiteLoc = Callsite.Location;
535 assert((!AllowCreate || ContextNode) &&
536 "Node must exist if creation is allowed");
541SampleContextTracker::getTopLevelContextNode(
FunctionId FName) {
542 assert(!FName.
empty() &&
"Top level node query must provide valid name");
547SampleContextTracker::addTopLevelContextNode(
FunctionId FName) {
548 assert(!getTopLevelContextNode(FName) &&
"Node to add must not exist");
556 if (FromSamples && ToSamples) {
558 ToSamples->
merge(*FromSamples);
563 }
else if (FromSamples) {
566 setContextNode(FromSamples, &ToNode);
579 bool MoveToRoot = (&ToNodeParent == &RootContext);
581 NewCallSiteLoc = OldCallSiteLoc;
590 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));
597 mergeContextNode(FromNode, *ToNode);
600 dbgs() <<
" Context promoted and merged to: "
623 for (
auto *Node : *
this) {
627 ContextLessProfiles.
create(Node->getFuncName()).
merge(*FProfile);
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...
ContextTrieNode * getOrCreateChildContext(const LineLocation &CallSite, FunctionId ChildName, bool AllowCreate=true)
std::map< uint64_t, ContextTrieNode > & getAllChildContext()
void setCallSiteLoc(const LineLocation &Loc)
LineLocation getCallSiteLoc() const
FunctionSamples * getFunctionSamples() const
std::optional< uint32_t > getFunctionSize() const
ContextTrieNode * getHottestChildContext(const LineLocation &CallSite)
void setParentContext(ContextTrieNode *Parent)
void removeChildContext(const LineLocation &CallSite, FunctionId ChildName)
void addFunctionSize(uint32_t FSize)
FunctionId getFuncName() const
ContextTrieNode * getChildContext(const LineLocation &CallSite, FunctionId ChildName)
ContextTrieNode * getParentContext() const
void setFunctionSamples(FunctionSamples *FSamples)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
void promoteMergeContextSamplesTree(const Instruction &Inst, FunctionId CalleeName)
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
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.
This class represents a function that is read from a sample profile.
Representation of the samples collected for a function.
static uint64_t getCallSiteHash(FunctionId Callee, const LineLocation &Callsite)
Returns a unique hash code for a combination of a callsite location and the callee function name.
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
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)
SampleContextFrames getContextFrames() const
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
void setState(ContextStateMask S)
void setAttribute(ContextAttributeMask A)
bool hasAttribute(ContextAttributeMask A)
std::string toString() const
This class provides operator overloads to the map container using MD5 as the key type,...
mapped_type & create(const SampleContext &Ctx)
static FunctionId getRepInFormat(StringRef Name)
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.