LLVM 20.0.0git
SampleContextTracker.cpp
Go to the documentation of this file.
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
14#include "llvm/ADT/StringRef.h"
16#include "llvm/IR/InstrTypes.h"
17#include "llvm/IR/Instruction.h"
19#include <map>
20#include <queue>
21#include <vector>
22
23using namespace llvm;
24using namespace sampleprof;
25
26#define DEBUG_TYPE "sample-context-tracker"
27
28namespace llvm {
29
31 FunctionId CalleeName) {
32 if (CalleeName.empty())
33 return getHottestChildContext(CallSite);
34
35 uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
36 auto It = AllChildContext.find(Hash);
37 if (It != AllChildContext.end())
38 return &It->second;
39 return nullptr;
40}
41
44 // CSFDO-TODO: This could be slow, change AllChildContext so we can
45 // do point look up for child node by call site alone.
46 // Retrieve the child node with max count for indirect call
47 ContextTrieNode *ChildNodeRet = nullptr;
48 uint64_t MaxCalleeSamples = 0;
49 for (auto &It : AllChildContext) {
50 ContextTrieNode &ChildNode = It.second;
51 if (ChildNode.CallSiteLoc != CallSite)
52 continue;
53 FunctionSamples *Samples = ChildNode.getFunctionSamples();
54 if (!Samples)
55 continue;
56 if (Samples->getTotalSamples() > MaxCalleeSamples) {
57 ChildNodeRet = &ChildNode;
58 MaxCalleeSamples = Samples->getTotalSamples();
59 }
60 }
61
62 return ChildNodeRet;
63}
64
66SampleContextTracker::moveContextSamples(ContextTrieNode &ToNodeParent,
67 const LineLocation &CallSite,
68 ContextTrieNode &&NodeToMove) {
69 uint64_t Hash =
70 FunctionSamples::getCallSiteHash(NodeToMove.getFuncName(), CallSite);
71 std::map<uint64_t, ContextTrieNode> &AllChildContext =
72 ToNodeParent.getAllChildContext();
73 assert(!AllChildContext.count(Hash) && "Node to remove must exist");
74 AllChildContext[Hash] = NodeToMove;
75 ContextTrieNode &NewNode = AllChildContext[Hash];
76 NewNode.setCallSiteLoc(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(&ToNodeParent);
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 setContextNode(FSamples, Node);
93 }
94
95 for (auto &It : Node->getAllChildContext()) {
96 ContextTrieNode *ChildNode = &It.second;
97 ChildNode->setParentContext(Node);
98 NodeToUpdate.push(ChildNode);
99 }
100 }
101
102 return NewNode;
103}
104
106 FunctionId CalleeName) {
107 uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
108 // Note this essentially calls dtor and destroys that child context
109 AllChildContext.erase(Hash);
110}
111
112std::map<uint64_t, ContextTrieNode> &ContextTrieNode::getAllChildContext() {
113 return AllChildContext;
114}
115
116FunctionId ContextTrieNode::getFuncName() const { return FuncName; }
117
119 return FuncSamples;
120}
121
123 FuncSamples = FSamples;
124}
125
126std::optional<uint32_t> ContextTrieNode::getFunctionSize() const {
127 return FuncSize;
128}
129
131 if (!FuncSize)
132 FuncSize = 0;
133
134 FuncSize = *FuncSize + FSize;
135}
136
137LineLocation ContextTrieNode::getCallSiteLoc() const { return CallSiteLoc; }
138
140 return ParentContext;
141}
142
144 ParentContext = Parent;
145}
146
148 CallSiteLoc = Loc;
149}
150
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
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
180 const LineLocation &CallSite, FunctionId 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
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.second.getContext();
204 LLVM_DEBUG(dbgs() << "Tracking Context for function: " << Context.toString()
205 << "\n");
206 ContextTrieNode *NewNode = getOrCreateContextPath(Context, true);
207 assert(!NewNode->getFunctionSamples() &&
208 "New node can't have sample profile");
209 NewNode->setFunctionSamples(FSamples);
210 }
212}
213
215 for (auto *Node : *this) {
216 FunctionSamples *FSamples = Node->getFunctionSamples();
217 if (FSamples) {
218 FSamples->getContext().setState(RawContext);
219 setContextNode(FSamples, Node);
220 FuncToCtxtProfiles[Node->getFuncName()].push_back(FSamples);
221 }
222 }
223}
224
227 StringRef CalleeName) {
228 LLVM_DEBUG(dbgs() << "Getting callee context for instr: " << Inst << "\n");
229 DILocation *DIL = Inst.getDebugLoc();
230 if (!DIL)
231 return nullptr;
232
233 CalleeName = FunctionSamples::getCanonicalFnName(CalleeName);
234
235 FunctionId FName = getRepInFormat(CalleeName);
236
237 // For indirect call, CalleeName will be empty, in which case the context
238 // profile for callee with largest total samples will be returned.
239 ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, FName);
240 if (CalleeContext) {
241 FunctionSamples *FSamples = CalleeContext->getFunctionSamples();
242 LLVM_DEBUG(if (FSamples) {
243 dbgs() << " Callee context found: " << getContextString(CalleeContext)
244 << "\n";
245 });
246 return FSamples;
247 }
248
249 return nullptr;
250}
251
252std::vector<const FunctionSamples *>
254 const DILocation *DIL) {
255 std::vector<const FunctionSamples *> R;
256 if (!DIL)
257 return R;
258
259 ContextTrieNode *CallerNode = getContextFor(DIL);
261 for (auto &It : CallerNode->getAllChildContext()) {
262 ContextTrieNode &ChildNode = It.second;
263 if (ChildNode.getCallSiteLoc() != CallSite)
264 continue;
265 if (FunctionSamples *CalleeSamples = ChildNode.getFunctionSamples())
266 R.push_back(CalleeSamples);
267 }
268
269 return R;
270}
271
274 assert(DIL && "Expect non-null location");
275
276 ContextTrieNode *ContextNode = getContextFor(DIL);
277 if (!ContextNode)
278 return nullptr;
279
280 // We may have inlined callees during pre-LTO compilation, in which case
281 // we need to rely on the inline stack from !dbg to mark context profile
282 // as inlined, instead of `MarkContextSamplesInlined` during inlining.
283 // Sample profile loader walks through all instructions to get profile,
284 // which calls this function. So once that is done, all previously inlined
285 // context profile should be marked properly.
286 FunctionSamples *Samples = ContextNode->getFunctionSamples();
287 if (Samples && ContextNode->getParentContext() != &RootContext)
289
290 return Samples;
291}
292
295 ContextTrieNode *Node = getContextFor(Context);
296 if (!Node)
297 return nullptr;
298
299 return Node->getFunctionSamples();
300}
301
305 return FuncToCtxtProfiles[getRepInFormat(CanonName)];
306}
307
310 return FuncToCtxtProfiles[getRepInFormat(Name)];
311}
312
314 bool MergeContext) {
316 return getBaseSamplesFor(getRepInFormat(CanonName), MergeContext);
317}
318
320 bool MergeContext) {
321 LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");
322
323 // Base profile is top-level node (child of root node), so try to retrieve
324 // existing top-level node for given function first. If it exists, it could be
325 // that we've merged base profile before, or there's actually context-less
326 // profile from the input (e.g. due to unreliable stack walking).
327 ContextTrieNode *Node = getTopLevelContextNode(Name);
328 if (MergeContext) {
329 LLVM_DEBUG(dbgs() << " Merging context profile into base profile: " << Name
330 << "\n");
331
332 // We have profile for function under different contexts,
333 // create synthetic base profile and merge context profiles
334 // into base profile.
335 for (auto *CSamples : FuncToCtxtProfiles[Name]) {
336 SampleContext &Context = CSamples->getContext();
337 // Skip inlined context profile and also don't re-merge any context
338 if (Context.hasState(InlinedContext) || Context.hasState(MergedContext))
339 continue;
340
341 ContextTrieNode *FromNode = getContextNodeForProfile(CSamples);
342 if (FromNode == Node)
343 continue;
344
346 assert((!Node || Node == &ToNode) && "Expect only one base profile");
347 Node = &ToNode;
348 }
349 }
350
351 // Still no profile even after merge/promotion (if allowed)
352 if (!Node)
353 return nullptr;
354
355 return Node->getFunctionSamples();
356}
357
359 const FunctionSamples *InlinedSamples) {
360 assert(InlinedSamples && "Expect non-null inlined samples");
361 LLVM_DEBUG(dbgs() << "Marking context profile as inlined: "
362 << getContextString(*InlinedSamples) << "\n");
363 InlinedSamples->getContext().setState(InlinedContext);
364}
365
367
369 const Instruction &Inst, FunctionId CalleeName) {
370 LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"
371 << Inst << "\n");
372 // Get the caller context for the call instruction, we don't use callee
373 // name from call because there can be context from indirect calls too.
374 DILocation *DIL = Inst.getDebugLoc();
375 ContextTrieNode *CallerNode = getContextFor(DIL);
376 if (!CallerNode)
377 return;
378
379 // Get the context that needs to be promoted
381 // For indirect call, CalleeName will be empty, in which case we need to
382 // promote all non-inlined child context profiles.
383 if (CalleeName.empty()) {
384 for (auto &It : CallerNode->getAllChildContext()) {
385 ContextTrieNode *NodeToPromo = &It.second;
386 if (CallSite != NodeToPromo->getCallSiteLoc())
387 continue;
388 FunctionSamples *FromSamples = NodeToPromo->getFunctionSamples();
389 if (FromSamples && FromSamples->getContext().hasState(InlinedContext))
390 continue;
391 promoteMergeContextSamplesTree(*NodeToPromo);
392 }
393 return;
394 }
395
396 // Get the context for the given callee that needs to be promoted
397 ContextTrieNode *NodeToPromo =
398 CallerNode->getChildContext(CallSite, CalleeName);
399 if (!NodeToPromo)
400 return;
401
402 promoteMergeContextSamplesTree(*NodeToPromo);
403}
404
406 ContextTrieNode &NodeToPromo) {
407 // Promote the input node to be directly under root. This can happen
408 // when we decided to not inline a function under context represented
409 // by the input node. The promote and merge is then needed to reflect
410 // the context profile in the base (context-less) profile.
411 FunctionSamples *FromSamples = NodeToPromo.getFunctionSamples();
412 assert(FromSamples && "Shouldn't promote a context without profile");
413 (void)FromSamples; // Unused in release build.
414
415 LLVM_DEBUG(dbgs() << " Found context tree root to promote: "
416 << getContextString(&NodeToPromo) << "\n");
417
418 assert(!FromSamples->getContext().hasState(InlinedContext) &&
419 "Shouldn't promote inlined context profile");
420 return promoteMergeContextSamplesTree(NodeToPromo, RootContext);
421}
422
423#ifndef NDEBUG
424std::string
427}
428
429std::string
432 if (Node == &RootContext)
433 return std::string();
434 Res.emplace_back(Node->getFuncName(), LineLocation(0, 0));
435
436 ContextTrieNode *PreNode = Node;
437 Node = Node->getParentContext();
438 while (Node && Node != &RootContext) {
439 Res.emplace_back(Node->getFuncName(), PreNode->getCallSiteLoc());
440 PreNode = Node;
441 Node = Node->getParentContext();
442 }
443
444 std::reverse(Res.begin(), Res.end());
445
447}
448#endif
449
450void SampleContextTracker::dump() { RootContext.dumpTree(); }
451
454 return Node->getFuncName().stringRef();
455 assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
456 return GUIDToFuncNameMap->lookup(Node->getFuncName().getHashCode());
457}
458
461 return getOrCreateContextPath(Context, false);
462}
463
465SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
466 FunctionId CalleeName) {
467 assert(DIL && "Expect non-null location");
468
469 ContextTrieNode *CallContext = getContextFor(DIL);
470 if (!CallContext)
471 return nullptr;
472
473 // When CalleeName is empty, the child context profile with max
474 // total samples will be returned.
475 return CallContext->getChildContext(
477}
478
480 assert(DIL && "Expect non-null location");
482
483 // Use C++ linkage name if possible.
484 const DILocation *PrevDIL = DIL;
485 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
486 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
487 if (Name.empty())
488 Name = PrevDIL->getScope()->getSubprogram()->getName();
489 S.push_back(
490 std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL),
492 PrevDIL = DIL;
493 }
494
495 // Push root node, note that root node like main may only
496 // a name, but not linkage name.
497 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
498 if (RootName.empty())
499 RootName = PrevDIL->getScope()->getSubprogram()->getName();
500 S.push_back(std::make_pair(LineLocation(0, 0),
501 getRepInFormat(RootName)));
502
503 ContextTrieNode *ContextNode = &RootContext;
504 int I = S.size();
505 while (--I >= 0 && ContextNode) {
506 LineLocation &CallSite = S[I].first;
507 FunctionId CalleeName = S[I].second;
508 ContextNode = ContextNode->getChildContext(CallSite, CalleeName);
509 }
510
511 if (I < 0)
512 return ContextNode;
513
514 return nullptr;
515}
516
519 bool AllowCreate) {
520 ContextTrieNode *ContextNode = &RootContext;
521 LineLocation CallSiteLoc(0, 0);
522
523 for (const auto &Callsite : Context.getContextFrames()) {
524 // Create child node at parent line/disc location
525 if (AllowCreate) {
526 ContextNode =
527 ContextNode->getOrCreateChildContext(CallSiteLoc, Callsite.Func);
528 } else {
529 ContextNode =
530 ContextNode->getChildContext(CallSiteLoc, Callsite.Func);
531 }
532 CallSiteLoc = Callsite.Location;
533 }
534
535 assert((!AllowCreate || ContextNode) &&
536 "Node must exist if creation is allowed");
537 return ContextNode;
538}
539
541SampleContextTracker::getTopLevelContextNode(FunctionId FName) {
542 assert(!FName.empty() && "Top level node query must provide valid name");
543 return RootContext.getChildContext(LineLocation(0, 0), FName);
544}
545
547SampleContextTracker::addTopLevelContextNode(FunctionId FName) {
548 assert(!getTopLevelContextNode(FName) && "Node to add must not exist");
549 return *RootContext.getOrCreateChildContext(LineLocation(0, 0), FName);
550}
551
552void SampleContextTracker::mergeContextNode(ContextTrieNode &FromNode,
553 ContextTrieNode &ToNode) {
554 FunctionSamples *FromSamples = FromNode.getFunctionSamples();
555 FunctionSamples *ToSamples = ToNode.getFunctionSamples();
556 if (FromSamples && ToSamples) {
557 // Merge/duplicate FromSamples into ToSamples
558 ToSamples->merge(*FromSamples);
560 FromSamples->getContext().setState(MergedContext);
563 } else if (FromSamples) {
564 // Transfer FromSamples from FromNode to ToNode
565 ToNode.setFunctionSamples(FromSamples);
566 setContextNode(FromSamples, &ToNode);
567 FromSamples->getContext().setState(SyntheticContext);
568 }
569}
570
572 ContextTrieNode &FromNode, ContextTrieNode &ToNodeParent) {
573
574 // Ignore call site location if destination is top level under root
575 LineLocation NewCallSiteLoc = LineLocation(0, 0);
576 LineLocation OldCallSiteLoc = FromNode.getCallSiteLoc();
577 ContextTrieNode &FromNodeParent = *FromNode.getParentContext();
578 ContextTrieNode *ToNode = nullptr;
579 bool MoveToRoot = (&ToNodeParent == &RootContext);
580 if (!MoveToRoot) {
581 NewCallSiteLoc = OldCallSiteLoc;
582 }
583
584 // Locate destination node, create/move if not existing
585 ToNode = ToNodeParent.getChildContext(NewCallSiteLoc, FromNode.getFuncName());
586 if (!ToNode) {
587 // Do not delete node to move from its parent here because
588 // caller is iterating over children of that parent node.
589 ToNode =
590 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));
591 LLVM_DEBUG({
592 dbgs() << " Context promoted and merged to: " << getContextString(ToNode)
593 << "\n";
594 });
595 } else {
596 // Destination node exists, merge samples for the context tree
597 mergeContextNode(FromNode, *ToNode);
598 LLVM_DEBUG({
599 if (ToNode->getFunctionSamples())
600 dbgs() << " Context promoted and merged to: "
601 << getContextString(ToNode) << "\n";
602 });
603
604 // Recursively promote and merge children
605 for (auto &It : FromNode.getAllChildContext()) {
606 ContextTrieNode &FromChildNode = It.second;
607 promoteMergeContextSamplesTree(FromChildNode, *ToNode);
608 }
609
610 // Remove children once they're all merged
611 FromNode.getAllChildContext().clear();
612 }
613
614 // For root of subtree, remove itself from old parent too
615 if (MoveToRoot)
616 FromNodeParent.removeChildContext(OldCallSiteLoc, ToNode->getFuncName());
617
618 return *ToNode;
619}
620
622 SampleProfileMap &ContextLessProfiles) {
623 for (auto *Node : *this) {
624 FunctionSamples *FProfile = Node->getFunctionSamples();
625 // Profile's context can be empty, use ContextNode's func name.
626 if (FProfile)
627 ContextLessProfiles.create(Node->getFuncName()).merge(*FProfile);
628 }
629}
630} // namespace llvm
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
#define I(x, y, z)
Definition: MD5.cpp:58
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...
Definition: InstrTypes.h:1236
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)
Debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Definition: Instruction.h:466
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
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)
FunctionSamples * getCalleeContextSamplesFor(const CallBase &Inst, StringRef CalleeName)
ContextTrieNode * getContextFor(const SampleContext &Context)
size_t size() const
Definition: SmallVector.h:92
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:951
void push_back(const T &Elt)
Definition: SmallVector.h:427
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
This class represents a function that is read from a sample profile.
Definition: FunctionId.h:36
Representation of the samples collected for a function.
Definition: SampleProf.h:745
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.
Definition: SampleProf.h:1163
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
Definition: SampleProf.h:1090
SampleContext & getContext() const
Definition: SampleProf.h:1192
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
Definition: SampleProf.h:934
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
Definition: SampleProf.h:998
static LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
Definition: SampleProf.cpp:221
static bool UseMD5
Whether the profile uses MD5 to represent string.
Definition: SampleProf.h:1197
bool hasState(ContextStateMask S)
Definition: SampleProf.h:612
SampleContextFrames getContextFrames() const
Definition: SampleProf.h:618
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
Definition: SampleProf.h:620
void setState(ContextStateMask S)
Definition: SampleProf.h:613
void setAttribute(ContextAttributeMask A)
Definition: SampleProf.h:609
bool hasAttribute(ContextAttributeMask A)
Definition: SampleProf.h:608
std::string toString() const
Definition: SampleProf.h:633
This class provides operator overloads to the map container using MD5 as the key type,...
Definition: SampleProf.h:1313
mapped_type & create(const SampleContext &Ctx)
Definition: SampleProf.h:1317
static FunctionId getRepInFormat(StringRef Name)
Get the proper representation of a string according to whether the current Format uses MD5 to represe...
Definition: SampleProf.h:1299
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Represents the relative location of an instruction.
Definition: SampleProf.h:280