LLVM 17.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/StringMap.h"
15#include "llvm/ADT/StringRef.h"
17#include "llvm/IR/InstrTypes.h"
18#include "llvm/IR/Instruction.h"
20#include <map>
21#include <queue>
22#include <vector>
23
24using namespace llvm;
25using namespace sampleprof;
26
27#define DEBUG_TYPE "sample-context-tracker"
28
29namespace llvm {
30
32 StringRef CalleeName) {
33 if (CalleeName.empty())
34 return getHottestChildContext(CallSite);
35
36 uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
37 auto It = AllChildContext.find(Hash);
38 if (It != AllChildContext.end())
39 return &It->second;
40 return nullptr;
41}
42
45 // CSFDO-TODO: This could be slow, change AllChildContext so we can
46 // do point look up for child node by call site alone.
47 // Retrieve the child node with max count for indirect call
48 ContextTrieNode *ChildNodeRet = nullptr;
49 uint64_t MaxCalleeSamples = 0;
50 for (auto &It : AllChildContext) {
51 ContextTrieNode &ChildNode = It.second;
52 if (ChildNode.CallSiteLoc != CallSite)
53 continue;
54 FunctionSamples *Samples = ChildNode.getFunctionSamples();
55 if (!Samples)
56 continue;
57 if (Samples->getTotalSamples() > MaxCalleeSamples) {
58 ChildNodeRet = &ChildNode;
59 MaxCalleeSamples = Samples->getTotalSamples();
60 }
61 }
62
63 return ChildNodeRet;
64}
65
67SampleContextTracker::moveContextSamples(ContextTrieNode &ToNodeParent,
68 const LineLocation &CallSite,
69 ContextTrieNode &&NodeToMove) {
70 uint64_t Hash =
71 FunctionSamples::getCallSiteHash(NodeToMove.getFuncName(), CallSite);
72 std::map<uint64_t, ContextTrieNode> &AllChildContext =
73 ToNodeParent.getAllChildContext();
74 assert(!AllChildContext.count(Hash) && "Node to remove must exist");
75 AllChildContext[Hash] = NodeToMove;
76 ContextTrieNode &NewNode = AllChildContext[Hash];
77 NewNode.setCallSiteLoc(CallSite);
78
79 // Walk through nodes in the moved the subtree, and update
80 // FunctionSamples' context as for the context promotion.
81 // We also need to set new parant link for all children.
82 std::queue<ContextTrieNode *> NodeToUpdate;
83 NewNode.setParentContext(&ToNodeParent);
84 NodeToUpdate.push(&NewNode);
85
86 while (!NodeToUpdate.empty()) {
87 ContextTrieNode *Node = NodeToUpdate.front();
88 NodeToUpdate.pop();
89 FunctionSamples *FSamples = Node->getFunctionSamples();
90
91 if (FSamples) {
92 setContextNode(FSamples, Node);
94 }
95
96 for (auto &It : Node->getAllChildContext()) {
97 ContextTrieNode *ChildNode = &It.second;
98 ChildNode->setParentContext(Node);
99 NodeToUpdate.push(ChildNode);
100 }
101 }
102
103 return NewNode;
104}
105
107 StringRef CalleeName) {
108 uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
109 // Note this essentially calls dtor and destroys that child context
110 AllChildContext.erase(Hash);
111}
112
113std::map<uint64_t, ContextTrieNode> &ContextTrieNode::getAllChildContext() {
114 return AllChildContext;
115}
116
117StringRef ContextTrieNode::getFuncName() const { return FuncName; }
118
120 return FuncSamples;
121}
122
124 FuncSamples = FSamples;
125}
126
127std::optional<uint32_t> ContextTrieNode::getFunctionSize() const {
128 return FuncSize;
129}
130
132 if (!FuncSize)
133 FuncSize = 0;
134
135 FuncSize = *FuncSize + FSize;
136}
137
138LineLocation ContextTrieNode::getCallSiteLoc() const { return CallSiteLoc; }
139
141 return ParentContext;
142}
143
145 ParentContext = Parent;
146}
147
149 CallSiteLoc = Loc;
150}
151
153 dbgs() << "Node: " << FuncName << "\n"
154 << " Callsite: " << CallSiteLoc << "\n"
155 << " Size: " << FuncSize << "\n"
156 << " Children:\n";
157
158 for (auto &It : AllChildContext) {
159 dbgs() << " Node: " << It.second.getFuncName() << "\n";
160 }
161}
162
164 dbgs() << "Context Profile Tree:\n";
165 std::queue<ContextTrieNode *> NodeQueue;
166 NodeQueue.push(this);
167
168 while (!NodeQueue.empty()) {
169 ContextTrieNode *Node = NodeQueue.front();
170 NodeQueue.pop();
171 Node->dumpNode();
172
173 for (auto &It : Node->getAllChildContext()) {
174 ContextTrieNode *ChildNode = &It.second;
175 NodeQueue.push(ChildNode);
176 }
177 }
178}
179
181 const LineLocation &CallSite, StringRef CalleeName, bool AllowCreate) {
182 uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
183 auto It = AllChildContext.find(Hash);
184 if (It != AllChildContext.end()) {
185 assert(It->second.getFuncName() == CalleeName &&
186 "Hash collision for child context node");
187 return &It->second;
188 }
189
190 if (!AllowCreate)
191 return nullptr;
192
193 AllChildContext[Hash] = ContextTrieNode(this, CalleeName, nullptr, CallSite);
194 return &AllChildContext[Hash];
195}
196
197// Profiler tracker than manages profiles and its associated context
199 SampleProfileMap &Profiles,
200 const DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap)
201 : GUIDToFuncNameMap(GUIDToFuncNameMap) {
202 for (auto &FuncSample : Profiles) {
203 FunctionSamples *FSamples = &FuncSample.second;
204 SampleContext Context = FuncSample.first;
205 LLVM_DEBUG(dbgs() << "Tracking Context for function: " << Context.toString()
206 << "\n");
208 assert(!NewNode->getFunctionSamples() &&
209 "New node can't have sample profile");
210 NewNode->setFunctionSamples(FSamples);
211 }
213}
214
216 for (auto *Node : *this) {
217 FunctionSamples *FSamples = Node->getFunctionSamples();
218 if (FSamples) {
219 FSamples->getContext().setState(RawContext);
220 setContextNode(FSamples, Node);
221 FuncToCtxtProfiles[Node->getFuncName()].push_back(FSamples);
222 }
223 }
224}
225
228 StringRef CalleeName) {
229 LLVM_DEBUG(dbgs() << "Getting callee context for instr: " << Inst << "\n");
230 DILocation *DIL = Inst.getDebugLoc();
231 if (!DIL)
232 return nullptr;
233
234 CalleeName = FunctionSamples::getCanonicalFnName(CalleeName);
235 // Convert real function names to MD5 names, if the input profile is
236 // MD5-based.
237 std::string FGUID;
238 CalleeName = getRepInFormat(CalleeName, FunctionSamples::UseMD5, FGUID);
239
240 // For indirect call, CalleeName will be empty, in which case the context
241 // profile for callee with largest total samples will be returned.
242 ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, CalleeName);
243 if (CalleeContext) {
244 FunctionSamples *FSamples = CalleeContext->getFunctionSamples();
245 LLVM_DEBUG(if (FSamples) {
246 dbgs() << " Callee context found: " << getContextString(CalleeContext)
247 << "\n";
248 });
249 return FSamples;
250 }
251
252 return nullptr;
253}
254
255std::vector<const FunctionSamples *>
257 const DILocation *DIL) {
258 std::vector<const FunctionSamples *> R;
259 if (!DIL)
260 return R;
261
262 ContextTrieNode *CallerNode = getContextFor(DIL);
264 for (auto &It : CallerNode->getAllChildContext()) {
265 ContextTrieNode &ChildNode = It.second;
266 if (ChildNode.getCallSiteLoc() != CallSite)
267 continue;
268 if (FunctionSamples *CalleeSamples = ChildNode.getFunctionSamples())
269 R.push_back(CalleeSamples);
270 }
271
272 return R;
273}
274
277 assert(DIL && "Expect non-null location");
278
279 ContextTrieNode *ContextNode = getContextFor(DIL);
280 if (!ContextNode)
281 return nullptr;
282
283 // We may have inlined callees during pre-LTO compilation, in which case
284 // we need to rely on the inline stack from !dbg to mark context profile
285 // as inlined, instead of `MarkContextSamplesInlined` during inlining.
286 // Sample profile loader walks through all instructions to get profile,
287 // which calls this function. So once that is done, all previously inlined
288 // context profile should be marked properly.
289 FunctionSamples *Samples = ContextNode->getFunctionSamples();
290 if (Samples && ContextNode->getParentContext() != &RootContext)
292
293 return Samples;
294}
295
299 if (!Node)
300 return nullptr;
301
302 return Node->getFunctionSamples();
303}
304
308 return FuncToCtxtProfiles[CanonName];
309}
310
313 return FuncToCtxtProfiles[Name];
314}
315
317 bool MergeContext) {
319 return getBaseSamplesFor(CanonName, MergeContext);
320}
321
323 bool MergeContext) {
324 LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");
325 // Convert real function names to MD5 names, if the input profile is
326 // MD5-based.
327 std::string FGUID;
329
330 // Base profile is top-level node (child of root node), so try to retrieve
331 // existing top-level node for given function first. If it exists, it could be
332 // that we've merged base profile before, or there's actually context-less
333 // profile from the input (e.g. due to unreliable stack walking).
334 ContextTrieNode *Node = getTopLevelContextNode(Name);
335 if (MergeContext) {
336 LLVM_DEBUG(dbgs() << " Merging context profile into base profile: " << Name
337 << "\n");
338
339 // We have profile for function under different contexts,
340 // create synthetic base profile and merge context profiles
341 // into base profile.
342 for (auto *CSamples : FuncToCtxtProfiles[Name]) {
343 SampleContext &Context = CSamples->getContext();
344 // Skip inlined context profile and also don't re-merge any context
345 if (Context.hasState(InlinedContext) || Context.hasState(MergedContext))
346 continue;
347
348 ContextTrieNode *FromNode = getContextNodeForProfile(CSamples);
349 if (FromNode == Node)
350 continue;
351
353 assert((!Node || Node == &ToNode) && "Expect only one base profile");
354 Node = &ToNode;
355 }
356 }
357
358 // Still no profile even after merge/promotion (if allowed)
359 if (!Node)
360 return nullptr;
361
362 return Node->getFunctionSamples();
363}
364
366 const FunctionSamples *InlinedSamples) {
367 assert(InlinedSamples && "Expect non-null inlined samples");
368 LLVM_DEBUG(dbgs() << "Marking context profile as inlined: "
369 << getContextString(*InlinedSamples) << "\n");
370 InlinedSamples->getContext().setState(InlinedContext);
371}
372
374
376 const Instruction &Inst, StringRef CalleeName) {
377 LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"
378 << Inst << "\n");
379 // Get the caller context for the call instruction, we don't use callee
380 // name from call because there can be context from indirect calls too.
381 DILocation *DIL = Inst.getDebugLoc();
382 ContextTrieNode *CallerNode = getContextFor(DIL);
383 if (!CallerNode)
384 return;
385
386 // Get the context that needs to be promoted
388 // For indirect call, CalleeName will be empty, in which case we need to
389 // promote all non-inlined child context profiles.
390 if (CalleeName.empty()) {
391 for (auto &It : CallerNode->getAllChildContext()) {
392 ContextTrieNode *NodeToPromo = &It.second;
393 if (CallSite != NodeToPromo->getCallSiteLoc())
394 continue;
395 FunctionSamples *FromSamples = NodeToPromo->getFunctionSamples();
396 if (FromSamples && FromSamples->getContext().hasState(InlinedContext))
397 continue;
398 promoteMergeContextSamplesTree(*NodeToPromo);
399 }
400 return;
401 }
402
403 // Get the context for the given callee that needs to be promoted
404 ContextTrieNode *NodeToPromo =
405 CallerNode->getChildContext(CallSite, CalleeName);
406 if (!NodeToPromo)
407 return;
408
409 promoteMergeContextSamplesTree(*NodeToPromo);
410}
411
413 ContextTrieNode &NodeToPromo) {
414 // Promote the input node to be directly under root. This can happen
415 // when we decided to not inline a function under context represented
416 // by the input node. The promote and merge is then needed to reflect
417 // the context profile in the base (context-less) profile.
418 FunctionSamples *FromSamples = NodeToPromo.getFunctionSamples();
419 assert(FromSamples && "Shouldn't promote a context without profile");
420 (void)FromSamples; // Unused in release build.
421
422 LLVM_DEBUG(dbgs() << " Found context tree root to promote: "
423 << getContextString(&NodeToPromo) << "\n");
424
425 assert(!FromSamples->getContext().hasState(InlinedContext) &&
426 "Shouldn't promote inlined context profile");
427 return promoteMergeContextSamplesTree(NodeToPromo, RootContext);
428}
429
430#ifndef NDEBUG
431std::string
434}
435
436std::string
439 if (Node == &RootContext)
440 return std::string();
441 Res.emplace_back(Node->getFuncName(), LineLocation(0, 0));
442
443 ContextTrieNode *PreNode = Node;
444 Node = Node->getParentContext();
445 while (Node && Node != &RootContext) {
446 Res.emplace_back(Node->getFuncName(), PreNode->getCallSiteLoc());
447 PreNode = Node;
448 Node = Node->getParentContext();
449 }
450
451 std::reverse(Res.begin(), Res.end());
452
454}
455#endif
456
457void SampleContextTracker::dump() { RootContext.dumpTree(); }
458
461 return Node->getFuncName();
462 assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
463 return GUIDToFuncNameMap->lookup(std::stoull(Node->getFuncName().data()));
464}
465
468 return getOrCreateContextPath(Context, false);
469}
470
472SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
473 StringRef CalleeName) {
474 assert(DIL && "Expect non-null location");
475
476 ContextTrieNode *CallContext = getContextFor(DIL);
477 if (!CallContext)
478 return nullptr;
479
480 // When CalleeName is empty, the child context profile with max
481 // total samples will be returned.
482 return CallContext->getChildContext(
484}
485
487 assert(DIL && "Expect non-null location");
489
490 // Use C++ linkage name if possible.
491 const DILocation *PrevDIL = DIL;
492 for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
493 StringRef Name = PrevDIL->getScope()->getSubprogram()->getLinkageName();
494 if (Name.empty())
495 Name = PrevDIL->getScope()->getSubprogram()->getName();
496 S.push_back(
497 std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL), Name));
498 PrevDIL = DIL;
499 }
500
501 // Push root node, note that root node like main may only
502 // a name, but not linkage name.
503 StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
504 if (RootName.empty())
505 RootName = PrevDIL->getScope()->getSubprogram()->getName();
506 S.push_back(std::make_pair(LineLocation(0, 0), RootName));
507
508 // Convert real function names to MD5 names, if the input profile is
509 // MD5-based.
510 std::list<std::string> MD5Names;
512 for (auto &Location : S) {
513 MD5Names.emplace_back();
514 getRepInFormat(Location.second, FunctionSamples::UseMD5, MD5Names.back());
515 Location.second = MD5Names.back();
516 }
517 }
518
519 ContextTrieNode *ContextNode = &RootContext;
520 int I = S.size();
521 while (--I >= 0 && ContextNode) {
522 LineLocation &CallSite = S[I].first;
523 StringRef CalleeName = S[I].second;
524 ContextNode = ContextNode->getChildContext(CallSite, CalleeName);
525 }
526
527 if (I < 0)
528 return ContextNode;
529
530 return nullptr;
531}
532
535 bool AllowCreate) {
536 ContextTrieNode *ContextNode = &RootContext;
537 LineLocation CallSiteLoc(0, 0);
538
539 for (const auto &Callsite : Context.getContextFrames()) {
540 // Create child node at parent line/disc location
541 if (AllowCreate) {
542 ContextNode =
543 ContextNode->getOrCreateChildContext(CallSiteLoc, Callsite.FuncName);
544 } else {
545 ContextNode =
546 ContextNode->getChildContext(CallSiteLoc, Callsite.FuncName);
547 }
548 CallSiteLoc = Callsite.Location;
549 }
550
551 assert((!AllowCreate || ContextNode) &&
552 "Node must exist if creation is allowed");
553 return ContextNode;
554}
555
556ContextTrieNode *SampleContextTracker::getTopLevelContextNode(StringRef FName) {
557 assert(!FName.empty() && "Top level node query must provide valid name");
558 return RootContext.getChildContext(LineLocation(0, 0), FName);
559}
560
561ContextTrieNode &SampleContextTracker::addTopLevelContextNode(StringRef FName) {
562 assert(!getTopLevelContextNode(FName) && "Node to add must not exist");
563 return *RootContext.getOrCreateChildContext(LineLocation(0, 0), FName);
564}
565
566void SampleContextTracker::mergeContextNode(ContextTrieNode &FromNode,
567 ContextTrieNode &ToNode) {
568 FunctionSamples *FromSamples = FromNode.getFunctionSamples();
569 FunctionSamples *ToSamples = ToNode.getFunctionSamples();
570 if (FromSamples && ToSamples) {
571 // Merge/duplicate FromSamples into ToSamples
572 ToSamples->merge(*FromSamples);
574 FromSamples->getContext().setState(MergedContext);
577 } else if (FromSamples) {
578 // Transfer FromSamples from FromNode to ToNode
579 ToNode.setFunctionSamples(FromSamples);
580 setContextNode(FromSamples, &ToNode);
581 FromSamples->getContext().setState(SyntheticContext);
582 }
583}
584
586 ContextTrieNode &FromNode, ContextTrieNode &ToNodeParent) {
587
588 // Ignore call site location if destination is top level under root
589 LineLocation NewCallSiteLoc = LineLocation(0, 0);
590 LineLocation OldCallSiteLoc = FromNode.getCallSiteLoc();
591 ContextTrieNode &FromNodeParent = *FromNode.getParentContext();
592 ContextTrieNode *ToNode = nullptr;
593 bool MoveToRoot = (&ToNodeParent == &RootContext);
594 if (!MoveToRoot) {
595 NewCallSiteLoc = OldCallSiteLoc;
596 }
597
598 // Locate destination node, create/move if not existing
599 ToNode = ToNodeParent.getChildContext(NewCallSiteLoc, FromNode.getFuncName());
600 if (!ToNode) {
601 // Do not delete node to move from its parent here because
602 // caller is iterating over children of that parent node.
603 ToNode =
604 &moveContextSamples(ToNodeParent, NewCallSiteLoc, std::move(FromNode));
605 LLVM_DEBUG({
606 dbgs() << " Context promoted and merged to: " << getContextString(ToNode)
607 << "\n";
608 });
609 } else {
610 // Destination node exists, merge samples for the context tree
611 mergeContextNode(FromNode, *ToNode);
612 LLVM_DEBUG({
613 if (ToNode->getFunctionSamples())
614 dbgs() << " Context promoted and merged to: "
615 << getContextString(ToNode) << "\n";
616 });
617
618 // Recursively promote and merge children
619 for (auto &It : FromNode.getAllChildContext()) {
620 ContextTrieNode &FromChildNode = It.second;
621 promoteMergeContextSamplesTree(FromChildNode, *ToNode);
622 }
623
624 // Remove children once they're all merged
625 FromNode.getAllChildContext().clear();
626 }
627
628 // For root of subtree, remove itself from old parent too
629 if (MoveToRoot)
630 FromNodeParent.removeChildContext(OldCallSiteLoc, ToNode->getFuncName());
631
632 return *ToNode;
633}
634
636 SampleProfileMap &ContextLessProfiles) {
637 for (auto *Node : *this) {
638 FunctionSamples *FProfile = Node->getFunctionSamples();
639 // Profile's context can be empty, use ContextNode's func name.
640 if (FProfile)
641 ContextLessProfiles[Node->getFuncName()].merge(*FProfile);
642 }
643}
644} // namespace llvm
This file defines the StringMap class.
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
#define I(x, y, z)
Definition: MD5.cpp:58
LLVMContext & Context
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:1184
std::map< uint64_t, ContextTrieNode > & getAllChildContext()
ContextTrieNode * getOrCreateChildContext(const LineLocation &CallSite, StringRef ChildName, bool AllowCreate=true)
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)
Debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Definition: Instruction.h:358
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
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)
FunctionSamples * getCalleeContextSamplesFor(const CallBase &Inst, StringRef CalleeName)
ContextTrieNode * getContextFor(const SampleContext &Context)
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:941
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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
Representation of the samples collected for a function.
Definition: SampleProf.h:718
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
Definition: SampleProf.h:1028
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.
Definition: SampleProf.cpp:238
SampleContext & getContext() const
Definition: SampleProf.h:1124
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
Definition: SampleProf.h:883
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
Definition: SampleProf.h:947
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:1129
bool hasState(ContextStateMask S)
Definition: SampleProf.h:592
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
Definition: SampleProf.h:600
void setState(ContextStateMask S)
Definition: SampleProf.h:593
void setAttribute(ContextAttributeMask A)
Definition: SampleProf.h:589
bool hasAttribute(ContextAttributeMask A)
Definition: SampleProf.h:588
std::unordered_map< SampleContext, FunctionSamples, SampleContext::Hash > SampleProfileMap
Definition: SampleProf.h:1199
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...
Definition: SampleProf.h:108
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:283