LLVM 19.0.0git
MemProf.cpp
Go to the documentation of this file.
3#include "llvm/IR/Function.h"
10
11namespace llvm {
12namespace memprof {
15#define MIBEntryDef(NameTag, Name, Type) List.push_back(Meta::Name);
17#undef MIBEntryDef
18 return List;
19}
20
22 return {Meta::AllocCount, Meta::TotalSize, Meta::TotalLifetime,
23 Meta::TotalLifetimeAccessDensity};
24}
25
26static size_t serializedSizeV0(const IndexedAllocationInfo &IAI,
27 const MemProfSchema &Schema) {
28 size_t Size = 0;
29 // The number of frames to serialize.
30 Size += sizeof(uint64_t);
31 // The callstack frame ids.
32 Size += sizeof(FrameId) * IAI.CallStack.size();
33 // The size of the payload.
35 return Size;
36}
37
38static size_t serializedSizeV2(const IndexedAllocationInfo &IAI,
39 const MemProfSchema &Schema) {
40 size_t Size = 0;
41 // The CallStackId
42 Size += sizeof(CallStackId);
43 // The size of the payload.
45 return Size;
46}
47
49 IndexedVersion Version) const {
50 switch (Version) {
51 case Version0:
52 case Version1:
53 return serializedSizeV0(*this, Schema);
54 case Version2:
55 return serializedSizeV2(*this, Schema);
56 }
57 llvm_unreachable("unsupported MemProf version");
58}
59
61 const MemProfSchema &Schema) {
62 // The number of alloc sites to serialize.
63 size_t Result = sizeof(uint64_t);
64 for (const IndexedAllocationInfo &N : Record.AllocSites)
65 Result += N.serializedSize(Schema, Version0);
66
67 // The number of callsites we have information for.
68 Result += sizeof(uint64_t);
69 for (const auto &Frames : Record.CallSites) {
70 // The number of frame ids to serialize.
71 Result += sizeof(uint64_t);
72 Result += Frames.size() * sizeof(FrameId);
73 }
74 return Result;
75}
76
78 const MemProfSchema &Schema) {
79 // The number of alloc sites to serialize.
80 size_t Result = sizeof(uint64_t);
81 for (const IndexedAllocationInfo &N : Record.AllocSites)
82 Result += N.serializedSize(Schema, Version2);
83
84 // The number of callsites we have information for.
85 Result += sizeof(uint64_t);
86 // The CallStackId
87 Result += Record.CallSiteIds.size() * sizeof(CallStackId);
88 return Result;
89}
90
92 IndexedVersion Version) const {
93 switch (Version) {
94 case Version0:
95 case Version1:
96 return serializedSizeV0(*this, Schema);
97 case Version2:
98 return serializedSizeV2(*this, Schema);
99 }
100 llvm_unreachable("unsupported MemProf version");
101}
102
104 const MemProfSchema &Schema, raw_ostream &OS) {
105 using namespace support;
106
108
109 LE.write<uint64_t>(Record.AllocSites.size());
110 for (const IndexedAllocationInfo &N : Record.AllocSites) {
111 LE.write<uint64_t>(N.CallStack.size());
112 for (const FrameId &Id : N.CallStack)
113 LE.write<FrameId>(Id);
114 N.Info.serialize(Schema, OS);
115 }
116
117 // Related contexts.
118 LE.write<uint64_t>(Record.CallSites.size());
119 for (const auto &Frames : Record.CallSites) {
120 LE.write<uint64_t>(Frames.size());
121 for (const FrameId &Id : Frames)
122 LE.write<FrameId>(Id);
123 }
124}
125
127 const MemProfSchema &Schema, raw_ostream &OS) {
128 using namespace support;
129
131
132 LE.write<uint64_t>(Record.AllocSites.size());
133 for (const IndexedAllocationInfo &N : Record.AllocSites) {
134 LE.write<CallStackId>(N.CSId);
135 N.Info.serialize(Schema, OS);
136 }
137
138 // Related contexts.
139 LE.write<uint64_t>(Record.CallSiteIds.size());
140 for (const auto &CSId : Record.CallSiteIds)
141 LE.write<CallStackId>(CSId);
142}
143
145 raw_ostream &OS, IndexedVersion Version) {
146 switch (Version) {
147 case Version0:
148 case Version1:
149 serializeV0(*this, Schema, OS);
150 return;
151 case Version2:
152 serializeV2(*this, Schema, OS);
153 return;
154 }
155 llvm_unreachable("unsupported MemProf version");
156}
157
159 const unsigned char *Ptr) {
160 using namespace support;
161
163
164 // Read the meminfo nodes.
165 const uint64_t NumNodes =
166 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
167 for (uint64_t I = 0; I < NumNodes; I++) {
169 const uint64_t NumFrames =
170 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
171 for (uint64_t J = 0; J < NumFrames; J++) {
172 const FrameId Id =
173 endian::readNext<FrameId, llvm::endianness::little>(Ptr);
174 Node.CallStack.push_back(Id);
175 }
176 Node.CSId = hashCallStack(Node.CallStack);
177 Node.Info.deserialize(Schema, Ptr);
179 Record.AllocSites.push_back(Node);
180 }
181
182 // Read the callsite information.
183 const uint64_t NumCtxs =
184 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
185 for (uint64_t J = 0; J < NumCtxs; J++) {
186 const uint64_t NumFrames =
187 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
189 Frames.reserve(NumFrames);
190 for (uint64_t K = 0; K < NumFrames; K++) {
191 const FrameId Id =
192 endian::readNext<FrameId, llvm::endianness::little>(Ptr);
193 Frames.push_back(Id);
194 }
195 Record.CallSites.push_back(Frames);
196 Record.CallSiteIds.push_back(hashCallStack(Frames));
197 }
198
199 return Record;
200}
201
203 const unsigned char *Ptr) {
204 using namespace support;
205
207
208 // Read the meminfo nodes.
209 const uint64_t NumNodes =
210 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
211 for (uint64_t I = 0; I < NumNodes; I++) {
213 Node.CSId = endian::readNext<CallStackId, llvm::endianness::little>(Ptr);
214 Node.Info.deserialize(Schema, Ptr);
216 Record.AllocSites.push_back(Node);
217 }
218
219 // Read the callsite information.
220 const uint64_t NumCtxs =
221 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
222 for (uint64_t J = 0; J < NumCtxs; J++) {
223 CallStackId CSId =
224 endian::readNext<CallStackId, llvm::endianness::little>(Ptr);
225 Record.CallSiteIds.push_back(CSId);
226 }
227
228 return Record;
229}
230
231IndexedMemProfRecord
233 const unsigned char *Ptr,
234 IndexedVersion Version) {
235 switch (Version) {
236 case Version0:
237 case Version1:
238 return deserializeV0(Schema, Ptr);
239 case Version2:
240 return deserializeV2(Schema, Ptr);
241 }
242 llvm_unreachable("unsupported MemProf version");
243}
244
246 std::function<const llvm::SmallVector<Frame>(const CallStackId)> Callback)
247 const {
249
250 for (const memprof::IndexedAllocationInfo &IndexedAI : AllocSites) {
252 AI.Info = IndexedAI.Info;
253 AI.CallStack = Callback(IndexedAI.CSId);
254 Record.AllocSites.push_back(AI);
255 }
256
258 Record.CallSites.push_back(Callback(CSId));
259
260 return Record;
261}
262
264 // Canonicalize the function name to drop suffixes such as ".llvm.". Note
265 // we do not drop any ".__uniq." suffixes, as getCanonicalFnName does not drop
266 // those by default. This is by design to differentiate internal linkage
267 // functions during matching. By dropping the other suffixes we can then match
268 // functions in the profile use phase prior to their addition. Note that this
269 // applies to both instrumented and sampled function names.
270 StringRef CanonicalName =
272
273 // We use the function guid which we expect to be a uint64_t. At
274 // this time, it is the lower 64 bits of the md5 of the canonical
275 // function name.
276 return Function::getGUID(CanonicalName);
277}
278
279Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
280 using namespace support;
281
282 const unsigned char *Ptr = Buffer;
283 const uint64_t NumSchemaIds =
284 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
285 if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
286 return make_error<InstrProfError>(instrprof_error::malformed,
287 "memprof schema invalid");
288 }
289
290 MemProfSchema Result;
291 for (size_t I = 0; I < NumSchemaIds; I++) {
292 const uint64_t Tag =
293 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
294 if (Tag >= static_cast<uint64_t>(Meta::Size)) {
295 return make_error<InstrProfError>(instrprof_error::malformed,
296 "memprof schema invalid");
297 }
298 Result.push_back(static_cast<Meta>(Tag));
299 }
300 // Advace the buffer to one past the schema if we succeeded.
301 Buffer = Ptr;
302 return Result;
303}
304
308 for (FrameId F : CS)
311 CallStackId CSId;
312 std::memcpy(&CSId, Hash.data(), sizeof(Hash));
313 return CSId;
314}
315
317 for (const auto &AS : Record.AllocSites) {
318 assert(AS.CSId == hashCallStack(AS.CallStack));
319 (void)AS;
320 }
321}
322
325 &FunctionProfileData) {
326 for (const auto &[GUID, Record] : FunctionProfileData) {
327 (void)GUID;
329 }
330}
331
332} // namespace memprof
333} // namespace llvm
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Tagged union holding either a T or a Error.
Definition: Error.h:474
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
Definition: GlobalValue.h:595
HashResultTy< HasherT_ > final()
Forward to HasherT::final() if available.
Definition: HashBuilder.h:66
Interface to help hash various types through a hasher type.
Definition: HashBuilder.h:139
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.
Definition: HashBuilder.h:149
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
void reserve(size_type N)
Definition: SmallVector.h:676
void push_back(const T &Elt)
Definition: SmallVector.h:426
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
Definition: SampleProf.h:1085
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void verifyIndexedMemProfRecord(const IndexedMemProfRecord &Record)
Definition: MemProf.cpp:316
MemProfSchema getHotColdSchema()
Definition: MemProf.cpp:21
CallStackId hashCallStack(ArrayRef< FrameId > CS)
Definition: MemProf.cpp:305
static size_t serializedSizeV2(const IndexedAllocationInfo &IAI, const MemProfSchema &Schema)
Definition: MemProf.cpp:38
static size_t serializedSizeV0(const IndexedAllocationInfo &IAI, const MemProfSchema &Schema)
Definition: MemProf.cpp:26
static void serializeV0(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS)
Definition: MemProf.cpp:103
uint64_t FrameId
Definition: MemProf.h:164
static IndexedMemProfRecord deserializeV0(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition: MemProf.cpp:158
uint64_t CallStackId
Definition: MemProf.h:282
MemProfSchema getFullSchema()
Definition: MemProf.cpp:13
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
Definition: MemProf.cpp:279
void verifyFunctionProfileData(const llvm::MapVector< GlobalValue::GUID, IndexedMemProfRecord > &FunctionProfileData)
Definition: MemProf.cpp:323
static void serializeV2(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS)
Definition: MemProf.cpp:126
static IndexedMemProfRecord deserializeV2(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition: MemProf.cpp:202
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::array< uint8_t, NumBytes > BLAKE3Result
The constant LLVM_BLAKE3_OUT_LEN provides the default output length, 32 bytes, which is recommended f...
Definition: BLAKE3.h:35
#define N
PortableMemInfoBlock Info
Definition: MemProf.h:326
llvm::SmallVector< Frame > CallStack
Definition: MemProf.h:324
size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition: MemProf.cpp:48
llvm::SmallVector< FrameId > CallStack
Definition: MemProf.h:290
llvm::SmallVector< CallStackId > CallSiteIds
Definition: MemProf.h:365
llvm::SmallVector< IndexedAllocationInfo > AllocSites
Definition: MemProf.h:356
size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition: MemProf.cpp:91
static IndexedMemProfRecord deserialize(const MemProfSchema &Schema, const unsigned char *Buffer, IndexedVersion Version)
Definition: MemProf.cpp:232
MemProfRecord toMemProfRecord(std::function< const llvm::SmallVector< Frame >(const CallStackId)> Callback) const
Definition: MemProf.cpp:245
void serialize(const MemProfSchema &Schema, raw_ostream &OS, IndexedVersion Version)
Definition: MemProf.cpp:144
static GlobalValue::GUID getGUID(const StringRef FunctionName)
Definition: MemProf.cpp:263
static size_t serializedSize(const MemProfSchema &Schema)
Definition: MemProf.h:138
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:67