1#ifndef LLVM_PROFILEDATA_MEMPROF_H_
2#define LLVM_PROFILEDATA_MEMPROF_H_
47#define MIBEntryDef(NameTag, Name, Type) NameTag,
68 for (
const Meta Id : IncomingSchema)
70#define MIBEntryDef(NameTag, Name, Type) Name = Block.Name;
82 const unsigned char *
Ptr) {
83 using namespace support;
86 for (
const Meta Id : IncomingSchema) {
88#define MIBEntryDef(NameTag, Name, Type) \
90 Name = endian::readNext<Type, llvm::endianness::little>(Ptr); \
96 "a newer version of the runtime?");
106 using namespace support;
109 for (
const Meta Id : Schema) {
111#define MIBEntryDef(NameTag, Name, Type) \
113 LE.write<Type>(Name); \
125 OS <<
" MemInfoBlock:\n";
126#define MIBEntryDef(NameTag, Name, Type) \
127 OS << " " << #Name << ": " << Name << "\n";
130 if (AccessHistogramSize > 0) {
131 OS <<
" " <<
"AccessHistogramValues" <<
":";
132 for (
uint32_t I = 0;
I < AccessHistogramSize; ++
I) {
145#define MIBEntryDef(NameTag, Name, Type) \
146 Type get##Name() const { \
147 assert(Schema[llvm::to_underlying(Meta::Name)]); \
154#define MIBEntryDef(NameTag, Name, Type) \
155 void set##Name(Type NewVal) { \
156 assert(Schema[llvm::to_underlying(Meta::Name)]); \
165 if (
Other.Schema != Schema)
168#define MIBEntryDef(NameTag, Name, Type) \
169 if (Schema[llvm::to_underlying(Meta::Name)] && \
170 Other.get##Name() != get##Name()) \
184 for (
const Meta Id : Schema) {
186#define MIBEntryDef(NameTag, Name, Type) \
188 Result += sizeof(Type); \
205 std::bitset<llvm::to_underlying(Meta::Size)> Schema;
207#define MIBEntryDef(NameTag, Name, Type) Type Name = Type();
208#include "llvm/ProfileData/MIBEntryDef.inc"
232 bool IsInlineFrame =
false;
237 SymbolName =
Other.SymbolName
238 ? std::make_unique<std::string>(*
Other.SymbolName)
240 LineOffset =
Other.LineOffset;
241 Column =
Other.Column;
242 IsInlineFrame =
Other.IsInlineFrame;
246 :
Function(Hash), LineOffset(Off), Column(Col), IsInlineFrame(Inline) {}
252 Other.Column == Column &&
Other.IsInlineFrame == IsInlineFrame;
257 SymbolName =
Other.SymbolName
258 ? std::make_unique<std::string>(*
Other.SymbolName)
260 LineOffset =
Other.LineOffset;
261 Column =
Other.Column;
262 IsInlineFrame =
Other.IsInlineFrame;
281 using namespace support;
287 static_assert(std::is_same<GlobalValue::GUID, uint64_t>::value,
288 "Expect GUID to be uint64_t.");
293 LE.write<
bool>(IsInlineFrame);
298 using namespace support;
301 endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
303 endian::readNext<uint32_t, llvm::endianness::little>(
Ptr);
305 endian::readNext<uint32_t, llvm::endianness::little>(
Ptr);
306 const bool I = endian::readNext<bool, llvm::endianness::little>(
Ptr);
313 return sizeof(Frame::Function) +
sizeof(Frame::LineOffset) +
314 sizeof(Frame::Column) +
sizeof(Frame::IsInlineFrame);
320 <<
" Function: " <<
Function <<
"\n"
321 <<
" SymbolName: " << getSymbolNameOr(
"<None>") <<
"\n"
322 <<
" LineOffset: " << LineOffset <<
"\n"
323 <<
" Column: " << Column <<
"\n"
324 <<
" Inline: " << IsInlineFrame <<
"\n";
346 : CSId(CSId),
Info(MB, Schema) {}
348 : CSId(CSId),
Info(MB) {}
358 if (
Other.CSId != CSId)
380 OS <<
" Callstack:\n";
416 if (
Other.AllocSites != AllocSites)
419 if (
Other.CallSiteIds != CallSiteIds)
429 *MemProfCallStackIndexes =
nullptr)
const;
433 const unsigned char *Buffer,
460 if (!AllocSites.
empty()) {
461 OS <<
" AllocSites:\n";
466 if (!CallSites.
empty()) {
467 OS <<
" CallSites:\n";
468 for (
const std::vector<Frame> &Frames : CallSites) {
469 for (
const Frame &
F : Frames) {
496 : Version(V), Schema(S) {}
504 static std::pair<offset_type, offset_type>
506 using namespace support;
509 endian::readNext<offset_type, llvm::endianness::little>(
D);
511 endian::readNext<offset_type, llvm::endianness::little>(
D);
512 return std::make_pair(KeyLen, DataLen);
516 using namespace support;
517 return endian::readNext<external_key_type, llvm::endianness::little>(
D);
522 Record = IndexedMemProfRecord::deserialize(Schema,
D, Version);
562 : Schema(Schema), Version(V),
563 MemProfCallStackIndexes(MemProfCallStackIndexes) {}
567 std::pair<offset_type, offset_type>
569 using namespace support;
574 offset_type M = V.serializedSize(*Schema, Version);
576 return std::make_pair(
N, M);
580 using namespace support;
587 assert(Schema !=
nullptr &&
"MemProf schema is not initialized!");
588 V.serialize(*Schema, Out, Version, MemProfCallStackIndexes);
611 static std::pair<offset_type, offset_type>
613 using namespace support;
619 return std::make_pair(
N, M);
623 using namespace support;
651 static std::pair<offset_type, offset_type>
653 using namespace support;
656 endian::readNext<offset_type, llvm::endianness::little>(
D);
658 endian::readNext<offset_type, llvm::endianness::little>(
D);
659 return std::make_pair(KeyLen, DataLen);
663 using namespace support;
664 return endian::readNext<external_key_type, llvm::endianness::little>(
D);
669 return Frame::deserialize(
D);
687 static std::pair<offset_type, offset_type>
689 using namespace support;
695 return std::make_pair(
N, M);
699 using namespace support;
706 using namespace support;
732 static std::pair<offset_type, offset_type>
734 using namespace support;
739 endian::readNext<offset_type, llvm::endianness::little>(
D);
740 return std::make_pair(KeyLen, DataLen);
744 using namespace support;
745 return endian::readNext<external_key_type, llvm::endianness::little>(
D);
749 using namespace support;
755 for (
size_t I = 0;
I != NumFrames; ++
I) {
756 FrameId F = endian::readNext<FrameId, llvm::endianness::little>(
D);
767template <
typename value_type,
typename IterTy>
770 if constexpr (std::is_same_v<deref_type, value_type>)
792 auto Iter = Map.find(Id);
793 if (Iter == Map.end()) {
797 return detail::DerefIterator<Frame>(Iter);
810 : Map(Map), FrameIdToFrame(FrameIdToFrame) {}
819 std::vector<Frame> Frames;
820 auto CSIter = Map.find(CSId);
821 if (CSIter == Map.end()) {
822 LastUnmappedId = CSId;
825 detail::DerefIterator<llvm::SmallVector<FrameId>>(CSIter);
828 Frames.push_back(FrameIdToFrame(Id));
841 : FrameBase(FrameBase) {}
845 return Frame::deserialize(FrameBase +
Offset);
857 const unsigned char *CallStackBase,
859 : CallStackBase(CallStackBase), FrameIdToFrame(FrameIdToFrame) {}
862 std::vector<Frame> Frames;
864 const unsigned char *
Ptr =
868 support::endian::readNext<uint32_t, llvm::endianness::little>(
Ptr);
869 Frames.reserve(NumFrames);
870 for (; NumFrames; --NumFrames) {
872 support::endian::read<LinearFrameId, llvm::endianness::little>(
Ptr);
875 if (
static_cast<std::make_signed_t<LinearFrameId>
>(Elem) < 0) {
878 support::endian::read<LinearFrameId, llvm::endianness::little>(
Ptr);
881 assert(
static_cast<std::make_signed_t<LinearFrameId>
>(Elem) >= 0);
882 Frames.push_back(FrameIdToFrame(Elem));
894 return LineOffset < O.LineOffset ||
895 (LineOffset == O.LineOffset && Column < O.Column);
899 return LineOffset == O.LineOffset && Column == O.Column;
903 return LineOffset != O.LineOffset || Column != O.Column;
934 const unsigned char *CallStackBase,
936 unsigned RadixTreeSize)
937 : CallStackBase(CallStackBase), FrameIdToFrame(FrameIdToFrame),
938 Visited(RadixTreeSize) {}
941 const unsigned char *
Ptr =
945 support::endian::readNext<uint32_t, llvm::endianness::little>(
Ptr);
948 for (; NumFrames; --NumFrames) {
950 support::endian::read<LinearFrameId, llvm::endianness::little>(
Ptr);
953 if (
static_cast<std::make_signed_t<LinearFrameId>
>(Elem) < 0) {
956 support::endian::read<LinearFrameId, llvm::endianness::little>(
Ptr);
959 assert(
static_cast<std::make_signed_t<LinearFrameId>
>(Elem) >= 0);
962 Frame F = FrameIdToFrame(Elem);
965 CallerCalleePairs[CallerGUID].emplace_back(Loc, CalleeGUID);
977 CalleeGUID = CallerGUID;
1025 std::memcpy(&Id, Hash.data(),
sizeof(Hash));
1038 : FrameIdConv(MemProfData.Frames),
1039 CSIdConv(MemProfData.CallStacks, FrameIdConv) {}
1062template <
typename FrameIdTy>
1065 &MemProfCallStackData);
1124 std::vector<LinearFrameId> RadixArray;
1147 std::vector<LinearCallStackId> Indexes;
1149 using CSIdPair = std::pair<CallStackId, llvm::SmallVector<FrameIdTy>>;
1164 &&MemProfCallStackData,
1171 return std::move(CallStackPos);
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
static StringRef getSymbolName(SymbolKind SymKind)
std::optional< std::vector< StOtherPiece > > Other
This file implements a map that provides insertion order iteration.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains library features backported from future STL versions.
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool test(unsigned Idx) const
Tagged union holding either a T or a Error.
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
HashResultTy< HasherT_ > final()
Forward to HasherT::final() if available.
Interface to help hash various types through a hasher type.
std::enable_if_t< hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > add(T Value)
Implement hashing for hashable data types, e.g. integral or enum values.
This class implements a map that also provides access to all stored values in a deterministic order.
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
An efficient, type-erasing, non-owning reference to a callable.
static uint64_t GetInternalKey(internal_key_type K)
hash_value_type ComputeHash(internal_key_type K)
static bool EqualKey(internal_key_type A, internal_key_type B)
static std::pair< offset_type, offset_type > ReadKeyDataLength(const unsigned char *&D)
uint64_t ReadKey(const unsigned char *D, offset_type)
data_type ReadData(uint64_t K, const unsigned char *D, offset_type Length)
static uint64_t GetExternalKey(external_key_type K)
CallStackRadixTreeBuilder()=default
ArrayRef< LinearFrameId > getRadixArray() const
llvm::DenseMap< CallStackId, LinearCallStackId > takeCallStackPos()
static hash_value_type ComputeHash(key_type_ref K)
static std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type)
Helper class to iterate through stack ids in both metadata (memprof MIB and callsite) and the corresp...
data_type ReadData(uint64_t K, const unsigned char *D, offset_type)
static uint64_t GetExternalKey(external_key_type K)
static bool EqualKey(internal_key_type A, internal_key_type B)
static uint64_t GetInternalKey(internal_key_type K)
static std::pair< offset_type, offset_type > ReadKeyDataLength(const unsigned char *&D)
hash_value_type ComputeHash(internal_key_type K)
uint64_t ReadKey(const unsigned char *D, offset_type)
static hash_value_type ComputeHash(key_type_ref K)
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type)
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
static std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
static bool EqualKey(uint64_t A, uint64_t B)
uint64_t ReadKey(const unsigned char *D, offset_type)
data_type ReadData(uint64_t K, const unsigned char *D, offset_type)
static std::pair< offset_type, offset_type > ReadKeyDataLength(const unsigned char *&D)
static uint64_t GetInternalKey(uint64_t K)
hash_value_type ComputeHash(uint64_t K)
static uint64_t GetExternalKey(uint64_t K)
RecordLookupTrait(IndexedVersion V, const MemProfSchema &S)
RecordLookupTrait()=delete
static hash_value_type ComputeHash(key_type_ref K)
RecordWriterTrait(const MemProfSchema *Schema, IndexedVersion V, llvm::DenseMap< CallStackId, LinearCallStackId > *MemProfCallStackIndexes)
std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
RecordWriterTrait()=delete
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type)
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
value_type DerefIterator(IterTy Iter)
constexpr uint64_t MaximumSupportedVersion
MemProfSchema getHotColdSchema()
uint32_t LinearCallStackId
constexpr uint64_t MinimumSupportedVersion
std::pair< LineLocation, uint64_t > CallEdgeTy
MemProfSchema getFullSchema()
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
llvm::DenseMap< FrameIdTy, FrameStat > computeFrameHistogram(llvm::MapVector< CallStackId, llvm::SmallVector< FrameIdTy > > &MemProfCallStackData)
This is an optimization pass for GlobalISel generic memory operations.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
std::array< uint8_t, NumBytes > BLAKE3Result
The constant LLVM_BLAKE3_OUT_LEN provides the default output length, 32 bytes, which is recommended f...
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
typename llvm::remove_cvref< T >::type remove_cvref_t
std::vector< Frame > CallStack
PortableMemInfoBlock Info
void printYAML(raw_ostream &OS) const
CallStackIdConverter & operator=(const CallStackIdConverter &)=delete
CallStackIdConverter()=delete
llvm::function_ref< Frame(FrameId)> FrameIdToFrame
std::optional< CallStackId > LastUnmappedId
CallStackIdConverter(MapTy &Map, llvm::function_ref< Frame(FrameId)> FrameIdToFrame)
std::vector< Frame > operator()(CallStackId CSId)
CallStackIdConverter(const CallStackIdConverter &)=delete
FrameIdConverter(const FrameIdConverter &)=delete
Frame operator()(FrameId Id)
FrameIdConverter(MapTy &Map)
std::optional< FrameId > LastUnmappedId
FrameIdConverter()=delete
FrameIdConverter & operator=(const FrameIdConverter &)=delete
Frame & operator=(const Frame &Other)
Frame(const Frame &Other)
static constexpr size_t serializedSize()
void printYAML(raw_ostream &OS) const
void serialize(raw_ostream &OS) const
bool hasSymbolName() const
std::string getSymbolNameOr(StringRef Alt) const
StringRef getSymbolName() const
bool operator==(const Frame &Other) const
bool operator!=(const Frame &Other) const
static Frame deserialize(const unsigned char *Ptr)
Frame(GlobalValue::GUID Hash, uint32_t Off, uint32_t Col, bool Inline)
std::unique_ptr< std::string > SymbolName
IndexedAllocationInfo(CallStackId CSId, const MemInfoBlock &MB, const MemProfSchema &Schema=getFullSchema())
bool operator==(const IndexedAllocationInfo &Other) const
bool operator!=(const IndexedAllocationInfo &Other) const
PortableMemInfoBlock Info
IndexedAllocationInfo(CallStackId CSId, const PortableMemInfoBlock &MB)
IndexedAllocationInfo()=default
IndexedCallstackIdConveter(IndexedMemProfData &MemProfData)
IndexedCallstackIdConveter(const IndexedCallstackIdConveter &)=delete
IndexedCallstackIdConveter & operator=(const IndexedCallstackIdConveter &)=delete
IndexedCallstackIdConveter()=delete
std::vector< Frame > operator()(CallStackId CSId)
llvm::MapVector< CallStackId, llvm::SmallVector< FrameId > > CallStacks
CallStackId addCallStack(SmallVector< FrameId > &&CS)
llvm::MapVector< GlobalValue::GUID, IndexedMemProfRecord > Records
CallStackId addCallStack(ArrayRef< FrameId > CS)
FrameId addFrame(const Frame &F)
llvm::MapVector< FrameId, Frame > Frames
llvm::SmallVector< CallStackId > CallSiteIds
llvm::SmallVector< IndexedAllocationInfo > AllocSites
bool operator==(const IndexedMemProfRecord &Other) const
void merge(const IndexedMemProfRecord &Other)
LineLocation(uint32_t L, uint32_t D)
bool operator!=(const LineLocation &O) const
bool operator==(const LineLocation &O) const
bool operator<(const LineLocation &O) const
uint64_t getHashCode() const
llvm::function_ref< Frame(LinearFrameId)> FrameIdToFrame
const unsigned char * CallStackBase
LinearCallStackIdConverter()=delete
std::vector< Frame > operator()(LinearCallStackId LinearCSId)
LinearCallStackIdConverter(const unsigned char *CallStackBase, llvm::function_ref< Frame(LinearFrameId)> FrameIdToFrame)
LinearFrameIdConverter()=delete
LinearFrameIdConverter(const unsigned char *FrameBase)
const unsigned char * FrameBase
Frame operator()(LinearFrameId LinearId)
llvm::SmallVector< std::vector< Frame > > CallSites
llvm::SmallVector< AllocationInfo > AllocSites
void print(llvm::raw_ostream &OS) const
bool operator!=(const PortableMemInfoBlock &Other) const
void deserialize(const MemProfSchema &IncomingSchema, const unsigned char *Ptr)
PortableMemInfoBlock(const MemProfSchema &Schema, const unsigned char *Ptr)
PortableMemInfoBlock()=default
std::bitset< llvm::to_underlying(Meta::Size)> getSchema() const
static size_t serializedSize(const MemProfSchema &Schema)
void printYAML(raw_ostream &OS) const
void serialize(const MemProfSchema &Schema, raw_ostream &OS) const
PortableMemInfoBlock(const MemInfoBlock &Block, const MemProfSchema &IncomingSchema)
bool operator==(const PortableMemInfoBlock &Other) const
Adapter to write values to a stream in a particular byte order.