LLVM 19.0.0git
InstrProfWriter.cpp
Go to the documentation of this file.
1//===- InstrProfWriter.cpp - Instrumented profiling writer ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains support for writing profiling data for clang's
10// instrumentation based PGO and coverage.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SetVector.h"
17#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/Endian.h"
25#include "llvm/Support/Error.h"
30#include <cstdint>
31#include <memory>
32#include <string>
33#include <tuple>
34#include <utility>
35#include <vector>
36
37using namespace llvm;
38
39// A struct to define how the data stream should be patched. For Indexed
40// profiling, only uint64_t data type is needed.
41struct PatchItem {
42 uint64_t Pos; // Where to patch.
43 uint64_t *D; // Pointer to an array of source data.
44 int N; // Number of elements in \c D array.
45};
46
47namespace llvm {
48
49// A wrapper class to abstract writer stream with support of bytes
50// back patching.
52public:
54 : IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {}
56 : IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {}
57
58 uint64_t tell() { return OS.tell(); }
59 void write(uint64_t V) { LE.write<uint64_t>(V); }
60 void writeByte(uint8_t V) { LE.write<uint8_t>(V); }
61
62 // \c patch can only be called when all data is written and flushed.
63 // For raw_string_ostream, the patch is done on the target string
64 // directly and it won't be reflected in the stream's internal buffer.
66 using namespace support;
67
68 if (IsFDOStream) {
69 raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
70 const uint64_t LastPos = FDOStream.tell();
71 for (const auto &K : P) {
72 FDOStream.seek(K.Pos);
73 for (int I = 0; I < K.N; I++)
74 write(K.D[I]);
75 }
76 // Reset the stream to the last position after patching so that users
77 // don't accidentally overwrite data. This makes it consistent with
78 // the string stream below which replaces the data directly.
79 FDOStream.seek(LastPos);
80 } else {
81 raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
82 std::string &Data = SOStream.str(); // with flush
83 for (const auto &K : P) {
84 for (int I = 0; I < K.N; I++) {
85 uint64_t Bytes =
86 endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]);
87 Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t),
88 (const char *)&Bytes, sizeof(uint64_t));
89 }
90 }
91 }
92 }
93
94 // If \c OS is an instance of \c raw_fd_ostream, this field will be
95 // true. Otherwise, \c OS will be an raw_string_ostream.
99};
100
102public:
105
108
111
115
117
120 }
121
122 static std::pair<offset_type, offset_type>
124 using namespace support;
125
127
128 offset_type N = K.size();
129 LE.write<offset_type>(N);
130
131 offset_type M = 0;
132 for (const auto &ProfileData : *V) {
133 const InstrProfRecord &ProfRecord = ProfileData.second;
134 M += sizeof(uint64_t); // The function hash
135 M += sizeof(uint64_t); // The size of the Counts vector
136 M += ProfRecord.Counts.size() * sizeof(uint64_t);
137 M += sizeof(uint64_t); // The size of the Bitmap vector
138 M += ProfRecord.BitmapBytes.size() * sizeof(uint64_t);
139
140 // Value data
141 M += ValueProfData::getSize(ProfileData.second);
142 }
143 LE.write<offset_type>(M);
144
145 return std::make_pair(N, M);
146 }
147
149 Out.write(K.data(), N);
150 }
151
153 using namespace support;
154
156 for (const auto &ProfileData : *V) {
157 const InstrProfRecord &ProfRecord = ProfileData.second;
158 if (NamedInstrProfRecord::hasCSFlagInHash(ProfileData.first))
159 CSSummaryBuilder->addRecord(ProfRecord);
160 else
161 SummaryBuilder->addRecord(ProfRecord);
162
163 LE.write<uint64_t>(ProfileData.first); // Function hash
164 LE.write<uint64_t>(ProfRecord.Counts.size());
165 for (uint64_t I : ProfRecord.Counts)
166 LE.write<uint64_t>(I);
167
168 LE.write<uint64_t>(ProfRecord.BitmapBytes.size());
169 for (uint64_t I : ProfRecord.BitmapBytes)
170 LE.write<uint64_t>(I);
171
172 // Write value data
173 std::unique_ptr<ValueProfData> VDataPtr =
174 ValueProfData::serializeFrom(ProfileData.second);
175 uint32_t S = VDataPtr->getSize();
176 VDataPtr->swapBytesFromHost(ValueProfDataEndianness);
177 Out.write((const char *)VDataPtr.get(), S);
178 }
179 }
180};
181
182} // end namespace llvm
183
185 bool Sparse, uint64_t TemporalProfTraceReservoirSize,
186 uint64_t MaxTemporalProfTraceLength, bool WritePrevVersion,
187 memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema)
188 : Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength),
189 TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize),
190 InfoObj(new InstrProfRecordWriterTrait()),
191 WritePrevVersion(WritePrevVersion),
192 MemProfVersionRequested(MemProfVersionRequested),
193 MemProfFullSchema(MemProfFullSchema) {}
194
196
197// Internal interface for testing purpose only.
199 InfoObj->ValueProfDataEndianness = Endianness;
200}
201
203 this->Sparse = Sparse;
204}
205
207 function_ref<void(Error)> Warn) {
208 auto Name = I.Name;
209 auto Hash = I.Hash;
210 addRecord(Name, Hash, std::move(I), Weight, Warn);
211}
212
214 OverlapStats &Overlap,
215 OverlapStats &FuncLevelOverlap,
216 const OverlapFuncFilters &FuncFilter) {
217 auto Name = Other.Name;
218 auto Hash = Other.Hash;
219 Other.accumulateCounts(FuncLevelOverlap.Test);
220 if (!FunctionData.contains(Name)) {
221 Overlap.addOneUnique(FuncLevelOverlap.Test);
222 return;
223 }
224 if (FuncLevelOverlap.Test.CountSum < 1.0f) {
225 Overlap.Overlap.NumEntries += 1;
226 return;
227 }
228 auto &ProfileDataMap = FunctionData[Name];
229 bool NewFunc;
231 std::tie(Where, NewFunc) =
232 ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
233 if (NewFunc) {
234 Overlap.addOneMismatch(FuncLevelOverlap.Test);
235 return;
236 }
237 InstrProfRecord &Dest = Where->second;
238
239 uint64_t ValueCutoff = FuncFilter.ValueCutoff;
240 if (!FuncFilter.NameFilter.empty() && Name.contains(FuncFilter.NameFilter))
241 ValueCutoff = 0;
242
243 Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
244}
245
247 InstrProfRecord &&I, uint64_t Weight,
248 function_ref<void(Error)> Warn) {
249 auto &ProfileDataMap = FunctionData[Name];
250
251 bool NewFunc;
253 std::tie(Where, NewFunc) =
254 ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
255 InstrProfRecord &Dest = Where->second;
256
257 auto MapWarn = [&](instrprof_error E) {
258 Warn(make_error<InstrProfError>(E));
259 };
260
261 if (NewFunc) {
262 // We've never seen a function with this name and hash, add it.
263 Dest = std::move(I);
264 if (Weight > 1)
265 Dest.scale(Weight, 1, MapWarn);
266 } else {
267 // We're updating a function we've seen before.
268 Dest.merge(I, Weight, MapWarn);
269 }
270
271 Dest.sortValueData();
272}
273
276 auto [Iter, Inserted] = MemProfData.RecordData.insert({Id, Record});
277 // If we inserted a new record then we are done.
278 if (Inserted) {
279 return;
280 }
281 memprof::IndexedMemProfRecord &Existing = Iter->second;
282 Existing.merge(Record);
283}
284
286 const memprof::Frame &Frame,
287 function_ref<void(Error)> Warn) {
288 auto [Iter, Inserted] = MemProfData.FrameData.insert({Id, Frame});
289 // If a mapping already exists for the current frame id and it does not
290 // match the new mapping provided then reset the existing contents and bail
291 // out. We don't support the merging of memprof data whose Frame -> Id
292 // mapping across profiles is inconsistent.
293 if (!Inserted && Iter->second != Frame) {
294 Warn(make_error<InstrProfError>(instrprof_error::malformed,
295 "frame to id mapping mismatch"));
296 return false;
297 }
298 return true;
299}
300
302 const memprof::CallStackId CSId,
304 function_ref<void(Error)> Warn) {
305 auto [Iter, Inserted] = MemProfData.CallStackData.insert({CSId, CallStack});
306 // If a mapping already exists for the current call stack id and it does not
307 // match the new mapping provided then reset the existing contents and bail
308 // out. We don't support the merging of memprof data whose CallStack -> Id
309 // mapping across profiles is inconsistent.
310 if (!Inserted && Iter->second != CallStack) {
311 Warn(make_error<InstrProfError>(instrprof_error::malformed,
312 "call stack to id mapping mismatch"));
313 return false;
314 }
315 return true;
316}
317
319 llvm::append_range(BinaryIds, BIs);
320}
321
322void InstrProfWriter::addTemporalProfileTrace(TemporalProfTraceTy Trace) {
323 assert(Trace.FunctionNameRefs.size() <= MaxTemporalProfTraceLength);
324 assert(!Trace.FunctionNameRefs.empty());
325 if (TemporalProfTraceStreamSize < TemporalProfTraceReservoirSize) {
326 // Simply append the trace if we have not yet hit our reservoir size limit.
327 TemporalProfTraces.push_back(std::move(Trace));
328 } else {
329 // Otherwise, replace a random trace in the stream.
330 std::uniform_int_distribution<uint64_t> Distribution(
331 0, TemporalProfTraceStreamSize);
332 uint64_t RandomIndex = Distribution(RNG);
333 if (RandomIndex < TemporalProfTraces.size())
334 TemporalProfTraces[RandomIndex] = std::move(Trace);
335 }
336 ++TemporalProfTraceStreamSize;
337}
338
340 SmallVectorImpl<TemporalProfTraceTy> &SrcTraces, uint64_t SrcStreamSize) {
341 for (auto &Trace : SrcTraces)
342 if (Trace.FunctionNameRefs.size() > MaxTemporalProfTraceLength)
343 Trace.FunctionNameRefs.resize(MaxTemporalProfTraceLength);
344 llvm::erase_if(SrcTraces, [](auto &T) { return T.FunctionNameRefs.empty(); });
345 // Assume that the source has the same reservoir size as the destination to
346 // avoid needing to record it in the indexed profile format.
347 bool IsDestSampled =
348 (TemporalProfTraceStreamSize > TemporalProfTraceReservoirSize);
349 bool IsSrcSampled = (SrcStreamSize > TemporalProfTraceReservoirSize);
350 if (!IsDestSampled && IsSrcSampled) {
351 // If one of the traces are sampled, ensure that it belongs to Dest.
352 std::swap(TemporalProfTraces, SrcTraces);
353 std::swap(TemporalProfTraceStreamSize, SrcStreamSize);
354 std::swap(IsDestSampled, IsSrcSampled);
355 }
356 if (!IsSrcSampled) {
357 // If the source stream is not sampled, we add each source trace normally.
358 for (auto &Trace : SrcTraces)
359 addTemporalProfileTrace(std::move(Trace));
360 return;
361 }
362 // Otherwise, we find the traces that would have been removed if we added
363 // the whole source stream.
364 SmallSetVector<uint64_t, 8> IndicesToReplace;
365 for (uint64_t I = 0; I < SrcStreamSize; I++) {
366 std::uniform_int_distribution<uint64_t> Distribution(
367 0, TemporalProfTraceStreamSize);
368 uint64_t RandomIndex = Distribution(RNG);
369 if (RandomIndex < TemporalProfTraces.size())
370 IndicesToReplace.insert(RandomIndex);
371 ++TemporalProfTraceStreamSize;
372 }
373 // Then we insert a random sample of the source traces.
374 llvm::shuffle(SrcTraces.begin(), SrcTraces.end(), RNG);
375 for (const auto &[Index, Trace] : llvm::zip(IndicesToReplace, SrcTraces))
376 TemporalProfTraces[Index] = std::move(Trace);
377}
378
380 function_ref<void(Error)> Warn) {
381 for (auto &I : IPW.FunctionData)
382 for (auto &Func : I.getValue())
383 addRecord(I.getKey(), Func.first, std::move(Func.second), 1, Warn);
384
385 BinaryIds.reserve(BinaryIds.size() + IPW.BinaryIds.size());
386 for (auto &I : IPW.BinaryIds)
388
389 addTemporalProfileTraces(IPW.TemporalProfTraces,
390 IPW.TemporalProfTraceStreamSize);
391
392 MemProfData.FrameData.reserve(IPW.MemProfData.FrameData.size());
393 for (auto &[FrameId, Frame] : IPW.MemProfData.FrameData) {
394 // If we weren't able to add the frame mappings then it doesn't make sense
395 // to try to merge the records from this profile.
396 if (!addMemProfFrame(FrameId, Frame, Warn))
397 return;
398 }
399
400 MemProfData.CallStackData.reserve(IPW.MemProfData.CallStackData.size());
401 for (auto &[CSId, CallStack] : IPW.MemProfData.CallStackData) {
402 if (!addMemProfCallStack(CSId, CallStack, Warn))
403 return;
404 }
405
406 MemProfData.RecordData.reserve(IPW.MemProfData.RecordData.size());
407 for (auto &[GUID, Record] : IPW.MemProfData.RecordData) {
409 }
410}
411
412bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
413 if (!Sparse)
414 return true;
415 for (const auto &Func : PD) {
416 const InstrProfRecord &IPR = Func.second;
417 if (llvm::any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; }))
418 return true;
419 if (llvm::any_of(IPR.BitmapBytes, [](uint8_t Byte) { return Byte > 0; }))
420 return true;
421 }
422 return false;
423}
424
425static void setSummary(IndexedInstrProf::Summary *TheSummary,
426 ProfileSummary &PS) {
427 using namespace IndexedInstrProf;
428
429 const std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary();
430 TheSummary->NumSummaryFields = Summary::NumKinds;
431 TheSummary->NumCutoffEntries = Res.size();
432 TheSummary->set(Summary::MaxFunctionCount, PS.getMaxFunctionCount());
433 TheSummary->set(Summary::MaxBlockCount, PS.getMaxCount());
434 TheSummary->set(Summary::MaxInternalBlockCount, PS.getMaxInternalCount());
435 TheSummary->set(Summary::TotalBlockCount, PS.getTotalCount());
436 TheSummary->set(Summary::TotalNumBlocks, PS.getNumCounts());
437 TheSummary->set(Summary::TotalNumFunctions, PS.getNumFunctions());
438 for (unsigned I = 0; I < Res.size(); I++)
439 TheSummary->setEntry(I, Res[I]);
440}
441
442// Serialize Schema.
444 const memprof::MemProfSchema &Schema) {
445 OS.write(static_cast<uint64_t>(Schema.size()));
446 for (const auto Id : Schema)
447 OS.write(static_cast<uint64_t>(Id));
448}
449
450// Serialize MemProfRecordData. Return RecordTableOffset.
454 &MemProfRecordData,
456 memprof::RecordWriterTrait RecordWriter(Schema, Version);
458 RecordTableGenerator;
459 for (auto &[GUID, Record] : MemProfRecordData) {
460 // Insert the key (func hash) and value (memprof record).
461 RecordTableGenerator.insert(GUID, Record, RecordWriter);
462 }
463 // Release the memory of this MapVector as it is no longer needed.
464 MemProfRecordData.clear();
465
466 // The call to Emit invokes RecordWriterTrait::EmitData which destructs
467 // the memprof record copies owned by the RecordTableGenerator. This works
468 // because the RecordTableGenerator is not used after this point.
469 return RecordTableGenerator.Emit(OS.OS, RecordWriter);
470}
471
472// Serialize MemProfFrameData. Return FrameTableOffset.
477 FrameTableGenerator;
478 for (auto &[FrameId, Frame] : MemProfFrameData) {
479 // Insert the key (frame id) and value (frame contents).
480 FrameTableGenerator.insert(FrameId, Frame);
481 }
482 // Release the memory of this MapVector as it is no longer needed.
483 MemProfFrameData.clear();
484
485 return FrameTableGenerator.Emit(OS.OS);
486}
487
491 &MemProfCallStackData) {
493 CallStackTableGenerator;
494 for (auto &[CSId, CallStack] : MemProfCallStackData)
495 CallStackTableGenerator.insert(CSId, CallStack);
496 // Release the memory of this vector as it is no longer needed.
497 MemProfCallStackData.clear();
498
499 return CallStackTableGenerator.Emit(OS.OS);
500}
501
502// Write out MemProf Version0 as follows:
503// uint64_t RecordTableOffset = RecordTableGenerator.Emit
504// uint64_t FramePayloadOffset = Offset for the frame payload
505// uint64_t FrameTableOffset = FrameTableGenerator.Emit
506// uint64_t Num schema entries
507// uint64_t Schema entry 0
508// uint64_t Schema entry 1
509// ....
510// uint64_t Schema entry N - 1
511// OnDiskChainedHashTable MemProfRecordData
512// OnDiskChainedHashTable MemProfFrameData
514 memprof::IndexedMemProfData &MemProfData) {
515 uint64_t HeaderUpdatePos = OS.tell();
516 OS.write(0ULL); // Reserve space for the memprof record table offset.
517 OS.write(0ULL); // Reserve space for the memprof frame payload offset.
518 OS.write(0ULL); // Reserve space for the memprof frame table offset.
519
520 auto Schema = memprof::getFullSchema();
521 writeMemProfSchema(OS, Schema);
522
523 uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData,
524 &Schema, memprof::Version0);
525
526 uint64_t FramePayloadOffset = OS.tell();
527 uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData);
528
529 uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
530 OS.patch({{HeaderUpdatePos, Header, std::size(Header)}});
531
532 return Error::success();
533}
534
535// Write out MemProf Version1 as follows:
536// uint64_t Version (NEW in V1)
537// uint64_t RecordTableOffset = RecordTableGenerator.Emit
538// uint64_t FramePayloadOffset = Offset for the frame payload
539// uint64_t FrameTableOffset = FrameTableGenerator.Emit
540// uint64_t Num schema entries
541// uint64_t Schema entry 0
542// uint64_t Schema entry 1
543// ....
544// uint64_t Schema entry N - 1
545// OnDiskChainedHashTable MemProfRecordData
546// OnDiskChainedHashTable MemProfFrameData
548 memprof::IndexedMemProfData &MemProfData) {
550 uint64_t HeaderUpdatePos = OS.tell();
551 OS.write(0ULL); // Reserve space for the memprof record table offset.
552 OS.write(0ULL); // Reserve space for the memprof frame payload offset.
553 OS.write(0ULL); // Reserve space for the memprof frame table offset.
554
555 auto Schema = memprof::getFullSchema();
556 writeMemProfSchema(OS, Schema);
557
558 uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData,
559 &Schema, memprof::Version1);
560
561 uint64_t FramePayloadOffset = OS.tell();
562 uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData);
563
564 uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
565 OS.patch({{HeaderUpdatePos, Header, std::size(Header)}});
566
567 return Error::success();
568}
569
570// Write out MemProf Version2 as follows:
571// uint64_t Version
572// uint64_t RecordTableOffset = RecordTableGenerator.Emit
573// uint64_t FramePayloadOffset = Offset for the frame payload
574// uint64_t FrameTableOffset = FrameTableGenerator.Emit
575// uint64_t CallStackPayloadOffset = Offset for the call stack payload (NEW V2)
576// uint64_t CallStackTableOffset = CallStackTableGenerator.Emit (NEW in V2)
577// uint64_t Num schema entries
578// uint64_t Schema entry 0
579// uint64_t Schema entry 1
580// ....
581// uint64_t Schema entry N - 1
582// OnDiskChainedHashTable MemProfRecordData
583// OnDiskChainedHashTable MemProfFrameData
584// OnDiskChainedHashTable MemProfCallStackData (NEW in V2)
586 memprof::IndexedMemProfData &MemProfData,
587 bool MemProfFullSchema) {
589 uint64_t HeaderUpdatePos = OS.tell();
590 OS.write(0ULL); // Reserve space for the memprof record table offset.
591 OS.write(0ULL); // Reserve space for the memprof frame payload offset.
592 OS.write(0ULL); // Reserve space for the memprof frame table offset.
593 OS.write(0ULL); // Reserve space for the memprof call stack payload offset.
594 OS.write(0ULL); // Reserve space for the memprof call stack table offset.
595
596 auto Schema = memprof::getHotColdSchema();
597 if (MemProfFullSchema)
598 Schema = memprof::getFullSchema();
599 writeMemProfSchema(OS, Schema);
600
601 uint64_t RecordTableOffset = writeMemProfRecords(OS, MemProfData.RecordData,
602 &Schema, memprof::Version2);
603
604 uint64_t FramePayloadOffset = OS.tell();
605 uint64_t FrameTableOffset = writeMemProfFrames(OS, MemProfData.FrameData);
606
607 uint64_t CallStackPayloadOffset = OS.tell();
608 uint64_t CallStackTableOffset =
610
611 uint64_t Header[] = {
612 RecordTableOffset, FramePayloadOffset, FrameTableOffset,
613 CallStackPayloadOffset, CallStackTableOffset,
614 };
615 OS.patch({{HeaderUpdatePos, Header, std::size(Header)}});
616
617 return Error::success();
618}
619
620// Write out the MemProf data in a requested version.
622 memprof::IndexedMemProfData &MemProfData,
623 memprof::IndexedVersion MemProfVersionRequested,
624 bool MemProfFullSchema) {
625 switch (MemProfVersionRequested) {
627 return writeMemProfV0(OS, MemProfData);
629 return writeMemProfV1(OS, MemProfData);
631 return writeMemProfV2(OS, MemProfData, MemProfFullSchema);
632 }
633
634 return make_error<InstrProfError>(
636 formatv("MemProf version {} not supported; "
637 "requires version between {} and {}, inclusive",
638 MemProfVersionRequested, memprof::MinimumSupportedVersion,
640}
641
642Error InstrProfWriter::writeImpl(ProfOStream &OS) {
643 using namespace IndexedInstrProf;
644 using namespace support;
645
647
649 InfoObj->SummaryBuilder = &ISB;
651 InfoObj->CSSummaryBuilder = &CSISB;
652
653 // Populate the hash table generator.
655 for (const auto &I : FunctionData)
656 if (shouldEncodeData(I.getValue()))
657 OrderedData.emplace_back((I.getKey()), &I.getValue());
658 llvm::sort(OrderedData, less_first());
659 for (const auto &I : OrderedData)
660 Generator.insert(I.first, I.second);
661
662 // Write the header.
664 Header.Magic = IndexedInstrProf::Magic;
665 Header.Version = WritePrevVersion
668 // The WritePrevVersion handling will either need to be removed or updated
669 // if the version is advanced beyond 12.
672 if (static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation))
673 Header.Version |= VARIANT_MASK_IR_PROF;
674 if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive))
675 Header.Version |= VARIANT_MASK_CSIR_PROF;
676 if (static_cast<bool>(ProfileKind &
678 Header.Version |= VARIANT_MASK_INSTR_ENTRY;
679 if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage))
680 Header.Version |= VARIANT_MASK_BYTE_COVERAGE;
681 if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly))
682 Header.Version |= VARIANT_MASK_FUNCTION_ENTRY_ONLY;
683 if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf))
684 Header.Version |= VARIANT_MASK_MEMPROF;
685 if (static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile))
686 Header.Version |= VARIANT_MASK_TEMPORAL_PROF;
687
688 Header.Unused = 0;
689 Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
690 Header.HashOffset = 0;
691 Header.MemProfOffset = 0;
692 Header.BinaryIdOffset = 0;
693 Header.TemporalProfTracesOffset = 0;
694 Header.VTableNamesOffset = 0;
695
696 // Only write out the first four fields. We need to remember the offset of the
697 // remaining fields to allow back patching later.
698 for (int I = 0; I < 4; I++)
699 OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);
700
701 // Save the location of Header.HashOffset field in \c OS.
702 uint64_t HashTableStartFieldOffset = OS.tell();
703 // Reserve the space for HashOffset field.
704 OS.write(0);
705
706 // Save the location of MemProf profile data. This is stored in two parts as
707 // the schema and as a separate on-disk chained hashtable.
708 uint64_t MemProfSectionOffset = OS.tell();
709 // Reserve space for the MemProf table field to be patched later if this
710 // profile contains memory profile information.
711 OS.write(0);
712
713 // Save the location of binary ids section.
714 uint64_t BinaryIdSectionOffset = OS.tell();
715 // Reserve space for the BinaryIdOffset field to be patched later if this
716 // profile contains binary ids.
717 OS.write(0);
718
719 uint64_t TemporalProfTracesOffset = OS.tell();
720 OS.write(0);
721
722 uint64_t VTableNamesOffset = OS.tell();
723 if (!WritePrevVersion)
724 OS.write(0);
725
726 // Reserve space to write profile summary data.
728 uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
729 // Remember the summary offset.
730 uint64_t SummaryOffset = OS.tell();
731 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
732 OS.write(0);
733 uint64_t CSSummaryOffset = 0;
734 uint64_t CSSummarySize = 0;
735 if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive)) {
736 CSSummaryOffset = OS.tell();
737 CSSummarySize = SummarySize / sizeof(uint64_t);
738 for (unsigned I = 0; I < CSSummarySize; I++)
739 OS.write(0);
740 }
741
742 // Write the hash table.
743 uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);
744
745 // Write the MemProf profile data if we have it.
746 uint64_t MemProfSectionStart = 0;
747 if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf)) {
748 MemProfSectionStart = OS.tell();
749 if (auto E = writeMemProf(OS, MemProfData, MemProfVersionRequested,
750 MemProfFullSchema))
751 return E;
752 }
753
754 // BinaryIdSection has two parts:
755 // 1. uint64_t BinaryIdsSectionSize
756 // 2. list of binary ids that consist of:
757 // a. uint64_t BinaryIdLength
758 // b. uint8_t BinaryIdData
759 // c. uint8_t Padding (if necessary)
760 uint64_t BinaryIdSectionStart = OS.tell();
761 // Calculate size of binary section.
762 uint64_t BinaryIdsSectionSize = 0;
763
764 // Remove duplicate binary ids.
765 llvm::sort(BinaryIds);
766 BinaryIds.erase(std::unique(BinaryIds.begin(), BinaryIds.end()),
767 BinaryIds.end());
768
769 for (auto BI : BinaryIds) {
770 // Increment by binary id length data type size.
771 BinaryIdsSectionSize += sizeof(uint64_t);
772 // Increment by binary id data length, aligned to 8 bytes.
773 BinaryIdsSectionSize += alignToPowerOf2(BI.size(), sizeof(uint64_t));
774 }
775 // Write binary ids section size.
776 OS.write(BinaryIdsSectionSize);
777
778 for (auto BI : BinaryIds) {
779 uint64_t BILen = BI.size();
780 // Write binary id length.
781 OS.write(BILen);
782 // Write binary id data.
783 for (unsigned K = 0; K < BILen; K++)
784 OS.writeByte(BI[K]);
785 // Write padding if necessary.
786 uint64_t PaddingSize = alignToPowerOf2(BILen, sizeof(uint64_t)) - BILen;
787 for (unsigned K = 0; K < PaddingSize; K++)
788 OS.writeByte(0);
789 }
790
791 uint64_t VTableNamesSectionStart = OS.tell();
792
793 if (!WritePrevVersion) {
794 std::vector<std::string> VTableNameStrs;
795 for (StringRef VTableName : VTableNames.keys())
796 VTableNameStrs.push_back(VTableName.str());
797
798 std::string CompressedVTableNames;
799 if (!VTableNameStrs.empty())
801 VTableNameStrs, compression::zlib::isAvailable(),
802 CompressedVTableNames))
803 return E;
804
805 const uint64_t CompressedStringLen = CompressedVTableNames.length();
806
807 // Record the length of compressed string.
808 OS.write(CompressedStringLen);
809
810 // Write the chars in compressed strings.
811 for (auto &c : CompressedVTableNames)
812 OS.writeByte(static_cast<uint8_t>(c));
813
814 // Pad up to a multiple of 8.
815 // InstrProfReader could read bytes according to 'CompressedStringLen'.
816 const uint64_t PaddedLength = alignTo(CompressedStringLen, 8);
817
818 for (uint64_t K = CompressedStringLen; K < PaddedLength; K++)
819 OS.writeByte(0);
820 }
821
822 uint64_t TemporalProfTracesSectionStart = 0;
823 if (static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile)) {
824 TemporalProfTracesSectionStart = OS.tell();
825 OS.write(TemporalProfTraces.size());
826 OS.write(TemporalProfTraceStreamSize);
827 for (auto &Trace : TemporalProfTraces) {
828 OS.write(Trace.Weight);
829 OS.write(Trace.FunctionNameRefs.size());
830 for (auto &NameRef : Trace.FunctionNameRefs)
831 OS.write(NameRef);
832 }
833 }
834
835 // Allocate space for data to be serialized out.
836 std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
838 // Compute the Summary and copy the data to the data
839 // structure to be serialized out (to disk or buffer).
840 std::unique_ptr<ProfileSummary> PS = ISB.getSummary();
841 setSummary(TheSummary.get(), *PS);
842 InfoObj->SummaryBuilder = nullptr;
843
844 // For Context Sensitive summary.
845 std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr;
846 if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive)) {
847 TheCSSummary = IndexedInstrProf::allocSummary(SummarySize);
848 std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary();
849 setSummary(TheCSSummary.get(), *CSPS);
850 }
851 InfoObj->CSSummaryBuilder = nullptr;
852
853 if (!WritePrevVersion) {
854 // Now do the final patch:
855 PatchItem PatchItems[] = {
856 // Patch the Header.HashOffset field.
857 {HashTableStartFieldOffset, &HashTableStart, 1},
858 // Patch the Header.MemProfOffset (=0 for profiles without MemProf
859 // data).
860 {MemProfSectionOffset, &MemProfSectionStart, 1},
861 // Patch the Header.BinaryIdSectionOffset.
862 {BinaryIdSectionOffset, &BinaryIdSectionStart, 1},
863 // Patch the Header.TemporalProfTracesOffset (=0 for profiles without
864 // traces).
865 {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1},
866 {VTableNamesOffset, &VTableNamesSectionStart, 1},
867 // Patch the summary data.
868 {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
869 (int)(SummarySize / sizeof(uint64_t))},
870 {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()),
871 (int)CSSummarySize}};
872
873 OS.patch(PatchItems);
874 } else {
875 // Now do the final patch:
876 PatchItem PatchItems[] = {
877 // Patch the Header.HashOffset field.
878 {HashTableStartFieldOffset, &HashTableStart, 1},
879 // Patch the Header.MemProfOffset (=0 for profiles without MemProf
880 // data).
881 {MemProfSectionOffset, &MemProfSectionStart, 1},
882 // Patch the Header.BinaryIdSectionOffset.
883 {BinaryIdSectionOffset, &BinaryIdSectionStart, 1},
884 // Patch the Header.TemporalProfTracesOffset (=0 for profiles without
885 // traces).
886 {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1},
887 // Patch the summary data.
888 {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
889 (int)(SummarySize / sizeof(uint64_t))},
890 {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()),
891 (int)CSSummarySize}};
892
893 OS.patch(PatchItems);
894 }
895
896 for (const auto &I : FunctionData)
897 for (const auto &F : I.getValue())
898 if (Error E = validateRecord(F.second))
899 return E;
900
901 return Error::success();
902}
903
905 // Write the hash table.
906 ProfOStream POS(OS);
907 return writeImpl(POS);
908}
909
911 ProfOStream POS(OS);
912 return writeImpl(POS);
913}
914
915std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
916 std::string Data;
918 // Write the hash table.
919 if (Error E = write(OS))
920 return nullptr;
921 // Return this in an aligned memory buffer.
923}
924
925static const char *ValueProfKindStr[] = {
926#define VALUE_PROF_KIND(Enumerator, Value, Descr) #Enumerator,
928};
929
931 for (uint32_t VK = 0; VK <= IPVK_Last; VK++) {
932 uint32_t NS = Func.getNumValueSites(VK);
933 if (!NS)
934 continue;
935 for (uint32_t S = 0; S < NS; S++) {
936 uint32_t ND = Func.getNumValueDataForSite(VK, S);
937 std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
938 DenseSet<uint64_t> SeenValues;
939 for (uint32_t I = 0; I < ND; I++)
940 if ((VK != IPVK_IndirectCallTarget && VK != IPVK_VTableTarget) &&
941 !SeenValues.insert(VD[I].Value).second)
942 return make_error<InstrProfError>(instrprof_error::invalid_prof);
943 }
944 }
945
946 return Error::success();
947}
948
950 const InstrProfRecord &Func,
951 InstrProfSymtab &Symtab,
953 OS << Name << "\n";
954 OS << "# Func Hash:\n" << Hash << "\n";
955 OS << "# Num Counters:\n" << Func.Counts.size() << "\n";
956 OS << "# Counter Values:\n";
957 for (uint64_t Count : Func.Counts)
958 OS << Count << "\n";
959
960 if (Func.BitmapBytes.size() > 0) {
961 OS << "# Num Bitmap Bytes:\n$" << Func.BitmapBytes.size() << "\n";
962 OS << "# Bitmap Byte Values:\n";
963 for (uint8_t Byte : Func.BitmapBytes) {
964 OS << "0x";
965 OS.write_hex(Byte);
966 OS << "\n";
967 }
968 OS << "\n";
969 }
970
971 uint32_t NumValueKinds = Func.getNumValueKinds();
972 if (!NumValueKinds) {
973 OS << "\n";
974 return;
975 }
976
977 OS << "# Num Value Kinds:\n" << Func.getNumValueKinds() << "\n";
978 for (uint32_t VK = 0; VK < IPVK_Last + 1; VK++) {
979 uint32_t NS = Func.getNumValueSites(VK);
980 if (!NS)
981 continue;
982 OS << "# ValueKind = " << ValueProfKindStr[VK] << ":\n" << VK << "\n";
983 OS << "# NumValueSites:\n" << NS << "\n";
984 for (uint32_t S = 0; S < NS; S++) {
985 uint32_t ND = Func.getNumValueDataForSite(VK, S);
986 OS << ND << "\n";
987 std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
988 for (uint32_t I = 0; I < ND; I++) {
989 if (VK == IPVK_IndirectCallTarget || VK == IPVK_VTableTarget)
990 OS << Symtab.getFuncOrVarNameIfDefined(VD[I].Value) << ":"
991 << VD[I].Count << "\n";
992 else
993 OS << VD[I].Value << ":" << VD[I].Count << "\n";
994 }
995 }
996 }
997
998 OS << "\n";
999}
1000
1002 // Check CS first since it implies an IR level profile.
1003 if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive))
1004 OS << "# CSIR level Instrumentation Flag\n:csir\n";
1005 else if (static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation))
1006 OS << "# IR level Instrumentation Flag\n:ir\n";
1007
1008 if (static_cast<bool>(ProfileKind &
1010 OS << "# Always instrument the function entry block\n:entry_first\n";
1011 if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage))
1012 OS << "# Instrument block coverage\n:single_byte_coverage\n";
1013 InstrProfSymtab Symtab;
1014
1016 using RecordType = std::pair<StringRef, FuncPair>;
1017 SmallVector<RecordType, 4> OrderedFuncData;
1018
1019 for (const auto &I : FunctionData) {
1020 if (shouldEncodeData(I.getValue())) {
1021 if (Error E = Symtab.addFuncName(I.getKey()))
1022 return E;
1023 for (const auto &Func : I.getValue())
1024 OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
1025 }
1026 }
1027
1028 for (const auto &VTableName : VTableNames)
1029 if (Error E = Symtab.addVTableName(VTableName.getKey()))
1030 return E;
1031
1032 if (static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile))
1034
1035 llvm::sort(OrderedFuncData, [](const RecordType &A, const RecordType &B) {
1036 return std::tie(A.first, A.second.first) <
1037 std::tie(B.first, B.second.first);
1038 });
1039
1040 for (const auto &record : OrderedFuncData) {
1041 const StringRef &Name = record.first;
1042 const FuncPair &Func = record.second;
1043 writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
1044 }
1045
1046 for (const auto &record : OrderedFuncData) {
1047 const FuncPair &Func = record.second;
1048 if (Error E = validateRecord(Func.second))
1049 return E;
1050 }
1051
1052 return Error::success();
1053}
1054
1056 InstrProfSymtab &Symtab) {
1057 OS << ":temporal_prof_traces\n";
1058 OS << "# Num Temporal Profile Traces:\n" << TemporalProfTraces.size() << "\n";
1059 OS << "# Temporal Profile Trace Stream Size:\n"
1060 << TemporalProfTraceStreamSize << "\n";
1061 for (auto &Trace : TemporalProfTraces) {
1062 OS << "# Weight:\n" << Trace.Weight << "\n";
1063 for (auto &NameRef : Trace.FunctionNameRefs)
1064 OS << Symtab.getFuncOrVarName(NameRef) << ",";
1065 OS << "\n";
1066 }
1067 OS << "\n";
1068}
basic Basic Alias true
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
std::string Name
static Error writeMemProfV0(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData)
static uint64_t writeMemProfRecords(ProfOStream &OS, llvm::MapVector< GlobalValue::GUID, memprof::IndexedMemProfRecord > &MemProfRecordData, memprof::MemProfSchema *Schema, memprof::IndexedVersion Version)
static Error writeMemProf(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData, memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema)
static uint64_t writeMemProfCallStacks(ProfOStream &OS, llvm::MapVector< memprof::CallStackId, llvm::SmallVector< memprof::FrameId > > &MemProfCallStackData)
static Error writeMemProfV1(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData)
static uint64_t writeMemProfFrames(ProfOStream &OS, llvm::MapVector< memprof::FrameId, memprof::Frame > &MemProfFrameData)
static Error writeMemProfV2(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData, bool MemProfFullSchema)
static void setSummary(IndexedInstrProf::Summary *TheSummary, ProfileSummary &PS)
static const char * ValueProfKindStr[]
static void writeMemProfSchema(ProfOStream &OS, const memprof::MemProfSchema &Schema)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Defines facilities for reading and writing on-disk hash tables.
#define P(N)
if(VerifyEach)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file implements a set that has insertion order iteration characteristics.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition: DenseMap.h:71
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
static std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
const InstrProfWriter::ProfilingData *const data_type_ref
InstrProfSummaryBuilder * SummaryBuilder
static hash_value_type ComputeHash(key_type_ref K)
InstrProfSummaryBuilder * CSSummaryBuilder
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N)
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
const InstrProfWriter::ProfilingData *const data_type
void addRecord(const InstrProfRecord &)
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Definition: InstrProf.h:452
StringRef getFuncOrVarName(uint64_t ValMD5Hash)
Return name of functions or global variables from the name's md5 hash value.
Definition: InstrProf.h:710
Error addVTableName(StringRef VTableName)
Adds VTableName as a known symbol, and inserts it to a map that tracks all vtable names.
Definition: InstrProf.h:594
Error addFuncName(StringRef FuncName)
The method name is kept since there are many callers.
Definition: InstrProf.h:590
StringRef getFuncOrVarNameIfDefined(uint64_t ValMD5Hash)
Just like getFuncOrVarName, except that it will return literal string 'External Symbol' if the functi...
Definition: InstrProf.h:703
Error write(raw_fd_ostream &OS)
Write the profile to OS.
void addTemporalProfileTraces(SmallVectorImpl< TemporalProfTraceTy > &SrcTraces, uint64_t SrcStreamSize)
Add SrcTraces using reservoir sampling where SrcStreamSize is the total number of temporal profiling ...
void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, const OverlapFuncFilters &FuncFilter)
Error writeText(raw_fd_ostream &OS)
Write the profile in text format to OS.
void addBinaryIds(ArrayRef< llvm::object::BuildID > BIs)
void addMemProfRecord(const GlobalValue::GUID Id, const memprof::IndexedMemProfRecord &Record)
Add a memprof record for a function identified by its Id.
static void writeRecordInText(StringRef Name, uint64_t Hash, const InstrProfRecord &Counters, InstrProfSymtab &Symtab, raw_fd_ostream &OS)
Write Record in text format to OS.
void setValueProfDataEndianness(llvm::endianness Endianness)
bool addMemProfCallStack(const memprof::CallStackId CSId, const llvm::SmallVector< memprof::FrameId > &CallStack, function_ref< void(Error)> Warn)
Add a call stack identified by the hash of the contents of the call stack in CallStack.
void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, function_ref< void(Error)> Warn)
Add function counts for the given function.
InstrProfWriter(bool Sparse=false, uint64_t TemporalProfTraceReservoirSize=0, uint64_t MaxTemporalProfTraceLength=0, bool WritePrevVersion=false, memprof::IndexedVersion MemProfVersionRequested=memprof::Version0, bool MemProfFullSchema=false)
void mergeRecordsFromWriter(InstrProfWriter &&IPW, function_ref< void(Error)> Warn)
Merge existing function counts from the given writer.
void writeTextTemporalProfTraceData(raw_fd_ostream &OS, InstrProfSymtab &Symtab)
Write temporal profile trace data to the header in text format to OS.
std::unique_ptr< MemoryBuffer > writeBuffer()
Write the profile, returning the raw data. For testing.
bool addMemProfFrame(const memprof::FrameId, const memprof::Frame &F, function_ref< void(Error)> Warn)
Add a memprof frame identified by the hash of the contents of the frame in FrameId.
void setOutputSparse(bool Sparse)
Error validateRecord(const InstrProfRecord &Func)
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
void clear()
Definition: MapVector.h:88
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Generates an on disk hash table.
offset_type Emit(raw_ostream &Out)
Emit the table to Out, which must not be at offset 0.
void writeByte(uint8_t V)
void patch(ArrayRef< PatchItem > P)
ProfOStream(raw_string_ostream &STR)
support::endian::Writer LE
ProfOStream(raw_fd_ostream &FD)
void write(uint64_t V)
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Definition: ProfileCommon.h:70
uint64_t getTotalCount() const
uint64_t getMaxCount() const
const SummaryEntryVector & getDetailedSummary()
uint32_t getNumCounts() const
uint64_t getMaxInternalCount() const
uint64_t getMaxFunctionCount() const
uint32_t getNumFunctions() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
iterator_range< StringMapKeyIterator< ValueTy > > keys() const
Definition: StringMap.h:228
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool empty() const
Definition: Trace.h:96
unsigned size() const
Definition: Trace.h:95
LLVM Value Representation.
Definition: Value.h:74
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:470
uint64_t seek(uint64_t off)
Flushes the stream and repositions the underlying file descriptor position to the offset specified fr...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:150
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:678
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
Definition: InstrProf.h:1299
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:1181
const uint64_t Magic
Definition: InstrProf.h:1138
const HashT HashType
Definition: InstrProf.h:1179
constexpr uint64_t MaximumSupportedVersion
Definition: MemProf.h:34
MemProfSchema getHotColdSchema()
Definition: MemProf.cpp:21
constexpr uint64_t MinimumSupportedVersion
Definition: MemProf.h:33
MemProfSchema getFullSchema()
Definition: MemProf.cpp:13
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition: STLExtras.h:853
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
Definition: MathExtras.h:393
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2073
void shuffle(Iterator first, Iterator last, RNG &&g)
Definition: STLExtras.h:1541
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1729
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1647
@ Other
Any other memory.
instrprof_error
Definition: InstrProf.h:347
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
Error collectGlobalObjectNameStrings(ArrayRef< std::string > NameStrs, bool doCompression, std::string &Result)
Given a vector of strings (names of global objects like functions or, virtual tables) NameStrs,...
Definition: InstrProf.cpp:658
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:2051
endianness
Definition: bit.h:70
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
#define N
uint64_t Pos
uint64_t * D
Helper object to track which of three possible relocation mechanisms are used for a particular value ...
void set(SummaryFieldKind K, uint64_t V)
Definition: InstrProf.h:1285
void setEntry(uint32_t I, const ProfileSummaryEntry &E)
Definition: InstrProf.h:1291
Profiling information for a single function.
Definition: InstrProf.h:832
std::vector< uint64_t > Counts
Definition: InstrProf.h:833
void merge(InstrProfRecord &Other, uint64_t Weight, function_ref< void(instrprof_error)> Warn)
Merge the counts in Other into this one.
Definition: InstrProf.cpp:896
void overlap(InstrProfRecord &Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff)
Compute the overlap b/w this IntrprofRecord and Other.
Definition: InstrProf.cpp:792
void sortValueData()
Sort value profile data (per site) by count.
Definition: InstrProf.h:907
std::vector< uint8_t > BitmapBytes
Definition: InstrProf.h:834
void scale(uint64_t N, uint64_t D, function_ref< void(instrprof_error)> Warn)
Scale up profile counts (including value profile data) by a factor of (N / D).
Definition: InstrProf.cpp:959
static bool hasCSFlagInHash(uint64_t FuncHash)
Definition: InstrProf.h:1040
const std::string NameFilter
Definition: InstrProf.h:797
void addOneMismatch(const CountSumOrPercent &MismatchFunc)
Definition: InstrProf.cpp:1524
CountSumOrPercent Overlap
Definition: InstrProf.h:759
void addOneUnique(const CountSumOrPercent &UniqueFunc)
Definition: InstrProf.cpp:1534
CountSumOrPercent Test
Definition: InstrProf.h:757
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.
Definition: InstrProf.h:378
Function object to check whether the first component of a container supported by std::get (like std::...
Definition: STLExtras.h:1450
llvm::MapVector< GlobalValue::GUID, IndexedMemProfRecord > RecordData
Definition: MemProf.h:839
llvm::MapVector< CallStackId, llvm::SmallVector< FrameId > > CallStackData
Definition: MemProf.h:847
llvm::MapVector< FrameId, Frame > FrameData
Definition: MemProf.h:844
void merge(const IndexedMemProfRecord &Other)
Definition: MemProf.h:397
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:67
void write(ArrayRef< value_type > Val)
Definition: EndianStream.h:71