LLVM 24.0.0git
MemProf.cpp
Go to the documentation of this file.
3#include "llvm/IR/Function.h"
8
9namespace llvm {
10namespace memprof {
13#define MIBEntryDef(NameTag, Name, Type) List.push_back(Meta::Name);
15#undef MIBEntryDef
16 return List;
17}
18
20 return {Meta::AllocCount, Meta::TotalSize, Meta::TotalLifetime,
21 Meta::TotalLifetimeAccessDensity};
22}
23
24static size_t serializedSizeV3(const IndexedAllocationInfo &IAI,
25 const MemProfSchema &Schema) {
26 size_t Size = 0;
27 // The linear call stack ID.
28 Size += sizeof(LinearCallStackId);
29 // The size of the payload.
31 return Size;
32}
33
35 IndexedVersion Version) const {
36 switch (Version) {
37 // Combine V3 and V4 as the size calculation is the same
38 case Version3:
39 case Version4:
40 return serializedSizeV3(*this, Schema);
41 }
42 llvm_unreachable("unsupported MemProf version");
43}
44
46 const MemProfSchema &Schema) {
47 // The number of alloc sites to serialize.
48 size_t Result = sizeof(uint64_t);
49 for (const IndexedAllocationInfo &N : Record.AllocSites)
50 Result += N.serializedSize(Schema, Version3);
51
52 // The number of callsites we have information for.
53 Result += sizeof(uint64_t);
54 // The linear call stack ID.
55 // Note: V3 only stored the LinearCallStackId per call site.
56 Result += Record.CallSites.size() * sizeof(LinearCallStackId);
57 return Result;
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, Version4);
66
67 // The number of callsites we have information for.
68 Result += sizeof(uint64_t);
69 for (const auto &CS : Record.CallSites)
70 Result += sizeof(LinearCallStackId) + sizeof(uint64_t) +
71 CS.CalleeGuids.size() * sizeof(GlobalValue::GUID);
72 return Result;
73}
74
76 IndexedVersion Version) const {
77 switch (Version) {
78 case Version3:
79 return serializedSizeV3(*this, Schema);
80 case Version4:
81 return serializedSizeV4(*this, Schema);
82 }
83 llvm_unreachable("unsupported MemProf version");
84}
85
86static void serializeV3(
87 const IndexedMemProfRecord &Record, const MemProfSchema &Schema,
88 raw_ostream &OS,
89 llvm::DenseMap<CallStackId, LinearCallStackId> &MemProfCallStackIndexes) {
90 using namespace support;
91
93
94 LE.write<uint64_t>(Record.AllocSites.size());
95 for (const IndexedAllocationInfo &N : Record.AllocSites) {
96 assert(MemProfCallStackIndexes.contains(N.CSId));
97 LE.write<LinearCallStackId>(MemProfCallStackIndexes[N.CSId]);
98 N.Info.serialize(Schema, OS);
99 }
100
101 // Related contexts.
102 LE.write<uint64_t>(Record.CallSites.size());
103 for (const auto &CS : Record.CallSites) {
104 assert(MemProfCallStackIndexes.contains(CS.CSId));
105 LE.write<LinearCallStackId>(MemProfCallStackIndexes[CS.CSId]);
106 }
107}
108
109static void serializeV4(
110 const IndexedMemProfRecord &Record, const MemProfSchema &Schema,
111 raw_ostream &OS,
112 llvm::DenseMap<CallStackId, LinearCallStackId> &MemProfCallStackIndexes) {
113 using namespace support;
114
116
117 LE.write<uint64_t>(Record.AllocSites.size());
118 for (const IndexedAllocationInfo &N : Record.AllocSites) {
119 assert(MemProfCallStackIndexes.contains(N.CSId));
120 LE.write<LinearCallStackId>(MemProfCallStackIndexes[N.CSId]);
121 N.Info.serialize(Schema, OS);
122 }
123
124 // Related contexts.
125 LE.write<uint64_t>(Record.CallSites.size());
126 for (const auto &CS : Record.CallSites) {
127 assert(MemProfCallStackIndexes.contains(CS.CSId));
128 LE.write<LinearCallStackId>(MemProfCallStackIndexes[CS.CSId]);
129 LE.write<uint64_t>(CS.CalleeGuids.size());
130 for (const auto &Guid : CS.CalleeGuids)
131 LE.write<GlobalValue::GUID>(Guid);
132 }
133}
134
137 llvm::DenseMap<CallStackId, LinearCallStackId> *MemProfCallStackIndexes)
138 const {
139 switch (Version) {
140 case Version3:
141 serializeV3(*this, Schema, OS, *MemProfCallStackIndexes);
142 return;
143 case Version4:
144 serializeV4(*this, Schema, OS, *MemProfCallStackIndexes);
145 return;
146 }
147 llvm_unreachable("unsupported MemProf version");
148}
149
151 const unsigned char *Ptr) {
152 using namespace support;
153
155
156 // Read the meminfo nodes.
157 const uint64_t NumNodes =
159 Record.AllocSites.reserve(NumNodes);
160 const size_t SerializedSize = PortableMemInfoBlock::serializedSize(Schema);
161 for (uint64_t I = 0; I < NumNodes; I++) {
163 Node.CSId =
165 Node.Info.deserialize(Schema, Ptr);
166 Ptr += SerializedSize;
167 Record.AllocSites.push_back(Node);
168 }
169
170 // Read the callsite information.
171 const uint64_t NumCtxs =
173 Record.CallSites.reserve(NumCtxs);
174 for (uint64_t J = 0; J < NumCtxs; J++) {
175 // We are storing LinearCallStackId in CallSiteIds, which is a vector of
176 // CallStackId. Assert that CallStackId is no smaller than
177 // LinearCallStackId.
178 static_assert(sizeof(LinearCallStackId) <= sizeof(CallStackId));
179 LinearCallStackId CSId =
181 Record.CallSites.emplace_back(CSId);
182 }
183
184 return Record;
185}
186
188 const unsigned char *Ptr) {
189 using namespace support;
190
192
193 // Read the meminfo nodes.
194 const uint64_t NumNodes =
196 Record.AllocSites.reserve(NumNodes);
197 const size_t SerializedSize = PortableMemInfoBlock::serializedSize(Schema);
198 for (uint64_t I = 0; I < NumNodes; I++) {
200 Node.CSId =
202 Node.Info.deserialize(Schema, Ptr);
203 Ptr += SerializedSize;
204 Record.AllocSites.push_back(Node);
205 }
206
207 // Read the callsite information.
208 const uint64_t NumCtxs =
210 Record.CallSites.reserve(NumCtxs);
211 for (uint64_t J = 0; J < NumCtxs; J++) {
212 static_assert(sizeof(LinearCallStackId) <= sizeof(CallStackId));
213 LinearCallStackId CSId =
215 const uint64_t NumGuids =
218 Guids.reserve(NumGuids);
219 for (uint64_t K = 0; K < NumGuids; ++K)
220 Guids.push_back(
222 Record.CallSites.emplace_back(CSId, std::move(Guids));
223 }
224
225 return Record;
226}
227
228IndexedMemProfRecord
230 const unsigned char *Ptr,
232 switch (Version) {
233 case Version3:
234 return deserializeV3(Schema, Ptr);
235 case Version4:
236 return deserializeV4(Schema, Ptr);
237 }
238 llvm_unreachable("unsupported MemProf version");
239}
240
242 llvm::function_ref<std::vector<Frame>(const CallStackId)> Callback) const {
244
245 Record.AllocSites.reserve(AllocSites.size());
246 for (const IndexedAllocationInfo &IndexedAI : AllocSites) {
248 AI.Info = IndexedAI.Info;
249 AI.CallStack = Callback(IndexedAI.CSId);
250 Record.AllocSites.push_back(std::move(AI));
251 }
252
253 Record.CallSites.reserve(CallSites.size());
254 for (const IndexedCallSiteInfo &CS : CallSites) {
255 std::vector<Frame> Frames = Callback(CS.CSId);
256 Record.CallSites.emplace_back(std::move(Frames), CS.CalleeGuids);
257 }
258
259 return Record;
260}
261
263 // Canonicalize the function name to drop suffixes such as ".llvm.". Note
264 // we do not drop any ".__uniq." suffixes, as getCanonicalFnName does not drop
265 // those by default. This is by design to differentiate internal linkage
266 // functions during matching. By dropping the other suffixes we can then match
267 // functions in the profile use phase prior to their addition. Note that this
268 // applies to both instrumented and sampled function names.
269 StringRef CanonicalName =
271
272 // We use the function guid which we expect to be a uint64_t. At
273 // this time, it is the lower 64 bits of the md5 of the canonical
274 // function name.
275 return Function::getGUIDAssumingExternalLinkage(CanonicalName);
276}
277
278Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
279 using namespace support;
280
281 const unsigned char *Ptr = Buffer;
282 const uint64_t NumSchemaIds =
284 if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
286 "memprof schema invalid");
287 }
288
289 MemProfSchema Result;
290 for (size_t I = 0; I < NumSchemaIds; I++) {
291 const uint64_t Tag =
293 if (Tag >= static_cast<uint64_t>(Meta::Size)) {
295 "memprof schema invalid");
296 }
297 Result.push_back(static_cast<Meta>(Tag));
298 }
299 // Advance the buffer to one past the schema if we succeeded.
300 Buffer = Ptr;
301 return Result;
302}
303} // namespace memprof
304} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the SmallVector class.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:758
Tagged union holding either a T or a Error.
Definition Error.h:485
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:80
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static IndexedMemProfRecord deserializeV4(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition MemProf.cpp:187
uint32_t LinearCallStackId
Definition MemProf.h:356
static IndexedMemProfRecord deserializeV3(const MemProfSchema &Schema, const unsigned char *Ptr)
Definition MemProf.cpp:150
static void serializeV3(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS, llvm::DenseMap< CallStackId, LinearCallStackId > &MemProfCallStackIndexes)
Definition MemProf.cpp:86
LLVM_ABI MemProfSchema getHotColdSchema()
Definition MemProf.cpp:19
llvm::SmallVector< Meta, static_cast< int >(Meta::Size)> MemProfSchema
Definition MemProf.h:74
static size_t serializedSizeV3(const IndexedAllocationInfo &IAI, const MemProfSchema &Schema)
Definition MemProf.cpp:24
LLVM_ABI MemProfSchema getFullSchema()
Definition MemProf.cpp:11
LLVM_ABI GlobalValue::GUID getGUID(const StringRef FunctionName)
Definition MemProf.cpp:262
static void serializeV4(const IndexedMemProfRecord &Record, const MemProfSchema &Schema, raw_ostream &OS, llvm::DenseMap< CallStackId, LinearCallStackId > &MemProfCallStackIndexes)
Definition MemProf.cpp:109
LLVM_ABI Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
Definition MemProf.cpp:278
uint64_t CallStackId
Definition MemProf.h:353
static size_t serializedSizeV4(const IndexedMemProfRecord &Record, const MemProfSchema &Schema)
Definition MemProf.cpp:60
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
Definition Endian.h:67
This is an optimization pass for GlobalISel generic memory operations.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
#define N
std::vector< Frame > CallStack
Definition MemProf.h:418
PortableMemInfoBlock Info
Definition MemProf.h:420
LLVM_ABI size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition MemProf.cpp:34
llvm::SmallVector< IndexedAllocationInfo > AllocSites
Definition MemProf.h:442
LLVM_ABI size_t serializedSize(const MemProfSchema &Schema, IndexedVersion Version) const
Definition MemProf.cpp:75
LLVM_ABI void serialize(const MemProfSchema &Schema, raw_ostream &OS, IndexedVersion Version, llvm::DenseMap< CallStackId, LinearCallStackId > *MemProfCallStackIndexes=nullptr) const
Definition MemProf.cpp:135
static LLVM_ABI IndexedMemProfRecord deserialize(const MemProfSchema &Schema, const unsigned char *Buffer, IndexedVersion Version)
Definition MemProf.cpp:229
llvm::SmallVector< IndexedCallSiteInfo > CallSites
Definition MemProf.h:448
LLVM_ABI MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const
Definition MemProf.cpp:241
static size_t serializedSize(const MemProfSchema &Schema)
Definition MemProf.h:202
Adapter to write values to a stream in a particular byte order.