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