LLVM 22.0.0git
SampleProf.h
Go to the documentation of this file.
1//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===//
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 contains common definitions used in the reading and writing of
10// sample profile data.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H
15#define LLVM_PROFILEDATA_SAMPLEPROF_H
16
17#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/GlobalValue.h"
28#include "llvm/Support/Debug.h"
31#include <algorithm>
32#include <cstdint>
33#include <list>
34#include <map>
35#include <set>
36#include <sstream>
37#include <string>
38#include <system_error>
39#include <unordered_map>
40#include <utility>
41
42namespace llvm {
43
44class DILocation;
45class raw_ostream;
46
47LLVM_ABI const std::error_category &sampleprof_category();
48
67
68inline std::error_code make_error_code(sampleprof_error E) {
69 return std::error_code(static_cast<int>(E), sampleprof_category());
70}
71
73 sampleprof_error Result) {
74 // Prefer first error encountered as later errors may be secondary effects of
75 // the initial problem.
78 Accumulator = Result;
79 return Accumulator;
80}
81
82} // end namespace llvm
83
84namespace std {
85
86template <>
87struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
88
89} // end namespace std
90
91namespace llvm {
92namespace sampleprof {
93
96 SPF_Text = 0x1,
97 SPF_Compact_Binary = 0x2, // Deprecated
98 SPF_GCC = 0x3,
101};
102
108
110 return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) |
111 uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) |
112 uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) |
113 uint64_t('2') << (64 - 56) | uint64_t(Format);
114}
115
116static inline uint64_t SPVersion() { return 103; }
117
118// Section Type used by SampleProfileExtBinaryBaseReader and
119// SampleProfileExtBinaryBaseWriter. Never change the existing
120// value of enum. Only append new ones.
133
134static inline std::string getSecName(SecType Type) {
135 switch (static_cast<int>(Type)) { // Avoid -Wcovered-switch-default
136 case SecInValid:
137 return "InvalidSection";
138 case SecProfSummary:
139 return "ProfileSummarySection";
140 case SecNameTable:
141 return "NameTableSection";
143 return "ProfileSymbolListSection";
145 return "FuncOffsetTableSection";
146 case SecFuncMetadata:
147 return "FunctionMetadata";
148 case SecCSNameTable:
149 return "CSNameTableSection";
150 case SecLBRProfile:
151 return "LBRProfileSection";
152 default:
153 return "UnknownSection";
154 }
155}
156
157// Entry type of section header table used by SampleProfileExtBinaryBaseReader
158// and SampleProfileExtBinaryBaseWriter.
164 // The index indicating the location of the current entry in
165 // SectionHdrLayout table.
167};
168
169// Flags common for all sections are defined here. In SecHdrTableEntry::Flags,
170// common flags will be saved in the lower 32bits and section specific flags
171// will be saved in the higher 32 bits.
174 SecFlagCompress = (1 << 0),
175 // Indicate the section contains only profile without context.
176 SecFlagFlat = (1 << 1)
177};
178
179// Section specific flags are defined here.
180// !!!Note: Everytime a new enum class is created here, please add
181// a new check in verifySecFlag.
184 SecFlagMD5Name = (1 << 0),
185 // Store MD5 in fixed length instead of ULEB128 so NameTable can be
186 // accessed like an array.
188 // Profile contains ".__uniq." suffix name. Compiler shouldn't strip
189 // the suffix when doing profile matching when seeing the flag.
191};
194 /// SecFlagPartial means the profile is for common/shared code.
195 /// The common profile is usually merged from profiles collected
196 /// from running other targets.
197 SecFlagPartial = (1 << 0),
198 /// SecFlagContext means this is context-sensitive flat profile for
199 /// CSSPGO
201 /// SecFlagFSDiscriminator means this profile uses flow-sensitive
202 /// discriminators.
204 /// SecFlagIsPreInlined means this profile contains ShouldBeInlined
205 /// contexts thus this is CS preinliner computed.
207};
208
214
217 // Store function offsets in an order of contexts. The order ensures that
218 // callee contexts of a given context laid out next to it.
219 SecFlagOrdered = (1 << 0),
220};
221
222// Verify section specific flag is used for the correct section.
223template <class SecFlagType>
224static inline void verifySecFlag(SecType Type, SecFlagType Flag) {
225 // No verification is needed for common flags.
226 if (std::is_same<SecCommonFlags, SecFlagType>())
227 return;
228
229 // Verification starts here for section specific flag.
230 bool IsFlagLegal = false;
231 switch (Type) {
232 case SecNameTable:
233 IsFlagLegal = std::is_same<SecNameTableFlags, SecFlagType>();
234 break;
235 case SecProfSummary:
236 IsFlagLegal = std::is_same<SecProfSummaryFlags, SecFlagType>();
237 break;
238 case SecFuncMetadata:
239 IsFlagLegal = std::is_same<SecFuncMetadataFlags, SecFlagType>();
240 break;
241 default:
243 IsFlagLegal = std::is_same<SecFuncOffsetFlags, SecFlagType>();
244 break;
245 }
246 if (!IsFlagLegal)
247 llvm_unreachable("Misuse of a flag in an incompatible section");
248}
249
250template <class SecFlagType>
251static inline void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) {
252 verifySecFlag(Entry.Type, Flag);
253 auto FVal = static_cast<uint64_t>(Flag);
254 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
255 Entry.Flags |= IsCommon ? FVal : (FVal << 32);
256}
257
258template <class SecFlagType>
259static inline void removeSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) {
260 verifySecFlag(Entry.Type, Flag);
261 auto FVal = static_cast<uint64_t>(Flag);
262 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
263 Entry.Flags &= ~(IsCommon ? FVal : (FVal << 32));
264}
265
266template <class SecFlagType>
267static inline bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag) {
268 verifySecFlag(Entry.Type, Flag);
269 auto FVal = static_cast<uint64_t>(Flag);
270 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
271 return Entry.Flags & (IsCommon ? FVal : (FVal << 32));
272}
273
274/// Represents the relative location of an instruction.
275///
276/// Instruction locations are specified by the line offset from the
277/// beginning of the function (marked by the line where the function
278/// header is) and the discriminator value within that line.
279///
280/// The discriminator value is useful to distinguish instructions
281/// that are on the same line but belong to different basic blocks
282/// (e.g., the two post-increment instructions in "if (p) x++; else y++;").
285
286 LLVM_ABI void print(raw_ostream &OS) const;
287 LLVM_ABI void dump() const;
288
289 // Serialize the line location to the output stream using ULEB128 encoding.
290 LLVM_ABI void serialize(raw_ostream &OS) const;
291
292 bool operator<(const LineLocation &O) const {
293 return std::tie(LineOffset, Discriminator) <
294 std::tie(O.LineOffset, O.Discriminator);
295 }
296
297 bool operator==(const LineLocation &O) const {
298 return LineOffset == O.LineOffset && Discriminator == O.Discriminator;
299 }
300
301 bool operator!=(const LineLocation &O) const {
302 return LineOffset != O.LineOffset || Discriminator != O.Discriminator;
303 }
304
306 return ((uint64_t) Discriminator << 32) | LineOffset;
307 }
308
311};
312
315 return Loc.getHashCode();
316 }
317};
318
320
321/// Representation of a single sample record.
322///
323/// A sample record is represented by a positive integer value, which
324/// indicates how frequently was the associated line location executed.
325///
326/// Additionally, if the associated location contains a function call,
327/// the record will hold a list of all the possible called targets. For
328/// direct calls, this will be the exact function being invoked. For
329/// indirect calls (function pointers, virtual table dispatch), this
330/// will be a list of one or more functions.
332public:
333 using CallTarget = std::pair<FunctionId, uint64_t>;
335 bool operator()(const CallTarget &LHS, const CallTarget &RHS) const {
336 if (LHS.second != RHS.second)
337 return LHS.second > RHS.second;
338
339 return LHS.first < RHS.first;
340 }
341 };
342
343 using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
344 using CallTargetMap = std::unordered_map<FunctionId, uint64_t>;
345 SampleRecord() = default;
346
347 /// Increment the number of samples for this record by \p S.
348 /// Optionally scale sample count \p S by \p Weight.
349 ///
350 /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
351 /// around unsigned integers.
353 bool Overflowed;
354 NumSamples = SaturatingMultiplyAdd(S, Weight, NumSamples, &Overflowed);
355 return Overflowed ? sampleprof_error::counter_overflow
357 }
358
359 /// Decrease the number of samples for this record by \p S. Return the amout
360 /// of samples actually decreased.
362 if (S > NumSamples)
363 S = NumSamples;
364 NumSamples -= S;
365 return S;
366 }
367
368 /// Add called function \p F with samples \p S.
369 /// Optionally scale sample count \p S by \p Weight.
370 ///
371 /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
372 /// around unsigned integers.
374 uint64_t Weight = 1) {
375 uint64_t &TargetSamples = CallTargets[F];
376 bool Overflowed;
377 TargetSamples =
378 SaturatingMultiplyAdd(S, Weight, TargetSamples, &Overflowed);
379 return Overflowed ? sampleprof_error::counter_overflow
381 }
382
383 /// Remove called function from the call target map. Return the target sample
384 /// count of the called function.
386 uint64_t Count = 0;
387 auto I = CallTargets.find(F);
388 if (I != CallTargets.end()) {
389 Count = I->second;
390 CallTargets.erase(I);
391 }
392 return Count;
393 }
394
395 /// Return true if this sample record contains function calls.
396 bool hasCalls() const { return !CallTargets.empty(); }
397
398 uint64_t getSamples() const { return NumSamples; }
399 const CallTargetMap &getCallTargets() const { return CallTargets; }
401 return sortCallTargets(CallTargets);
402 }
403
405 uint64_t Sum = 0;
406 for (const auto &I : CallTargets)
407 Sum += I.second;
408 return Sum;
409 }
410
411 /// Sort call targets in descending order of call frequency.
412 static const SortedCallTargetSet
414 SortedCallTargetSet SortedTargets;
415 for (const auto &[Target, Frequency] : Targets) {
416 SortedTargets.emplace(Target, Frequency);
417 }
418 return SortedTargets;
419 }
420
421 /// Prorate call targets by a distribution factor.
422 static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets,
423 float DistributionFactor) {
424 CallTargetMap AdjustedTargets;
425 for (const auto &[Target, Frequency] : Targets) {
426 AdjustedTargets[Target] = Frequency * DistributionFactor;
427 }
428 return AdjustedTargets;
429 }
430
431 /// Merge the samples in \p Other into this record.
432 /// Optionally scale sample counts by \p Weight.
434 uint64_t Weight = 1);
435 LLVM_ABI void print(raw_ostream &OS, unsigned Indent) const;
436 LLVM_ABI void dump() const;
437 /// Serialize the sample record to the output stream using ULEB128 encoding.
438 /// The \p NameTable is used to map function names to their IDs.
439 LLVM_ABI std::error_code
441 const MapVector<FunctionId, uint32_t> &NameTable) const;
442
443 bool operator==(const SampleRecord &Other) const {
444 return NumSamples == Other.NumSamples && CallTargets == Other.CallTargets;
445 }
446
447 bool operator!=(const SampleRecord &Other) const {
448 return !(*this == Other);
449 }
450
451private:
452 uint64_t NumSamples = 0;
453 CallTargetMap CallTargets;
454};
455
457
458// State of context associated with FunctionSamples
460 UnknownContext = 0x0, // Profile without context
461 RawContext = 0x1, // Full context profile from input profile
462 SyntheticContext = 0x2, // Synthetic context created for context promotion
463 InlinedContext = 0x4, // Profile for context that is inlined into caller
464 MergedContext = 0x8 // Profile for context merged into base profile
465};
466
467// Attribute of context associated with FunctionSamples
470 ContextWasInlined = 0x1, // Leaf of context was inlined in previous build
471 ContextShouldBeInlined = 0x2, // Leaf of context should be inlined
473 0x4, // Leaf of context is duplicated into the base profile
474};
475
476// Represents a context frame with profile function and line location
480
482
485
486 bool operator==(const SampleContextFrame &That) const {
487 return Location == That.Location && Func == That.Func;
488 }
489
490 bool operator!=(const SampleContextFrame &That) const {
491 return !(*this == That);
492 }
493
494 std::string toString(bool OutputLineLocation) const {
495 std::ostringstream OContextStr;
496 OContextStr << Func.str();
497 if (OutputLineLocation) {
498 OContextStr << ":" << Location.LineOffset;
499 if (Location.Discriminator)
500 OContextStr << "." << Location.Discriminator;
501 }
502 return OContextStr.str();
503 }
504
506 uint64_t NameHash = Func.getHashCode();
507 uint64_t LocId = Location.getHashCode();
508 return NameHash + (LocId << 5) + LocId;
509 }
510};
511
512static inline hash_code hash_value(const SampleContextFrame &arg) {
513 return arg.getHashCode();
514}
515
518
524
525// Sample context for FunctionSamples. It consists of the calling context,
526// the function name and context state. Internally sample context is represented
527// using ArrayRef, which is also the input for constructing a `SampleContext`.
528// It can accept and represent both full context string as well as context-less
529// function name.
530// For a CS profile, a full context vector can look like:
531// `main:3 _Z5funcAi:1 _Z8funcLeafi`
532// For a base CS profile without calling context, the context vector should only
533// contain the leaf frame name.
534// For a non-CS profile, the context vector should be empty.
536public:
537 SampleContext() : State(UnknownContext), Attributes(ContextNone) {}
538
540 : Func(Name), State(UnknownContext), Attributes(ContextNone) {
541 assert(!Name.empty() && "Name is empty");
542 }
543
545 : Func(Func), State(UnknownContext), Attributes(ContextNone) {}
546
549 : Attributes(ContextNone) {
550 assert(!Context.empty() && "Context is empty");
551 setContext(Context, CState);
552 }
553
554 // Give a context string, decode and populate internal states like
555 // Function name, Calling context and context state. Example of input
556 // `ContextStr`: `[main:3 @ _Z5funcAi:1 @ _Z8funcLeafi]`
558 std::list<SampleContextFrameVector> &CSNameTable,
560 : Attributes(ContextNone) {
561 assert(!ContextStr.empty());
562 // Note that `[]` wrapped input indicates a full context string, otherwise
563 // it's treated as context-less function name only.
564 bool HasContext = ContextStr.starts_with("[");
565 if (!HasContext) {
566 State = UnknownContext;
567 Func = FunctionId(ContextStr);
568 } else {
569 CSNameTable.emplace_back();
570 SampleContextFrameVector &Context = CSNameTable.back();
571 createCtxVectorFromStr(ContextStr, Context);
572 setContext(Context, CState);
573 }
574 }
575
576 /// Create a context vector from a given context string and save it in
577 /// `Context`.
578 static void createCtxVectorFromStr(StringRef ContextStr,
579 SampleContextFrameVector &Context) {
580 // Remove encapsulating '[' and ']' if any
581 ContextStr = ContextStr.substr(1, ContextStr.size() - 2);
582 StringRef ContextRemain = ContextStr;
583 StringRef ChildContext;
584 FunctionId Callee;
585 while (!ContextRemain.empty()) {
586 auto ContextSplit = ContextRemain.split(" @ ");
587 ChildContext = ContextSplit.first;
588 ContextRemain = ContextSplit.second;
589 LineLocation CallSiteLoc(0, 0);
590 decodeContextString(ChildContext, Callee, CallSiteLoc);
591 Context.emplace_back(Callee, CallSiteLoc);
592 }
593 }
594
595 // Decode context string for a frame to get function name and location.
596 // `ContextStr` is in the form of `FuncName:StartLine.Discriminator`.
597 static void decodeContextString(StringRef ContextStr,
598 FunctionId &Func,
599 LineLocation &LineLoc) {
600 // Get function name
601 auto EntrySplit = ContextStr.split(':');
602 Func = FunctionId(EntrySplit.first);
603
604 LineLoc = {0, 0};
605 if (!EntrySplit.second.empty()) {
606 // Get line offset, use signed int for getAsInteger so string will
607 // be parsed as signed.
608 int LineOffset = 0;
609 auto LocSplit = EntrySplit.second.split('.');
610 LocSplit.first.getAsInteger(10, LineOffset);
611 LineLoc.LineOffset = LineOffset;
612
613 // Get discriminator
614 if (!LocSplit.second.empty())
615 LocSplit.second.getAsInteger(10, LineLoc.Discriminator);
616 }
617 }
618
619 operator SampleContextFrames() const { return FullContext; }
620 bool hasAttribute(ContextAttributeMask A) { return Attributes & (uint32_t)A; }
621 void setAttribute(ContextAttributeMask A) { Attributes |= (uint32_t)A; }
622 uint32_t getAllAttributes() { return Attributes; }
623 void setAllAttributes(uint32_t A) { Attributes = A; }
624 bool hasState(ContextStateMask S) { return State & (uint32_t)S; }
625 void setState(ContextStateMask S) { State |= (uint32_t)S; }
626 void clearState(ContextStateMask S) { State &= (uint32_t)~S; }
627 bool hasContext() const { return State != UnknownContext; }
628 bool isBaseContext() const { return FullContext.size() == 1; }
629 FunctionId getFunction() const { return Func; }
630 SampleContextFrames getContextFrames() const { return FullContext; }
631
632 static std::string getContextString(SampleContextFrames Context,
633 bool IncludeLeafLineLocation = false) {
634 std::ostringstream OContextStr;
635 for (uint32_t I = 0; I < Context.size(); I++) {
636 if (OContextStr.str().size()) {
637 OContextStr << " @ ";
638 }
639 OContextStr << Context[I].toString(I != Context.size() - 1 ||
640 IncludeLeafLineLocation);
641 }
642 return OContextStr.str();
643 }
644
645 std::string toString() const {
646 if (!hasContext())
647 return Func.str();
648 return getContextString(FullContext, false);
649 }
650
652 if (hasContext())
654 return getFunction().getHashCode();
655 }
656
657 /// Set the name of the function and clear the current context.
658 void setFunction(FunctionId NewFunctionID) {
659 Func = NewFunctionID;
660 FullContext = SampleContextFrames();
661 State = UnknownContext;
662 }
663
665 ContextStateMask CState = RawContext) {
666 assert(CState != UnknownContext);
667 FullContext = Context;
668 Func = Context.back().Func;
669 State = CState;
670 }
671
672 bool operator==(const SampleContext &That) const {
673 return State == That.State && Func == That.Func &&
674 FullContext == That.FullContext;
675 }
676
677 bool operator!=(const SampleContext &That) const { return !(*this == That); }
678
679 bool operator<(const SampleContext &That) const {
680 if (State != That.State)
681 return State < That.State;
682
683 if (!hasContext()) {
684 return Func < That.Func;
685 }
686
687 uint64_t I = 0;
688 while (I < std::min(FullContext.size(), That.FullContext.size())) {
689 auto &Context1 = FullContext[I];
690 auto &Context2 = That.FullContext[I];
691 auto V = Context1.Func.compare(Context2.Func);
692 if (V)
693 return V < 0;
694 if (Context1.Location != Context2.Location)
695 return Context1.Location < Context2.Location;
696 I++;
697 }
698
699 return FullContext.size() < That.FullContext.size();
700 }
701
702 struct Hash {
703 uint64_t operator()(const SampleContext &Context) const {
704 return Context.getHashCode();
705 }
706 };
707
708 bool isPrefixOf(const SampleContext &That) const {
709 auto ThisContext = FullContext;
710 auto ThatContext = That.FullContext;
711 if (ThatContext.size() < ThisContext.size())
712 return false;
713 ThatContext = ThatContext.take_front(ThisContext.size());
714 // Compare Leaf frame first
715 if (ThisContext.back().Func != ThatContext.back().Func)
716 return false;
717 // Compare leading context
718 return ThisContext.drop_back() == ThatContext.drop_back();
719 }
720
721private:
722 // The function associated with this context. If CS profile, this is the leaf
723 // function.
724 FunctionId Func;
725 // Full context including calling context and leaf function name
726 SampleContextFrames FullContext;
727 // State of the associated sample profile
728 uint32_t State;
729 // Attribute of the associated sample profile
730 uint32_t Attributes;
731};
732
733static inline hash_code hash_value(const SampleContext &Context) {
734 return Context.getHashCode();
735}
736
737inline raw_ostream &operator<<(raw_ostream &OS, const SampleContext &Context) {
738 return OS << Context.toString();
739}
740
741class FunctionSamples;
743
744using BodySampleMap = std::map<LineLocation, SampleRecord>;
745// NOTE: Using a StringMap here makes parsed profiles consume around 17% more
746// memory, which is *very* significant for large profiles.
747using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
748using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
750 std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
751
752/// Representation of the samples collected for a function.
753///
754/// This data structure contains all the collected samples for the body
755/// of a function. Each sample corresponds to a LineLocation instance
756/// within the body of the function.
758public:
759 FunctionSamples() = default;
760
761 LLVM_ABI void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
762 LLVM_ABI void dump() const;
763
765 bool Overflowed;
766 TotalSamples =
767 SaturatingMultiplyAdd(Num, Weight, TotalSamples, &Overflowed);
768 return Overflowed ? sampleprof_error::counter_overflow
770 }
771
773 if (TotalSamples < Num)
774 TotalSamples = 0;
775 else
776 TotalSamples -= Num;
777 }
778
779 void setTotalSamples(uint64_t Num) { TotalSamples = Num; }
780
781 void setHeadSamples(uint64_t Num) { TotalHeadSamples = Num; }
782
784 bool Overflowed;
785 TotalHeadSamples =
786 SaturatingMultiplyAdd(Num, Weight, TotalHeadSamples, &Overflowed);
787 return Overflowed ? sampleprof_error::counter_overflow
789 }
790
792 uint64_t Num, uint64_t Weight = 1) {
793 return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
794 Num, Weight);
795 }
796
798 uint32_t Discriminator,
799 FunctionId Func,
800 uint64_t Num,
801 uint64_t Weight = 1) {
802 return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
803 Func, Num, Weight);
804 }
805
808 uint64_t Weight = 1) {
809 return BodySamples[Location].merge(SampleRecord, Weight);
810 }
811
812 // Remove a call target and decrease the body sample correspondingly. Return
813 // the number of body samples actually decreased.
815 uint32_t Discriminator,
816 FunctionId Func) {
817 uint64_t Count = 0;
818 auto I = BodySamples.find(LineLocation(LineOffset, Discriminator));
819 if (I != BodySamples.end()) {
820 Count = I->second.removeCalledTarget(Func);
821 Count = I->second.removeSamples(Count);
822 if (!I->second.getSamples())
823 BodySamples.erase(I);
824 }
825 return Count;
826 }
827
828 // Remove all call site samples for inlinees. This is needed when flattening
829 // a nested profile.
831 CallsiteSamples.clear();
832 }
833
834 // Accumulate all call target samples to update the body samples.
836 for (auto &I : BodySamples) {
837 uint64_t TargetSamples = I.second.getCallTargetSum();
838 // It's possible that the body sample count can be greater than the call
839 // target sum. E.g, if some call targets are external targets, they won't
840 // be considered valid call targets, but the body sample count which is
841 // from lbr ranges can actually include them.
842 if (TargetSamples > I.second.getSamples())
843 I.second.addSamples(TargetSamples - I.second.getSamples());
844 }
845 }
846
847 // Accumulate all body samples to set total samples.
850 for (const auto &I : BodySamples)
851 addTotalSamples(I.second.getSamples());
852
853 for (auto &I : CallsiteSamples) {
854 for (auto &CS : I.second) {
855 CS.second.updateTotalSamples();
856 addTotalSamples(CS.second.getTotalSamples());
857 }
858 }
859 }
860
861 // Set current context and all callee contexts to be synthetic.
863 Context.setState(SyntheticContext);
864 for (auto &I : CallsiteSamples) {
865 for (auto &CS : I.second) {
866 CS.second.setContextSynthetic();
867 }
868 }
869 }
870
871 // Propagate the given attribute to this profile context and all callee
872 // contexts.
874 Context.setAttribute(Attr);
875 for (auto &I : CallsiteSamples) {
876 for (auto &CS : I.second) {
877 CS.second.setContextAttribute(Attr);
878 }
879 }
880 }
881
882 // Query the stale profile matching results and remap the location.
883 const LineLocation &mapIRLocToProfileLoc(const LineLocation &IRLoc) const {
884 // There is no remapping if the profile is not stale or the matching gives
885 // the same location.
886 if (!IRToProfileLocationMap)
887 return IRLoc;
888 const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc);
889 if (ProfileLoc != IRToProfileLocationMap->end())
890 return ProfileLoc->second;
891 return IRLoc;
892 }
893
894 /// Return the number of samples collected at the given location.
895 /// Each location is specified by \p LineOffset and \p Discriminator.
896 /// If the location is not found in profile, return error.
898 uint32_t Discriminator) const {
899 const auto &Ret = BodySamples.find(
900 mapIRLocToProfileLoc(LineLocation(LineOffset, Discriminator)));
901 if (Ret == BodySamples.end())
902 return std::error_code();
903 return Ret->second.getSamples();
904 }
905
906 /// Returns the call target map collected at a given location.
907 /// Each location is specified by \p LineOffset and \p Discriminator.
908 /// If the location is not found in profile, return error.
910 findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const {
911 const auto &Ret = BodySamples.find(
912 mapIRLocToProfileLoc(LineLocation(LineOffset, Discriminator)));
913 if (Ret == BodySamples.end())
914 return std::error_code();
915 return Ret->second.getCallTargets();
916 }
917
918 /// Returns the call target map collected at a given location specified by \p
919 /// CallSite. If the location is not found in profile, return error.
921 findCallTargetMapAt(const LineLocation &CallSite) const {
922 const auto &Ret = BodySamples.find(mapIRLocToProfileLoc(CallSite));
923 if (Ret == BodySamples.end())
924 return std::error_code();
925 return Ret->second.getCallTargets();
926 }
927
928 /// Return the function samples at the given callsite location.
930 return CallsiteSamples[mapIRLocToProfileLoc(Loc)];
931 }
932
933 /// Returns the FunctionSamplesMap at the given \p Loc.
934 const FunctionSamplesMap *
936 auto Iter = CallsiteSamples.find(mapIRLocToProfileLoc(Loc));
937 if (Iter == CallsiteSamples.end())
938 return nullptr;
939 return &Iter->second;
940 }
941
942 /// Returns a pointer to FunctionSamples at the given callsite location
943 /// \p Loc with callee \p CalleeName. If no callsite can be found, relax
944 /// the restriction to return the FunctionSamples at callsite location
945 /// \p Loc with the maximum total sample count. If \p Remapper or \p
946 /// FuncNameToProfNameMap is not nullptr, use them to find FunctionSamples
947 /// with equivalent name as \p CalleeName.
949 const LineLocation &Loc, StringRef CalleeName,
952 *FuncNameToProfNameMap = nullptr) const;
953
954 bool empty() const { return TotalSamples == 0; }
955
956 /// Return the total number of samples collected inside the function.
957 uint64_t getTotalSamples() const { return TotalSamples; }
958
959 /// For top-level functions, return the total number of branch samples that
960 /// have the function as the branch target (or 0 otherwise). This is the raw
961 /// data fetched from the profile. This should be equivalent to the sample of
962 /// the first instruction of the symbol. But as we directly get this info for
963 /// raw profile without referring to potentially inaccurate debug info, this
964 /// gives more accurate profile data and is preferred for standalone symbols.
965 uint64_t getHeadSamples() const { return TotalHeadSamples; }
966
967 /// Return an estimate of the sample count of the function entry basic block.
968 /// The function can be either a standalone symbol or an inlined function.
969 /// For Context-Sensitive profiles, this will prefer returning the head
970 /// samples (i.e. getHeadSamples()), if non-zero. Otherwise it estimates from
971 /// the function body's samples or callsite samples.
974 // For CS profile, if we already have more accurate head samples
975 // counted by branch sample from caller, use them as entry samples.
976 return getHeadSamples();
977 }
978 uint64_t Count = 0;
979 // Use either BodySamples or CallsiteSamples which ever has the smaller
980 // lineno.
981 if (!BodySamples.empty() &&
982 (CallsiteSamples.empty() ||
983 BodySamples.begin()->first < CallsiteSamples.begin()->first))
984 Count = BodySamples.begin()->second.getSamples();
985 else if (!CallsiteSamples.empty()) {
986 // An indirect callsite may be promoted to several inlined direct calls.
987 // We need to get the sum of them.
988 for (const auto &FuncSamples : CallsiteSamples.begin()->second)
989 Count += FuncSamples.second.getHeadSamplesEstimate();
990 }
991 // Return at least 1 if total sample is not 0.
992 return Count ? Count : TotalSamples > 0;
993 }
994
995 /// Return all the samples collected in the body of the function.
996 const BodySampleMap &getBodySamples() const { return BodySamples; }
997
998 /// Return all the callsite samples collected in the body of the function.
1000 return CallsiteSamples;
1001 }
1002
1003 /// Return the maximum of sample counts in a function body. When SkipCallSite
1004 /// is false, which is the default, the return count includes samples in the
1005 /// inlined functions. When SkipCallSite is true, the return count only
1006 /// considers the body samples.
1007 uint64_t getMaxCountInside(bool SkipCallSite = false) const {
1008 uint64_t MaxCount = 0;
1009 for (const auto &L : getBodySamples())
1010 MaxCount = std::max(MaxCount, L.second.getSamples());
1011 if (SkipCallSite)
1012 return MaxCount;
1013 for (const auto &C : getCallsiteSamples())
1014 for (const FunctionSamplesMap::value_type &F : C.second)
1015 MaxCount = std::max(MaxCount, F.second.getMaxCountInside());
1016 return MaxCount;
1017 }
1018
1019 /// Merge the samples in \p Other into this one.
1020 /// Optionally scale samples by \p Weight.
1023 if (!GUIDToFuncNameMap)
1024 GUIDToFuncNameMap = Other.GUIDToFuncNameMap;
1025 if (Context.getFunction().empty())
1026 Context = Other.getContext();
1027 if (FunctionHash == 0) {
1028 // Set the function hash code for the target profile.
1029 FunctionHash = Other.getFunctionHash();
1030 } else if (FunctionHash != Other.getFunctionHash()) {
1031 // The two profiles coming with different valid hash codes indicates
1032 // either:
1033 // 1. They are same-named static functions from different compilation
1034 // units (without using -unique-internal-linkage-names), or
1035 // 2. They are really the same function but from different compilations.
1036 // Let's bail out in either case for now, which means one profile is
1037 // dropped.
1039 }
1040
1041 mergeSampleProfErrors(Result,
1042 addTotalSamples(Other.getTotalSamples(), Weight));
1043 mergeSampleProfErrors(Result,
1044 addHeadSamples(Other.getHeadSamples(), Weight));
1045 for (const auto &I : Other.getBodySamples()) {
1046 const LineLocation &Loc = I.first;
1047 const SampleRecord &Rec = I.second;
1048 mergeSampleProfErrors(Result, BodySamples[Loc].merge(Rec, Weight));
1049 }
1050 for (const auto &I : Other.getCallsiteSamples()) {
1051 const LineLocation &Loc = I.first;
1053 for (const auto &Rec : I.second)
1054 mergeSampleProfErrors(Result,
1055 FSMap[Rec.first].merge(Rec.second, Weight));
1056 }
1057 return Result;
1058 }
1059
1060 /// Recursively traverses all children, if the total sample count of the
1061 /// corresponding function is no less than \p Threshold, add its corresponding
1062 /// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID
1063 /// to \p S.
1065 const HashKeyMap<std::unordered_map, FunctionId,
1066 Function *> &SymbolMap,
1067 uint64_t Threshold) const {
1068 if (TotalSamples <= Threshold)
1069 return;
1070 auto IsDeclaration = [](const Function *F) {
1071 return !F || F->isDeclaration();
1072 };
1073 if (IsDeclaration(SymbolMap.lookup(getFunction()))) {
1074 // Add to the import list only when it's defined out of module.
1075 S.insert(getGUID());
1076 }
1077 // Import hot CallTargets, which may not be available in IR because full
1078 // profile annotation cannot be done until backend compilation in ThinLTO.
1079 for (const auto &BS : BodySamples)
1080 for (const auto &TS : BS.second.getCallTargets())
1081 if (TS.second > Threshold) {
1082 const Function *Callee = SymbolMap.lookup(TS.first);
1083 if (IsDeclaration(Callee))
1084 S.insert(TS.first.getHashCode());
1085 }
1086 for (const auto &CS : CallsiteSamples)
1087 for (const auto &NameFS : CS.second)
1088 NameFS.second.findInlinedFunctions(S, SymbolMap, Threshold);
1089 }
1090
1091 /// Set the name of the function.
1092 void setFunction(FunctionId NewFunctionID) {
1093 Context.setFunction(NewFunctionID);
1094 }
1095
1096 /// Return the function name.
1097 FunctionId getFunction() const { return Context.getFunction(); }
1098
1099 /// Return the original function name.
1101
1102 void setFunctionHash(uint64_t Hash) { FunctionHash = Hash; }
1103
1104 uint64_t getFunctionHash() const { return FunctionHash; }
1105
1107 assert(IRToProfileLocationMap == nullptr && "this should be set only once");
1108 IRToProfileLocationMap = LTLM;
1109 }
1110
1111 /// Return the canonical name for a function, taking into account
1112 /// suffix elision policy attributes.
1114 const char *AttrName = "sample-profile-suffix-elision-policy";
1115 auto Attr = F.getFnAttribute(AttrName).getValueAsString();
1116 return getCanonicalFnName(F.getName(), Attr);
1117 }
1118
1119 /// Name suffixes which canonicalization should handle to avoid
1120 /// profile mismatch.
1121 static constexpr const char *LLVMSuffix = ".llvm.";
1122 static constexpr const char *PartSuffix = ".part.";
1123 static constexpr const char *UniqSuffix = ".__uniq.";
1124
1126 StringRef Attr = "selected") {
1127 // Note the sequence of the suffixes in the knownSuffixes array matters.
1128 // If suffix "A" is appended after the suffix "B", "A" should be in front
1129 // of "B" in knownSuffixes.
1130 const char *KnownSuffixes[] = {LLVMSuffix, PartSuffix, UniqSuffix};
1131 if (Attr == "" || Attr == "all")
1132 return FnName.split('.').first;
1133 if (Attr == "selected") {
1134 StringRef Cand(FnName);
1135 for (const auto &Suf : KnownSuffixes) {
1136 StringRef Suffix(Suf);
1137 // If the profile contains ".__uniq." suffix, don't strip the
1138 // suffix for names in the IR.
1140 continue;
1141 auto It = Cand.rfind(Suffix);
1142 if (It == StringRef::npos)
1143 continue;
1144 auto Dit = Cand.rfind('.');
1145 if (Dit == It + Suffix.size() - 1)
1146 Cand = Cand.substr(0, It);
1147 }
1148 return Cand;
1149 }
1150 if (Attr == "none")
1151 return FnName;
1152 assert(false && "internal error: unknown suffix elision policy");
1153 return FnName;
1154 }
1155
1156 /// Translate \p Func into its original name.
1157 /// When profile doesn't use MD5, \p Func needs no translation.
1158 /// When profile uses MD5, \p Func in current FunctionSamples
1159 /// is actually GUID of the original function name. getFuncName will
1160 /// translate \p Func in current FunctionSamples into its original name
1161 /// by looking up in the function map GUIDToFuncNameMap.
1162 /// If the original name doesn't exist in the map, return empty StringRef.
1164 if (!UseMD5)
1165 return Func.stringRef();
1166
1167 assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
1168 return GUIDToFuncNameMap->lookup(Func.getHashCode());
1169 }
1170
1171 /// Returns the line offset to the start line of the subprogram.
1172 /// We assume that a single function will not exceed 65535 LOC.
1173 LLVM_ABI static unsigned getOffset(const DILocation *DIL);
1174
1175 /// Returns a unique call site identifier for a given debug location of a call
1176 /// instruction. This is wrapper of two scenarios, the probe-based profile and
1177 /// regular profile, to hide implementation details from the sample loader and
1178 /// the context tracker.
1180 bool ProfileIsFS = false);
1181
1182 /// Returns a unique hash code for a combination of a callsite location and
1183 /// the callee function name.
1184 /// Guarantee MD5 and non-MD5 representation of the same function results in
1185 /// the same hash.
1187 const LineLocation &Callsite) {
1188 return SampleContextFrame(Callee, Callsite).getHashCode();
1189 }
1190
1191 /// Get the FunctionSamples of the inline instance where DIL originates
1192 /// from.
1193 ///
1194 /// The FunctionSamples of the instruction (Machine or IR) associated to
1195 /// \p DIL is the inlined instance in which that instruction is coming from.
1196 /// We traverse the inline stack of that instruction, and match it with the
1197 /// tree nodes in the profile.
1198 ///
1199 /// \returns the FunctionSamples pointer to the inlined instance.
1200 /// If \p Remapper or \p FuncNameToProfNameMap is not nullptr, it will be used
1201 /// to find matching FunctionSamples with not exactly the same but equivalent
1202 /// name.
1204 const DILocation *DIL,
1205 SampleProfileReaderItaniumRemapper *Remapper = nullptr,
1207 *FuncNameToProfNameMap = nullptr) const;
1208
1210
1212
1214
1215 SampleContext &getContext() const { return Context; }
1216
1217 void setContext(const SampleContext &FContext) { Context = FContext; }
1218
1219 /// Whether the profile uses MD5 to represent string.
1220 LLVM_ABI static bool UseMD5;
1221
1222 /// Whether the profile contains any ".__uniq." suffix in a name.
1224
1225 /// If this profile uses flow sensitive discriminators.
1227
1228 /// GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for
1229 /// all the function symbols defined or declared in current module.
1231
1232 /// Return the GUID of the context's name. If the context is already using
1233 /// MD5, don't hash it again.
1235 return getFunction().getHashCode();
1236 }
1237
1238 // Find all the names in the current FunctionSamples including names in
1239 // all the inline instances and names of call targets.
1240 LLVM_ABI void findAllNames(DenseSet<FunctionId> &NameSet) const;
1241
1242 bool operator==(const FunctionSamples &Other) const {
1243 return (GUIDToFuncNameMap == Other.GUIDToFuncNameMap ||
1244 (GUIDToFuncNameMap && Other.GUIDToFuncNameMap &&
1245 *GUIDToFuncNameMap == *Other.GUIDToFuncNameMap)) &&
1246 FunctionHash == Other.FunctionHash && Context == Other.Context &&
1247 TotalSamples == Other.TotalSamples &&
1248 TotalHeadSamples == Other.TotalHeadSamples &&
1249 BodySamples == Other.BodySamples &&
1250 CallsiteSamples == Other.CallsiteSamples;
1251 }
1252
1253 bool operator!=(const FunctionSamples &Other) const {
1254 return !(*this == Other);
1255 }
1256
1257private:
1258 /// CFG hash value for the function.
1259 uint64_t FunctionHash = 0;
1260
1261 /// Calling context for function profile
1262 mutable SampleContext Context;
1263
1264 /// Total number of samples collected inside this function.
1265 ///
1266 /// Samples are cumulative, they include all the samples collected
1267 /// inside this function and all its inlined callees.
1268 uint64_t TotalSamples = 0;
1269
1270 /// Total number of samples collected at the head of the function.
1271 /// This is an approximation of the number of calls made to this function
1272 /// at runtime.
1273 uint64_t TotalHeadSamples = 0;
1274
1275 /// Map instruction locations to collected samples.
1276 ///
1277 /// Each entry in this map contains the number of samples
1278 /// collected at the corresponding line offset. All line locations
1279 /// are an offset from the start of the function.
1280 BodySampleMap BodySamples;
1281
1282 /// Map call sites to collected samples for the called function.
1283 ///
1284 /// Each entry in this map corresponds to all the samples
1285 /// collected for the inlined function call at the given
1286 /// location. For example, given:
1287 ///
1288 /// void foo() {
1289 /// 1 bar();
1290 /// ...
1291 /// 8 baz();
1292 /// }
1293 ///
1294 /// If the bar() and baz() calls were inlined inside foo(), this
1295 /// map will contain two entries. One for all the samples collected
1296 /// in the call to bar() at line offset 1, the other for all the samples
1297 /// collected in the call to baz() at line offset 8.
1298 CallsiteSampleMap CallsiteSamples;
1299
1300 /// IR to profile location map generated by stale profile matching.
1301 ///
1302 /// Each entry is a mapping from the location on current build to the matched
1303 /// location in the "stale" profile. For example:
1304 /// Profiled source code:
1305 /// void foo() {
1306 /// 1 bar();
1307 /// }
1308 ///
1309 /// Current source code:
1310 /// void foo() {
1311 /// 1 // Code change
1312 /// 2 bar();
1313 /// }
1314 /// Supposing the stale profile matching algorithm generated the mapping [2 ->
1315 /// 1], the profile query using the location of bar on the IR which is 2 will
1316 /// be remapped to 1 and find the location of bar in the profile.
1317 const LocToLocMap *IRToProfileLocationMap = nullptr;
1318};
1319
1320/// Get the proper representation of a string according to whether the
1321/// current Format uses MD5 to represent the string.
1323 if (Name.empty() || !FunctionSamples::UseMD5)
1324 return FunctionId(Name);
1326}
1327
1329
1330/// This class provides operator overloads to the map container using MD5 as the
1331/// key type, so that existing code can still work in most cases using
1332/// SampleContext as key.
1333/// Note: when populating container, make sure to assign the SampleContext to
1334/// the mapped value immediately because the key no longer holds it.
1336 : public HashKeyMap<std::unordered_map, SampleContext, FunctionSamples> {
1337public:
1338 // Convenience method because this is being used in many places. Set the
1339 // FunctionSamples' context if its newly inserted.
1341 auto Ret = try_emplace(Ctx, FunctionSamples());
1342 if (Ret.second)
1343 Ret.first->second.setContext(Ctx);
1344 return Ret.first->second;
1345 }
1346
1351
1356
1361
1362 size_t erase(const key_type &Key) { return base_type::erase(Key); }
1363
1364 iterator erase(iterator It) { return base_type::erase(It); }
1365};
1366
1367using NameFunctionSamples = std::pair<hash_code, const FunctionSamples *>;
1368
1369LLVM_ABI void
1370sortFuncProfiles(const SampleProfileMap &ProfileMap,
1371 std::vector<NameFunctionSamples> &SortedProfiles);
1372
1373/// Sort a LocationT->SampleT map by LocationT.
1374///
1375/// It produces a sorted list of <LocationT, SampleT> records by ascending
1376/// order of LocationT.
1377template <class LocationT, class SampleT> class SampleSorter {
1378public:
1379 using SamplesWithLoc = std::pair<const LocationT, SampleT>;
1381
1382 SampleSorter(const std::map<LocationT, SampleT> &Samples) {
1383 for (const auto &I : Samples)
1384 V.push_back(&I);
1385 llvm::stable_sort(V, [](const SamplesWithLoc *A, const SamplesWithLoc *B) {
1386 return A->first < B->first;
1387 });
1388 }
1389
1390 const SamplesWithLocList &get() const { return V; }
1391
1392private:
1394};
1395
1396/// SampleContextTrimmer impelements helper functions to trim, merge cold
1397/// context profiles. It also supports context profile canonicalization to make
1398/// sure ProfileMap's key is consistent with FunctionSample's name/context.
1400public:
1401 SampleContextTrimmer(SampleProfileMap &Profiles) : ProfileMap(Profiles){};
1402 // Trim and merge cold context profile when requested. TrimBaseProfileOnly
1403 // should only be effective when TrimColdContext is true. On top of
1404 // TrimColdContext, TrimBaseProfileOnly can be used to specify to trim all
1405 // cold profiles or only cold base profiles. Trimming base profiles only is
1406 // mainly to honor the preinliner decsion. Note that when MergeColdContext is
1407 // true, preinliner decsion is not honored anyway so TrimBaseProfileOnly will
1408 // be ignored.
1410 bool TrimColdContext,
1411 bool MergeColdContext,
1412 uint32_t ColdContextFrameLength,
1413 bool TrimBaseProfileOnly);
1414
1415private:
1416 SampleProfileMap &ProfileMap;
1417};
1418
1419/// Helper class for profile conversion.
1420///
1421/// It supports full context-sensitive profile to nested profile conversion,
1422/// nested profile to flatten profile conversion, etc.
1424public:
1426 // Convert a full context-sensitive flat sample profile into a nested sample
1427 // profile.
1429 struct FrameNode {
1431 FunctionSamples *FSamples = nullptr,
1432 LineLocation CallLoc = {0, 0})
1433 : FuncName(FName), FuncSamples(FSamples), CallSiteLoc(CallLoc){};
1434
1435 // Map line+discriminator location to child frame
1436 std::map<uint64_t, FrameNode> AllChildFrames;
1437 // Function name for current frame
1439 // Function Samples for current frame
1441 // Callsite location in parent context
1443
1445 FunctionId CalleeName);
1446 };
1447
1448 static void flattenProfile(SampleProfileMap &ProfileMap,
1449 bool ProfileIsCS = false) {
1450 SampleProfileMap TmpProfiles;
1451 flattenProfile(ProfileMap, TmpProfiles, ProfileIsCS);
1452 ProfileMap = std::move(TmpProfiles);
1453 }
1454
1455 static void flattenProfile(const SampleProfileMap &InputProfiles,
1456 SampleProfileMap &OutputProfiles,
1457 bool ProfileIsCS = false) {
1458 if (ProfileIsCS) {
1459 for (const auto &I : InputProfiles) {
1460 // Retain the profile name and clear the full context for each function
1461 // profile.
1462 FunctionSamples &FS = OutputProfiles.create(I.second.getFunction());
1463 FS.merge(I.second);
1464 }
1465 } else {
1466 for (const auto &I : InputProfiles)
1467 flattenNestedProfile(OutputProfiles, I.second);
1468 }
1469 }
1470
1471private:
1472 static void flattenNestedProfile(SampleProfileMap &OutputProfiles,
1473 const FunctionSamples &FS) {
1474 // To retain the context, checksum, attributes of the original profile, make
1475 // a copy of it if no profile is found.
1476 SampleContext &Context = FS.getContext();
1477 auto Ret = OutputProfiles.try_emplace(Context, FS);
1478 FunctionSamples &Profile = Ret.first->second;
1479 if (Ret.second) {
1480 // Clear nested inlinees' samples for the flattened copy. These inlinees
1481 // will have their own top-level entries after flattening.
1482 Profile.removeAllCallsiteSamples();
1483 // We recompute TotalSamples later, so here set to zero.
1484 Profile.setTotalSamples(0);
1485 } else {
1486 for (const auto &[LineLocation, SampleRecord] : FS.getBodySamples()) {
1487 Profile.addSampleRecord(LineLocation, SampleRecord);
1488 }
1489 }
1490
1491 assert(Profile.getCallsiteSamples().empty() &&
1492 "There should be no inlinees' profiles after flattening.");
1493
1494 // TotalSamples might not be equal to the sum of all samples from
1495 // BodySamples and CallsiteSamples. So here we use "TotalSamples =
1496 // Original_TotalSamples - All_of_Callsite_TotalSamples +
1497 // All_of_Callsite_HeadSamples" to compute the new TotalSamples.
1498 uint64_t TotalSamples = FS.getTotalSamples();
1499
1500 for (const auto &I : FS.getCallsiteSamples()) {
1501 for (const auto &Callee : I.second) {
1502 const auto &CalleeProfile = Callee.second;
1503 // Add body sample.
1504 Profile.addBodySamples(I.first.LineOffset, I.first.Discriminator,
1505 CalleeProfile.getHeadSamplesEstimate());
1506 // Add callsite sample.
1507 Profile.addCalledTargetSamples(
1508 I.first.LineOffset, I.first.Discriminator,
1509 CalleeProfile.getFunction(),
1510 CalleeProfile.getHeadSamplesEstimate());
1511 // Update total samples.
1512 TotalSamples = TotalSamples >= CalleeProfile.getTotalSamples()
1513 ? TotalSamples - CalleeProfile.getTotalSamples()
1514 : 0;
1515 TotalSamples += CalleeProfile.getHeadSamplesEstimate();
1516 // Recursively convert callee profile.
1517 flattenNestedProfile(OutputProfiles, CalleeProfile);
1518 }
1519 }
1520 Profile.addTotalSamples(TotalSamples);
1521
1522 Profile.setHeadSamples(Profile.getHeadSamplesEstimate());
1523 }
1524
1525 // Nest all children profiles into the profile of Node.
1526 void convertCSProfiles(FrameNode &Node);
1527 FrameNode *getOrCreateContextPath(const SampleContext &Context);
1528
1529 SampleProfileMap &ProfileMap;
1530 FrameNode RootFrame;
1531};
1532
1533/// ProfileSymbolList records the list of function symbols shown up
1534/// in the binary used to generate the profile. It is useful to
1535/// to discriminate a function being so cold as not to shown up
1536/// in the profile and a function newly added.
1538public:
1539 /// copy indicates whether we need to copy the underlying memory
1540 /// for the input Name.
1541 void add(StringRef Name, bool Copy = false) {
1542 if (!Copy) {
1543 Syms.insert(Name);
1544 return;
1545 }
1546 Syms.insert(Name.copy(Allocator));
1547 }
1548
1549 bool contains(StringRef Name) { return Syms.count(Name); }
1550
1552 for (auto Sym : List.Syms)
1553 add(Sym, true);
1554 }
1555
1556 unsigned size() { return Syms.size(); }
1557
1558 void setToCompress(bool TC) { ToCompress = TC; }
1559 bool toCompress() { return ToCompress; }
1560
1561 LLVM_ABI std::error_code read(const uint8_t *Data, uint64_t ListSize);
1562 LLVM_ABI std::error_code write(raw_ostream &OS);
1563 LLVM_ABI void dump(raw_ostream &OS = dbgs()) const;
1564
1565private:
1566 // Determine whether or not to compress the symbol list when
1567 // writing it into profile. The variable is unused when the symbol
1568 // list is read from an existing profile.
1569 bool ToCompress = false;
1572};
1573
1574} // end namespace sampleprof
1575
1576using namespace sampleprof;
1577// Provide DenseMapInfo for SampleContext.
1578template <> struct DenseMapInfo<SampleContext> {
1579 static inline SampleContext getEmptyKey() { return SampleContext(); }
1580
1582 return SampleContext(FunctionId(~1ULL));
1583 }
1584
1585 static unsigned getHashValue(const SampleContext &Val) {
1586 return Val.getHashCode();
1587 }
1588
1589 static bool isEqual(const SampleContext &LHS, const SampleContext &RHS) {
1590 return LHS == RHS;
1591 }
1592};
1593
1594// Prepend "__uniq" before the hash for tools like profilers to understand
1595// that this symbol is of internal linkage type. The "__uniq" is the
1596// pre-determined prefix that is used to tell tools that this symbol was
1597// created with -funique-internal-linkage-symbols and the tools can strip or
1598// keep the prefix as needed.
1599inline std::string getUniqueInternalLinkagePostfix(const StringRef &FName) {
1600 llvm::MD5 Md5;
1601 Md5.update(FName);
1603 Md5.final(R);
1604 SmallString<32> Str;
1606 // Convert MD5hash to Decimal. Demangler suffixes can either contain
1607 // numbers or characters but not both.
1608 llvm::APInt IntHash(128, Str.str(), 16);
1609 return toString(IntHash, /* Radix = */ 10, /* Signed = */ false)
1610 .insert(0, FunctionSamples::UniqSuffix);
1611}
1612
1613} // end namespace llvm
1614
1615#endif // LLVM_PROFILEDATA_SAMPLEPROF_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
This file defines the DenseSet and SmallDenseSet classes.
Provides ErrorOr<T> smart pointer.
Defines HashKeyMap template.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
Load MIR Sample Profile
static cl::opt< unsigned > ColdCountThreshold("mfs-count-threshold", cl::desc("Minimum number of times a block must be executed to be retained."), cl::init(1), cl::Hidden)
This file implements a map that provides insertion order iteration.
Defines FunctionId class.
Basic Register Allocator
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:224
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
Definition ArrayRef.h:206
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition DenseMap.h:187
Implements a dense probed hash-table based set.
Definition DenseSet.h:261
Represents either an error or a value T.
Definition ErrorOr.h:56
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
Definition Globals.cpp:77
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition MD5.cpp:189
static LLVM_ABI void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)
Translates the bytes in Res to a hex string that is deposited into Str.
Definition MD5.cpp:287
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition MD5.cpp:234
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:36
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
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.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:710
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:581
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:269
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:151
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
Definition StringRef.h:353
static constexpr size_t npos
Definition StringRef.h:57
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:194
An opaque object representing a hash code.
Definition Hashing.h:76
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
uint64_t getHashCode() const
Get hash code of this object.
Definition FunctionId.h:123
Representation of the samples collected for a function.
Definition SampleProf.h:757
void setTotalSamples(uint64_t Num)
Definition SampleProf.h:779
static LLVM_ABI bool ProfileIsPreInlined
void setContextAttribute(ContextAttributeMask Attr)
Definition SampleProf.h:873
void findInlinedFunctions(DenseSet< GlobalValue::GUID > &S, const HashKeyMap< std::unordered_map, FunctionId, Function * > &SymbolMap, uint64_t Threshold) const
Recursively traverses all children, if the total sample count of the corresponding function is no les...
bool operator!=(const FunctionSamples &Other) const
void setHeadSamples(uint64_t Num)
Definition SampleProf.h:781
LLVM_ABI const FunctionSamples * findFunctionSamplesAt(const LineLocation &Loc, StringRef CalleeName, SampleProfileReaderItaniumRemapper *Remapper, const HashKeyMap< std::unordered_map, FunctionId, FunctionId > *FuncNameToProfNameMap=nullptr) const
Returns a pointer to FunctionSamples at the given callsite location Loc with callee CalleeName.
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:764
static constexpr const char * UniqSuffix
static StringRef getCanonicalFnName(StringRef FnName, StringRef Attr="selected")
bool operator==(const FunctionSamples &Other) const
static constexpr const char * PartSuffix
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.
const FunctionSamplesMap * findFunctionSamplesMapAt(const LineLocation &Loc) const
Returns the FunctionSamplesMap at the given Loc.
Definition SampleProf.h:935
uint64_t getMaxCountInside(bool SkipCallSite=false) const
Return the maximum of sample counts in a function body.
void removeTotalSamples(uint64_t Num)
Definition SampleProf.h:772
uint64_t getHeadSamples() const
For top-level functions, return the total number of branch samples that have the function as the bran...
Definition SampleProf.h:965
void setFunction(FunctionId NewFunctionID)
Set the name of the function.
ErrorOr< uint64_t > findSamplesAt(uint32_t LineOffset, uint32_t Discriminator) const
Return the number of samples collected at the given location.
Definition SampleProf.h:897
static LLVM_ABI bool ProfileIsCS
ErrorOr< const SampleRecord::CallTargetMap & > findCallTargetMapAt(const LineLocation &CallSite) const
Returns the call target map collected at a given location specified by CallSite.
Definition SampleProf.h:921
const LineLocation & mapIRLocToProfileLoc(const LineLocation &IRLoc) const
Definition SampleProf.h:883
FunctionId getFunction() const
Return the function name.
static constexpr const char * LLVMSuffix
Name suffixes which canonicalization should handle to avoid profile mismatch.
StringRef getFuncName(FunctionId Func) const
Translate Func into its original name.
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:783
sampleprof_error addSampleRecord(LineLocation Location, const SampleRecord &SampleRecord, uint64_t Weight=1)
Definition SampleProf.h:806
uint64_t removeCalledTargetAndBodySample(uint32_t LineOffset, uint32_t Discriminator, FunctionId Func)
Definition SampleProf.h:814
DenseMap< uint64_t, StringRef > * GUIDToFuncNameMap
GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for all the function symbols define...
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, FunctionId Func, uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:797
FunctionSamplesMap & functionSamplesAt(const LineLocation &Loc)
Return the function samples at the given callsite location.
Definition SampleProf.h:929
LLVM_ABI const FunctionSamples * findFunctionSamples(const DILocation *DIL, SampleProfileReaderItaniumRemapper *Remapper=nullptr, const HashKeyMap< std::unordered_map, FunctionId, FunctionId > *FuncNameToProfNameMap=nullptr) const
Get the FunctionSamples of the inline instance where DIL originates from.
static LLVM_ABI bool ProfileIsProbeBased
void setIRToProfileLocationMap(const LocToLocMap *LTLM)
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
StringRef getFuncName() const
Return the original function name.
LLVM_ABI void findAllNames(DenseSet< FunctionId > &NameSet) const
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight=1)
Definition SampleProf.h:791
static LLVM_ABI unsigned getOffset(const DILocation *DIL)
Returns the line offset to the start line of the subprogram.
void setFunctionHash(uint64_t Hash)
static LLVM_ABI bool ProfileIsFS
If this profile uses flow sensitive discriminators.
ErrorOr< const SampleRecord::CallTargetMap & > findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const
Returns the call target map collected at a given location.
Definition SampleProf.h:910
SampleContext & getContext() const
static LLVM_ABI bool HasUniqSuffix
Whether the profile contains any ".__uniq." suffix in a name.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
Definition SampleProf.h:957
LLVM_ABI void print(raw_ostream &OS=dbgs(), unsigned Indent=0) const
Print the samples collected for a function on stream OS.
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
const CallsiteSampleMap & getCallsiteSamples() const
Return all the callsite samples collected in the body of the function.
Definition SampleProf.h:999
void setContext(const SampleContext &FContext)
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.
uint64_t getHeadSamplesEstimate() const
Return an estimate of the sample count of the function entry basic block.
Definition SampleProf.h:972
uint64_t getGUID() const
Return the GUID of the context's name.
const BodySampleMap & getBodySamples() const
Return all the samples collected in the body of the function.
Definition SampleProf.h:996
static LLVM_ABI bool UseMD5
Whether the profile uses MD5 to represent string.
This class is a wrapper to associative container MapT<KeyT, ValueT> using the hash value of the origi...
Definition HashKeyMap.h:53
std::pair< iterator, bool > try_emplace(const key_type &Hash, const original_key_type &Key, Ts &&...Args)
Definition HashKeyMap.h:65
size_t erase(const original_key_type &Ctx)
Definition HashKeyMap.h:111
iterator find(const original_key_type &Key)
Definition HashKeyMap.h:86
LLVM_ABI ProfileConverter(SampleProfileMap &Profiles)
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
static void flattenProfile(const SampleProfileMap &InputProfiles, SampleProfileMap &OutputProfiles, bool ProfileIsCS=false)
ProfileSymbolList records the list of function symbols shown up in the binary used to generate the pr...
void add(StringRef Name, bool Copy=false)
copy indicates whether we need to copy the underlying memory for the input Name.
LLVM_ABI std::error_code write(raw_ostream &OS)
LLVM_ABI void dump(raw_ostream &OS=dbgs()) const
void merge(const ProfileSymbolList &List)
LLVM_ABI std::error_code read(const uint8_t *Data, uint64_t ListSize)
SampleContextTrimmer(SampleProfileMap &Profiles)
LLVM_ABI void trimAndMergeColdContextProfiles(uint64_t ColdCountThreshold, bool TrimColdContext, bool MergeColdContext, uint32_t ColdContextFrameLength, bool TrimBaseProfileOnly)
static void createCtxVectorFromStr(StringRef ContextStr, SampleContextFrameVector &Context)
Create a context vector from a given context string and save it in Context.
Definition SampleProf.h:578
bool operator==(const SampleContext &That) const
Definition SampleProf.h:672
void setFunction(FunctionId NewFunctionID)
Set the name of the function and clear the current context.
Definition SampleProf.h:658
SampleContext(SampleContextFrames Context, ContextStateMask CState=RawContext)
Definition SampleProf.h:547
bool operator<(const SampleContext &That) const
Definition SampleProf.h:679
SampleContext(StringRef ContextStr, std::list< SampleContextFrameVector > &CSNameTable, ContextStateMask CState=RawContext)
Definition SampleProf.h:557
bool hasState(ContextStateMask S)
Definition SampleProf.h:624
void clearState(ContextStateMask S)
Definition SampleProf.h:626
SampleContextFrames getContextFrames() const
Definition SampleProf.h:630
static void decodeContextString(StringRef ContextStr, FunctionId &Func, LineLocation &LineLoc)
Definition SampleProf.h:597
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
Definition SampleProf.h:632
bool operator!=(const SampleContext &That) const
Definition SampleProf.h:677
void setState(ContextStateMask S)
Definition SampleProf.h:625
void setAllAttributes(uint32_t A)
Definition SampleProf.h:623
void setContext(SampleContextFrames Context, ContextStateMask CState=RawContext)
Definition SampleProf.h:664
FunctionId getFunction() const
Definition SampleProf.h:629
void setAttribute(ContextAttributeMask A)
Definition SampleProf.h:621
bool hasAttribute(ContextAttributeMask A)
Definition SampleProf.h:620
std::string toString() const
Definition SampleProf.h:645
bool isPrefixOf(const SampleContext &That) const
Definition SampleProf.h:708
This class provides operator overloads to the map container using MD5 as the key type,...
iterator find(const SampleContext &Ctx)
mapped_type & create(const SampleContext &Ctx)
size_t erase(const key_type &Key)
const_iterator find(const SampleContext &Ctx) const
size_t erase(const SampleContext &Ctx)
SampleProfileReaderItaniumRemapper remaps the profile data from a sample profile data reader,...
Representation of a single sample record.
Definition SampleProf.h:331
std::unordered_map< FunctionId, uint64_t > CallTargetMap
Definition SampleProf.h:344
LLVM_ABI std::error_code serialize(raw_ostream &OS, const MapVector< FunctionId, uint32_t > &NameTable) const
Serialize the sample record to the output stream using ULEB128 encoding.
LLVM_ABI void dump() const
bool hasCalls() const
Return true if this sample record contains function calls.
Definition SampleProf.h:396
LLVM_ABI sampleprof_error merge(const SampleRecord &Other, uint64_t Weight=1)
Merge the samples in Other into this record.
static const SortedCallTargetSet sortCallTargets(const CallTargetMap &Targets)
Sort call targets in descending order of call frequency.
Definition SampleProf.h:413
const CallTargetMap & getCallTargets() const
Definition SampleProf.h:399
std::set< CallTarget, CallTargetComparator > SortedCallTargetSet
Definition SampleProf.h:343
uint64_t getCallTargetSum() const
Definition SampleProf.h:404
uint64_t removeSamples(uint64_t S)
Decrease the number of samples for this record by S.
Definition SampleProf.h:361
sampleprof_error addSamples(uint64_t S, uint64_t Weight=1)
Increment the number of samples for this record by S.
Definition SampleProf.h:352
uint64_t removeCalledTarget(FunctionId F)
Remove called function from the call target map.
Definition SampleProf.h:385
const SortedCallTargetSet getSortedCallTargets() const
Definition SampleProf.h:400
static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, float DistributionFactor)
Prorate call targets by a distribution factor.
Definition SampleProf.h:422
std::pair< FunctionId, uint64_t > CallTarget
Definition SampleProf.h:333
bool operator!=(const SampleRecord &Other) const
Definition SampleProf.h:447
bool operator==(const SampleRecord &Other) const
Definition SampleProf.h:443
LLVM_ABI void print(raw_ostream &OS, unsigned Indent) const
Print the sample record to the stream OS indented by Indent.
sampleprof_error addCalledTarget(FunctionId F, uint64_t S, uint64_t Weight=1)
Add called function F with samples S.
Definition SampleProf.h:373
std::pair< const LocationT, SampleT > SamplesWithLoc
SampleSorter(const std::map< LocationT, SampleT > &Samples)
const SamplesWithLocList & get() const
SmallVector< const SamplesWithLoc *, 20 > SamplesWithLocList
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
static FunctionId getRepInFormat(StringRef Name)
Get the proper representation of a string according to whether the current Format uses MD5 to represe...
static void verifySecFlag(SecType Type, SecFlagType Flag)
Definition SampleProf.h:224
LLVM_ABI void sortFuncProfiles(const SampleProfileMap &ProfileMap, std::vector< NameFunctionSamples > &SortedProfiles)
static uint64_t SPMagic(SampleProfileFormat Format=SPF_Binary)
Definition SampleProf.h:109
static void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:251
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
Definition SampleProf.h:748
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:267
ArrayRef< SampleContextFrame > SampleContextFrames
Definition SampleProf.h:517
std::pair< hash_code, const FunctionSamples * > NameFunctionSamples
@ SecFlagIsPreInlined
SecFlagIsPreInlined means this profile contains ShouldBeInlined contexts thus this is CS preinliner c...
Definition SampleProf.h:206
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
Definition SampleProf.h:197
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
Definition SampleProf.h:203
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
Definition SampleProf.h:200
static void removeSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:259
SmallVector< SampleContextFrame, 1 > SampleContextFrameVector
Definition SampleProf.h:516
std::map< FunctionId, FunctionSamples > FunctionSamplesMap
Definition SampleProf.h:747
std::unordered_map< LineLocation, LineLocation, LineLocationHash > LocToLocMap
Definition SampleProf.h:749
raw_ostream & operator<<(raw_ostream &OS, const FunctionId &Obj)
Definition FunctionId.h:159
static std::string getSecName(SecType Type)
Definition SampleProf.h:134
uint64_t hash_value(const FunctionId &Obj)
Definition FunctionId.h:171
static uint64_t SPVersion()
Definition SampleProf.h:116
std::map< LineLocation, SampleRecord > BodySampleMap
Definition SampleProf.h:744
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Definition STLExtras.h:2060
std::error_code make_error_code(BitcodeError E)
sampleprof_error mergeSampleProfErrors(sampleprof_error &Accumulator, sampleprof_error Result)
Definition SampleProf.h:72
sampleprof_error
Definition SampleProf.h:49
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed=nullptr)
Multiply two unsigned integers, X and Y, and add the unsigned integer, A to the product.
Definition MathExtras.h:689
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Other
Any other memory.
Definition ModRef.h:68
LLVM_ABI const std::error_category & sampleprof_category()
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
std::string getUniqueInternalLinkagePostfix(const StringRef &FName)
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LogicalResult success(bool IsSuccess=true)
Utility function to generate a LogicalResult.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition Hashing.h:465
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851
static unsigned getHashValue(const SampleContext &Val)
static SampleContext getTombstoneKey()
static SampleContext getEmptyKey()
static bool isEqual(const SampleContext &LHS, const SampleContext &RHS)
An information struct used to provide DenseMap with the various necessary components for a given valu...
uint64_t operator()(const LineLocation &Loc) const
Definition SampleProf.h:314
Represents the relative location of an instruction.
Definition SampleProf.h:283
LLVM_ABI void serialize(raw_ostream &OS) const
LLVM_ABI void print(raw_ostream &OS) const
LineLocation(uint32_t L, uint32_t D)
Definition SampleProf.h:284
bool operator!=(const LineLocation &O) const
Definition SampleProf.h:301
bool operator<(const LineLocation &O) const
Definition SampleProf.h:292
bool operator==(const LineLocation &O) const
Definition SampleProf.h:297
LLVM_ABI void dump() const
FrameNode(FunctionId FName=FunctionId(), FunctionSamples *FSamples=nullptr, LineLocation CallLoc={0, 0})
LLVM_ABI FrameNode * getOrCreateChildFrame(const LineLocation &CallSite, FunctionId CalleeName)
std::map< uint64_t, FrameNode > AllChildFrames
uint64_t operator()(const SampleContextFrameVector &S) const
Definition SampleProf.h:520
bool operator==(const SampleContextFrame &That) const
Definition SampleProf.h:486
SampleContextFrame(FunctionId Func, LineLocation Location)
Definition SampleProf.h:483
bool operator!=(const SampleContextFrame &That) const
Definition SampleProf.h:490
std::string toString(bool OutputLineLocation) const
Definition SampleProf.h:494
uint64_t operator()(const SampleContext &Context) const
Definition SampleProf.h:703
bool operator()(const CallTarget &LHS, const CallTarget &RHS) const
Definition SampleProf.h:335