LLVM 19.0.0git
MemProf.cpp
Go to the documentation of this file.
3#include "llvm/IR/Function.h"
10
11namespace llvm {
12namespace memprof {
13static size_t serializedSizeV0(const IndexedAllocationInfo &IAI,
14 const MemProfSchema &Schema) {
15 size_t Size = 0;
16 // The number of frames to serialize.
17 Size += sizeof(uint64_t);
18 // The callstack frame ids.
19 Size += sizeof(FrameId) * IAI.CallStack.size();
20 // The size of the payload.
22 return Size;
23}
24
25static size_t serializedSizeV2(const IndexedAllocationInfo &IAI,
26 const MemProfSchema &Schema) {
27 size_t Size = 0;
28 // The CallStackId
29 Size += sizeof(CallStackId);
30 // The size of the payload.
32 return Size;
33}
34
36 IndexedVersion Version) const {
37 switch (Version) {
38 case Version0:
39 case Version1:
40 return serializedSizeV0(*this, Schema);
41 case Version2:
42 return serializedSizeV2(*this, Schema);
43 }
44 llvm_unreachable("unsupported MemProf version");
45}
46
48 const MemProfSchema &Schema) {
49 // The number of alloc sites to serialize.
50 size_t Result = sizeof(uint64_t);
51 for (const IndexedAllocationInfo &N : Record.AllocSites)
52 Result += N.serializedSize(Schema, Version0);
53
54 // The number of callsites we have information for.
55 Result += sizeof(uint64_t);
56 for (const auto &Frames : Record.CallSites) {
57 // The number of frame ids to serialize.
58 Result += sizeof(uint64_t);
59 Result += Frames.size() * sizeof(FrameId);
60 }
61 return Result;
62}
63
65 const MemProfSchema &Schema) {
66 // The number of alloc sites to serialize.
67 size_t Result = sizeof(uint64_t);
68 for (const IndexedAllocationInfo &N : Record.AllocSites)
69 Result += N.serializedSize(Schema, Version2);
70
71 // The number of callsites we have information for.
72 Result += sizeof(uint64_t);
73 // The CallStackId
74 Result += Record.CallSiteIds.size() * sizeof(CallStackId);
75 return Result;
76}
77
79 IndexedVersion Version) const {
80 switch (Version) {
81 case Version0:
82 case Version1:
83 return serializedSizeV0(*this, Schema);
84 case Version2:
85 return serializedSizeV2(*this, Schema);
86 }
87 llvm_unreachable("unsupported MemProf version");
88}
89
91 const MemProfSchema &Schema, raw_ostream &OS) {
92 using namespace support;
93
95
96 LE.write<uint64_t>(Record.AllocSites.size());
97 for (const IndexedAllocationInfo &N : Record.AllocSites) {
98 LE.write<uint64_t>(N.CallStack.size());
99 for (const FrameId &Id : N.CallStack)
100 LE.write<FrameId>(Id);
101 N.Info.serialize(Schema, OS);
102 }
103
104 // Related contexts.
105 LE.write<uint64_t>(Record.CallSites.size());
106 for (const auto &Frames : Record.CallSites) {
107 LE.write<uint64_t>(Frames.size());
108 for (const FrameId &Id : Frames)
109 LE.write<FrameId>(Id);
110 }
111}
112
114 const MemProfSchema &Schema, raw_ostream &OS) {
115 using namespace support;
116
118
119 LE.write<uint64_t>(Record.AllocSites.size());
120 for (const IndexedAllocationInfo &N : Record.AllocSites) {
121 LE.write<CallStackId>(N.CSId);
122 N.Info.serialize(Schema, OS);
123 }
124
125 // Related contexts.
126 LE.write<uint64_t>(Record.CallSiteIds.size());
127 for (const auto &CSId : Record.CallSiteIds)
128 LE.write<CallStackId>(CSId);
129}
130
132 raw_ostream &OS, IndexedVersion Version) {
133 switch (Version) {
134 case Version0:
135 case Version1:
136 serializeV0(*this, Schema, OS);
137 return;
138 case Version2:
139 serializeV2(*this, Schema, OS);
140 return;
141 }
142 llvm_unreachable("unsupported MemProf version");
143}
144
146 const unsigned char *Ptr) {
147 using namespace support;
148
150
151 // Read the meminfo nodes.
152 const uint64_t NumNodes =
153 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
154 for (uint64_t I = 0; I < NumNodes; I++) {
156 const uint64_t NumFrames =
157 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
158 for (uint64_t J = 0; J < NumFrames; J++) {
159 const FrameId Id =
160 endian::readNext<FrameId, llvm::endianness::little>(Ptr);
161 Node.CallStack.push_back(Id);
162 }
163 Node.CSId = hashCallStack(Node.CallStack);
164 Node.Info.deserialize(Schema, Ptr);
166 Record.AllocSites.push_back(Node);
167 }
168
169 // Read the callsite information.
170 const uint64_t NumCtxs =
171 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
172 for (uint64_t J = 0; J < NumCtxs; J++) {
173 const uint64_t NumFrames =
174 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
176 Frames.reserve(NumFrames);
177 for (uint64_t K = 0; K < NumFrames; K++) {
178 const FrameId Id =
179 endian::readNext<FrameId, llvm::endianness::little>(Ptr);
180 Frames.push_back(Id);
181 }
182 Record.CallSites.push_back(Frames);
183 Record.CallSiteIds.push_back(hashCallStack(Frames));
184 }
185
186 return Record;
187}
188
190 const unsigned char *Ptr) {
191 using namespace support;
192
194
195 // Read the meminfo nodes.
196 const uint64_t NumNodes =
197 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
198 for (uint64_t I = 0; I < NumNodes; I++) {
200 Node.CSId = endian::readNext<CallStackId, llvm::endianness::little>(Ptr);
201 Node.Info.deserialize(Schema, Ptr);
203 Record.AllocSites.push_back(Node);
204 }
205
206 // Read the callsite information.
207 const uint64_t NumCtxs =
208 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
209 for (uint64_t J = 0; J < NumCtxs; J++) {
210 CallStackId CSId =
211 endian::readNext<CallStackId, llvm::endianness::little>(Ptr);
212 Record.CallSiteIds.push_back(CSId);
213 }
214
215 return Record;
216}
217
218IndexedMemProfRecord
220 const unsigned char *Ptr,
221 IndexedVersion Version) {
222 switch (Version) {
223 case Version0:
224 case Version1:
225 return deserializeV0(Schema, Ptr);
226 case Version2:
227 return deserializeV2(Schema, Ptr);
228 }
229 llvm_unreachable("unsupported MemProf version");
230}
231
233 std::function<const llvm::SmallVector<Frame>(const CallStackId)> Callback)
234 const {
236
237 for (const memprof::IndexedAllocationInfo &IndexedAI : AllocSites) {
239 AI.Info = IndexedAI.Info;
240 AI.CallStack = Callback(IndexedAI.CSId);
241 Record.AllocSites.push_back(AI);
242 }
243
245 Record.CallSites.push_back(Callback(CSId));
246
247 return Record;
248}
249
251 // Canonicalize the function name to drop suffixes such as ".llvm.". Note
252 // we do not drop any ".__uniq." suffixes, as getCanonicalFnName does not drop
253 // those by default. This is by design to differentiate internal linkage
254 // functions during matching. By dropping the other suffixes we can then match
255 // functions in the profile use phase prior to their addition. Note that this
256 // applies to both instrumented and sampled function names.
257 StringRef CanonicalName =
259
260 // We use the function guid which we expect to be a uint64_t. At
261 // this time, it is the lower 64 bits of the md5 of the canonical
262 // function name.
263 return Function::getGUID(CanonicalName);
264}
265
266Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
267 using namespace support;
268
269 const unsigned char *Ptr = Buffer;
270 const uint64_t NumSchemaIds =
271 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
272 if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
273 return make_error<InstrProfError>(instrprof_error::malformed,
274 "memprof schema invalid");
275 }
276
277 MemProfSchema Result;
278 for (size_t I = 0; I < NumSchemaIds; I++) {
279 const uint64_t Tag =
280 endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
281 if (Tag >= static_cast<uint64_t>(Meta::Size)) {
282 return make_error<InstrProfError>(instrprof_error::malformed,
283 "memprof schema invalid");
284 }
285 Result.push_back(static_cast<Meta>(Tag));
286 }
287 // Advace the buffer to one past the schema if we succeeded.
288 Buffer = Ptr;
289 return Result;
290}
291
295 for (FrameId F : CS)
298 CallStackId CSId;
299 std::memcpy(&CSId, Hash.data(), sizeof(Hash));
300 return CSId;
301}
302
304 for (const auto &AS : Record.AllocSites) {
305 assert(AS.CSId == hashCallStack(AS.CallStack));
306 (void)AS;
307 }
308}
309
312 &FunctionProfileData) {
313 for (const auto &[GUID, Record] : FunctionProfileData) {
314 (void)GUID;
316 }
317}
318
319} // namespace memprof
320} // 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:303
CallStackId hashCallStack(ArrayRef< FrameId > CS)
Definition: MemProf.cpp:292
static size_t serializedSizeV2(const IndexedAllocationInfo &IAI, const MemProfSchema &Schema)
Definition: MemProf.cpp:25
static size_t serializedSizeV0(const IndexedAllocationInfo &IAI, const MemProfSchema &Schema)
Definition: MemProf.cpp:13
static void serializeV0(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS)
Definition: MemProf.cpp:90
uint64_t FrameId
Definition: MemProf.h:174
static IndexedMemProfRecord deserializeV0(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition: MemProf.cpp:145
uint64_t CallStackId
Definition: MemProf.h:292
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
Definition: MemProf.cpp:266
void verifyFunctionProfileData(const llvm::MapVector< GlobalValue::GUID, IndexedMemProfRecord > &FunctionProfileData)
Definition: MemProf.cpp:310
static void serializeV2(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS)
Definition: MemProf.cpp:113
static IndexedMemProfRecord deserializeV2(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition: MemProf.cpp:189
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:336
llvm::SmallVector< Frame > CallStack
Definition: MemProf.h:334
size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition: MemProf.cpp:35
llvm::SmallVector< FrameId > CallStack
Definition: MemProf.h:300
llvm::SmallVector< CallStackId > CallSiteIds
Definition: MemProf.h:375
llvm::SmallVector< IndexedAllocationInfo > AllocSites
Definition: MemProf.h:366
size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition: MemProf.cpp:78
static IndexedMemProfRecord deserialize(const MemProfSchema &Schema, const unsigned char *Buffer, IndexedVersion Version)
Definition: MemProf.cpp:219
MemProfRecord toMemProfRecord(std::function< const llvm::SmallVector< Frame >(const CallStackId)> Callback) const
Definition: MemProf.cpp:232
void serialize(const MemProfSchema &Schema, raw_ostream &OS, IndexedVersion Version)
Definition: MemProf.cpp:131
static GlobalValue::GUID getGUID(const StringRef FunctionName)
Definition: MemProf.cpp:250
static size_t serializedSize(const MemProfSchema &Schema)
Definition: MemProf.h:148
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:67