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");
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");
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");
253std::vector<const FunctionSamples *>
256 std::vector<const FunctionSamples *> R;
267 R.push_back(CalleeSamples);
275 assert(DIL &&
"Expect non-null location");
300 return Node->getFunctionSamples();
336 for (
auto *CSamples : FuncToCtxtProfiles[
Name]) {
343 if (FromNode == Node)
347 assert((!Node || Node == &ToNode) &&
"Expect only one base profile");
356 return Node->getFunctionSamples();
361 assert(InlinedSamples &&
"Expect non-null inlined samples");
371 LLVM_DEBUG(
dbgs() <<
"Promoting and merging context tree for instr: \n"
384 if (CalleeName.
empty()) {
413 assert(FromSamples &&
"Shouldn't promote a context without profile");
420 "Shouldn't promote inlined context profile");
433 if (Node == &RootContext)
434 return std::string();
438 Node = Node->getParentContext();
439 while (Node && Node != &RootContext) {
442 Node = Node->getParentContext();
445 std::reverse(Res.
begin(), Res.
end());
455 return Node->getFuncName().stringRef();
456 assert(GUIDToFuncNameMap &&
"GUIDToFuncNameMap needs to be populated first");
457 return GUIDToFuncNameMap->lookup(Node->getFuncName().getHashCode());
466SampleContextTracker::getCalleeContextFor(
const DILocation *DIL,
468 assert(DIL &&
"Expect non-null location");
481 assert(DIL &&
"Expect non-null location");
486 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
487 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
489 Name = PrevDIL->getScope()->getSubprogram()->getName();
498 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
499 if (RootName.
empty())
500 RootName = PrevDIL->getScope()->getSubprogram()->getName();
506 while (--
I >= 0 && ContextNode) {
524 for (
const auto &Callsite :
Context.getContextFrames()) {
533 CallSiteLoc = Callsite.Location;
536 assert((!AllowCreate || ContextNode) &&
537 "Node must exist if creation is allowed");
542SampleContextTracker::getTopLevelContextNode(
FunctionId FName) {
543 assert(!FName.
empty() &&
"Top level node query must provide valid name");
548SampleContextTracker::addTopLevelContextNode(
FunctionId FName) {
549 assert(!getTopLevelContextNode(FName) &&
"Node to add must not exist");
557 if (FromSamples && ToSamples) {
559 ToSamples->
merge(*FromSamples);
564 }
else if (FromSamples) {
567 setContextNode(FromSamples, &ToNode);
580 bool MoveToRoot = (&ToNodeParent == &RootContext);
582 NewCallSiteLoc = OldCallSiteLoc;
591 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));
598 mergeContextNode(FromNode, *ToNode);
601 dbgs() <<
" Context promoted and merged to: "
624 for (
auto *Node : *
this) {
628 ContextLessProfiles.
create(Node->getFuncName()).
merge(*FProfile);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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...
LLVM_ABI ContextTrieNode * getOrCreateChildContext(const LineLocation &CallSite, FunctionId ChildName, bool AllowCreate=true)
LLVM_ABI std::map< uint64_t, ContextTrieNode > & getAllChildContext()
LLVM_ABI void setCallSiteLoc(const LineLocation &Loc)
LLVM_ABI LineLocation getCallSiteLoc() const
LLVM_ABI FunctionSamples * getFunctionSamples() const
LLVM_ABI std::optional< uint32_t > getFunctionSize() const
LLVM_ABI ContextTrieNode * getHottestChildContext(const LineLocation &CallSite)
LLVM_ABI void setParentContext(ContextTrieNode *Parent)
LLVM_ABI void removeChildContext(const LineLocation &CallSite, FunctionId ChildName)
LLVM_ABI void addFunctionSize(uint32_t FSize)
LLVM_ABI FunctionId getFuncName() const
LLVM_ABI ContextTrieNode * getChildContext(const LineLocation &CallSite, FunctionId ChildName)
LLVM_ABI ContextTrieNode * getParentContext() const
LLVM_ABI void setFunctionSamples(FunctionSamples *FSamples)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void promoteMergeContextSamplesTree(const Instruction &Inst, FunctionId CalleeName)
LLVM_ABI FunctionSamples * getBaseSamplesFor(const Function &Func, bool MergeContext=true)
LLVM_ABI ContextTrieNode * getOrCreateContextPath(const SampleContext &Context, bool AllowCreate)
LLVM_ABI StringRef getFuncNameFor(ContextTrieNode *Node) const
LLVM_ABI void populateFuncToCtxtMap()
LLVM_ABI ContextTrieNode & getRootContext()
LLVM_ABI std::string getContextString(const FunctionSamples &FSamples) const
ContextTrieNode * getContextNodeForProfile(const FunctionSamples *FSamples) const
LLVM_ABI FunctionSamples * getContextSamplesFor(const DILocation *DIL)
std::vector< FunctionSamples * > ContextSamplesTy
LLVM_ABI ContextSamplesTy & getAllContextSamplesFor(const Function &Func)
LLVM_ABI void markContextSamplesInlined(const FunctionSamples *InlinedSamples)
LLVM_ABI void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles)
LLVM_ABI std::vector< const FunctionSamples * > getIndirectCalleeContextSamplesFor(const DILocation *DIL)
SampleContextTracker()=default
LLVM_ABI FunctionSamples * getCalleeContextSamplesFor(const CallBase &Inst, StringRef CalleeName)
LLVM_ABI 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 LLVM_ABI LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
static LLVM_ABI 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 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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Represents the relative location of an instruction.