LLVM 24.0.0git
SampleProfWriter.cpp
Go to the documentation of this file.
1//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===//
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 implements the class that writes LLVM sample profiles. It
10// supports two file formats: text and binary. The textual representation
11// is useful for debugging and testing purposes. The binary representation
12// is more compact, resulting in smaller file sizes. However, they can
13// both be used interchangeably.
14//
15// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the
16// supported formats.
17//
18//===----------------------------------------------------------------------===//
19
21#include "llvm/ADT/Eytzinger.h"
22#include "llvm/ADT/StringRef.h"
29#include "llvm/Support/LEB128.h"
30#include "llvm/Support/MD5.h"
32#include <array>
33#include <cmath>
34#include <cstdint>
35#include <memory>
36#include <system_error>
37#include <utility>
38#include <vector>
39
40#define DEBUG_TYPE "llvm-profdata"
41
42using namespace llvm;
43using namespace sampleprof;
44
45// To begin with, make this option off by default.
47 "extbinary-write-vtable-type-prof", cl::init(false), cl::Hidden,
48 cl::desc("Write vtable type profile in ext-binary sample profile writer"));
49
51 "sample-profile-format-version", cl::init(DefaultVersion), cl::Hidden,
52 cl::desc("Format version to write for extensible binary profiles"));
53
54static cl::opt<bool>
55 WriteMD5ProfSymList("md5-prof-sym-list", cl::init(false), cl::Hidden,
56 cl::desc("Write ProfileSymbolList (Cold Symbols) as "
57 "64-bit MD5 hashes in Eytzinger layout"));
58
60 "sample-profile-write-eytzinger-name-tables", cl::init(false), cl::Hidden,
61 cl::desc("Write Eytzinger 3-span layout for NameTable and parallel "
62 "FuncOffsetTable"));
63
64namespace llvm {
65namespace support {
66namespace endian {
67namespace {
68
69// Adapter class to llvm::support::endian::Writer for pwrite().
70struct SeekableWriter {
72 endianness Endian;
73 SeekableWriter(raw_pwrite_stream &OS, endianness Endian)
74 : OS(OS), Endian(Endian) {}
75
76 template <typename ValueType> void pwrite(ValueType Val, size_t Offset) {
77 std::string StringBuf;
78 raw_string_ostream SStream(StringBuf);
79 Writer(SStream, Endian).write(Val);
80 OS.pwrite(StringBuf.data(), StringBuf.size(), Offset);
81 }
82};
83
84} // namespace
85} // namespace endian
86} // namespace support
87} // namespace llvm
88
94
95void DefaultFunctionPruningStrategy::Erase(size_t CurrentOutputSize) {
96 double D = (double)OutputSizeLimit / CurrentOutputSize;
97 size_t NewSize = (size_t)round(ProfileMap.size() * D * D);
98 size_t NumToRemove = ProfileMap.size() - NewSize;
99 if (NumToRemove < 1)
100 NumToRemove = 1;
101
102 assert(NumToRemove <= SortedFunctions.size());
103 for (const NameFunctionSamples &E :
104 llvm::drop_begin(SortedFunctions, SortedFunctions.size() - NumToRemove))
105 ProfileMap.erase(E.first);
106 SortedFunctions.resize(SortedFunctions.size() - NumToRemove);
107}
108
110 SampleProfileMap &ProfileMap, size_t OutputSizeLimit,
111 FunctionPruningStrategy *Strategy) {
112 if (OutputSizeLimit == 0)
113 return write(ProfileMap);
114
115 size_t OriginalFunctionCount = ProfileMap.size();
116
117 std::unique_ptr<raw_ostream> OriginalOutputStream;
118 OutputStream.swap(OriginalOutputStream);
119
120 size_t IterationCount = 0;
121 size_t TotalSize;
122
123 SmallVector<char> StringBuffer;
124 do {
125 StringBuffer.clear();
126 OutputStream.reset(new raw_svector_ostream(StringBuffer));
127 if (std::error_code EC = write(ProfileMap))
128 return EC;
129
130 TotalSize = StringBuffer.size();
131 // On Windows every "\n" is actually written as "\r\n" to disk but not to
132 // memory buffer, this difference should be added when considering the total
133 // output size.
134#ifdef _WIN32
135 if (Format == SPF_Text)
136 TotalSize += LineCount;
137#endif
138 if (TotalSize <= OutputSizeLimit)
139 break;
140
141 Strategy->Erase(TotalSize);
142 IterationCount++;
143 } while (ProfileMap.size() != 0);
144
145 if (ProfileMap.size() == 0)
147
148 OutputStream.swap(OriginalOutputStream);
149 OutputStream->write(StringBuffer.data(), StringBuffer.size());
150 LLVM_DEBUG(dbgs() << "Profile originally has " << OriginalFunctionCount
151 << " functions, reduced to " << ProfileMap.size() << " in "
152 << IterationCount << " iterations\n");
153 // Silence warning on Release build.
154 (void)OriginalFunctionCount;
155 (void)IterationCount;
157}
158
159std::error_code
161 std::vector<NameFunctionSamples> V;
162 sortFuncProfiles(ProfileMap, V);
163 for (const auto &I : V) {
164 if (std::error_code EC = writeSample(*I.second))
165 return EC;
166 }
168}
169
170std::error_code SampleProfileWriter::write(const SampleProfileMap &ProfileMap) {
171 if (std::error_code EC = writeHeader(ProfileMap))
172 return EC;
173
174 if (std::error_code EC = writeFuncProfiles(ProfileMap))
175 return EC;
176
178}
179
180/// Return the current position and prepare to use it as the start
181/// position of a section given the section type \p Type and its position
182/// \p LayoutIdx in SectionHdrLayout.
185 uint32_t LayoutIdx) {
186 uint64_t SectionStart = OutputStream->tell();
187 assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
188 const auto &Entry = SectionHdrLayout[LayoutIdx];
189 assert(Entry.Type == Type && "Unexpected section type");
190 // Use LocalBuf as a temporary output for writting data.
192 LocalBufStream.swap(OutputStream);
193 return SectionStart;
194}
195
196std::error_code SampleProfileWriterExtBinaryBase::compressAndOutput() {
199 std::string &UncompressedStrings =
200 static_cast<raw_string_ostream *>(LocalBufStream.get())->str();
201 if (UncompressedStrings.size() == 0)
203 auto &OS = *OutputStream;
204 SmallVector<uint8_t, 128> CompressedStrings;
206 CompressedStrings,
208 encodeULEB128(UncompressedStrings.size(), OS);
209 encodeULEB128(CompressedStrings.size(), OS);
210 OS << toStringRef(CompressedStrings);
211 UncompressedStrings.clear();
213}
214
215/// Add a new section into section header table given the section type
216/// \p Type, its position \p LayoutIdx in SectionHdrLayout and the
217/// location \p SectionStart where the section should be written to.
219 SecType Type, uint32_t LayoutIdx, uint64_t SectionStart) {
220 assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
221 const auto &Entry = SectionHdrLayout[LayoutIdx];
222 assert(Entry.Type == Type && "Unexpected section type");
224 LocalBufStream.swap(OutputStream);
225 if (std::error_code EC = compressAndOutput())
226 return EC;
227 }
228 SecHdrTable.push_back({Type, Entry.Flags, SectionStart - FileStart,
229 OutputStream->tell() - SectionStart, LayoutIdx});
231}
232
233std::error_code
235 // When calling write on a different profile map, existing states should be
236 // cleared.
237 NameTable.clear();
238 CSNameTable.clear();
239 SecHdrTable.clear();
240
241 if (std::error_code EC = writeHeader(ProfileMap))
242 return EC;
243
244 std::string LocalBuf;
245 LocalBufStream = std::make_unique<raw_string_ostream>(LocalBuf);
246 if (std::error_code EC = writeSections(ProfileMap))
247 return EC;
248
249 if (std::error_code EC = writeSecHdrTable())
250 return EC;
251
253}
254
256 const SampleContext &Context) {
257 if (Context.hasContext())
258 return writeCSNameIdx(Context);
259 else
260 return SampleProfileWriterBinary::writeNameIdx(Context.getFunction());
261}
262
263std::error_code
265 const auto &Ret = CSNameTable.find(Context);
266 if (Ret == CSNameTable.end())
268 encodeULEB128(Ret->second, *OutputStream);
270}
271
272std::error_code
274 uint64_t Offset = OutputStream->tell();
275 auto &Context = S.getContext();
276 FuncOffsetTable[Context] = Offset - SecLBRProfileStart;
278 return writeBody(S);
279}
280
281std::error_code
284 // Eytzinger layout requires MD5 representation and does not support
285 // multi-context Context-Sensitive profiles.
286 if (!UseMD5 || FunctionSamples::ProfileIsCS)
288 return writeEytzingerFuncOffsetTable(IsNested);
289 }
291}
292
293std::error_code
295 assert((NumNested + NumFlat > 0 || FuncOffsetTable.empty()) &&
296 "SecNameTable must be written before SecFuncOffsetTable to establish "
297 "Eytzinger indices!");
298
299 size_t SpanSize = IsNested ? NumNested : NumFlat;
300 size_t BaseIdx = IsNested ? 0 : NumNested;
301
302 std::vector<support::ulittle32_t> FuncOffsets(
303 SpanSize, support::ulittle32_t(UINT32_MAX));
304
305 // Populate the function offset array parallel to the Eytzinger span.
306 for (const auto &[Context, RelativeOffset] : FuncOffsetTable) {
307 if (RelativeOffset >= UINT32_MAX)
309
310 FunctionId FId = Context.getFunction();
311 auto It = NameTable.find(FId);
312 if (It == NameTable.end())
313 continue;
314
315 size_t GlobalIdx = It->second;
316 if (GlobalIdx < BaseIdx || (GlobalIdx - BaseIdx) >= SpanSize)
317 continue;
318
319 size_t LocalIdx = GlobalIdx - BaseIdx;
320 assert(
321 FuncOffsets[LocalIdx] == UINT32_MAX &&
322 "Function offset slot already populated; duplicate GUID or collision!");
323 FuncOffsets[LocalIdx] = static_cast<uint32_t>(RelativeOffset);
324 }
325
326 assert(!llvm::is_contained(FuncOffsets, support::ulittle32_t(UINT32_MAX)) &&
327 "Unpopulated slot in Eytzinger function offset array!");
328
329 OutputStream->write(reinterpret_cast<const char *>(FuncOffsets.data()),
330 SpanSize * sizeof(support::ulittle32_t));
332 FuncOffsetTable.clear();
334}
335
337 auto &OS = *OutputStream;
338
339 // Write out the table size.
340 encodeULEB128(FuncOffsetTable.size(), OS);
341
342 // Write out FuncOffsetTable.
343 auto WriteItem = [&](const SampleContext &Context, uint64_t Offset) {
344 if (std::error_code EC = writeContextIdx(Context))
345 return EC;
347 return (std::error_code)sampleprof_error::success;
348 };
349
351 // Sort the contexts before writing them out. This is to help fast load all
352 // context profiles for a function as well as their callee contexts which
353 // can help profile-guided importing for ThinLTO.
354 std::map<SampleContext, uint64_t> OrderedFuncOffsetTable(
355 FuncOffsetTable.begin(), FuncOffsetTable.end());
356 for (const auto &Entry : OrderedFuncOffsetTable) {
357 if (std::error_code EC = WriteItem(Entry.first, Entry.second))
358 return EC;
359 }
361 } else {
362 for (const auto &Entry : FuncOffsetTable) {
363 if (std::error_code EC = WriteItem(Entry.first, Entry.second))
364 return EC;
365 }
366 }
367
368 FuncOffsetTable.clear();
370}
371
373 const FunctionSamples &FunctionProfile) {
374 auto &OS = *OutputStream;
375 if (std::error_code EC = writeContextIdx(FunctionProfile.getContext()))
376 return EC;
377
379 encodeULEB128(FunctionProfile.getFunctionHash(), OS);
381 encodeULEB128(FunctionProfile.getContext().getAllAttributes(), OS);
382 }
383
385 // Recursively emit attributes for all callee samples.
386 uint64_t NumCallsites = 0;
387 for (const auto &J : FunctionProfile.getCallsiteSamples())
388 NumCallsites += J.second.size();
389 encodeULEB128(NumCallsites, OS);
390 for (const auto &J : FunctionProfile.getCallsiteSamples()) {
391 for (const auto &FS : J.second) {
392 LineLocation Loc = J.first;
393 encodeULEB128(Loc.LineOffset, OS);
394 encodeULEB128(Loc.Discriminator, OS);
395 if (std::error_code EC = writeFuncMetadata(FS.second))
396 return EC;
397 }
398 }
399 }
400
402}
403
405 const SampleProfileMap &Profiles) {
409 for (const auto &Entry : Profiles) {
410 if (std::error_code EC = writeFuncMetadata(Entry.second))
411 return EC;
412 }
414}
415
416template <class KeyT, class ValT>
421
422 llvm::sort(Entries,
423 [](const auto *L, const auto *R) { return L->first < R->first; });
424
425 for (const auto &[I, Entry] : llvm::enumerate(Entries))
426 Entry->second = I;
427
428 return Entries;
429}
430
432 if (!UseMD5)
434
435 auto &OS = *OutputStream;
436
437 // Write out the MD5 name table. We wrote unencoded MD5 so reader can
438 // retrieve the name using the name index without having to read the
439 // whole name table.
440 encodeULEB128(NameTable.size(), OS);
442 for (const auto *Entry : stabilizeTable(NameTable))
443 Writer.write(Entry->first.getHashCode());
445}
446
448 const SampleProfileMap &ProfileMap) {
449 for (const auto &I : ProfileMap) {
450 addContext(I.second.getContext());
451 addNames(I.second);
452 }
453
454 // If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag
455 // so compiler won't strip the suffix during profile matching after
456 // seeing the flag in the profile.
457 // Original names are unavailable if using MD5, so this option has no use.
458 if (!UseMD5) {
459 for (const auto &I : NameTable) {
460 if (I.first.stringRef().contains(FunctionSamples::UniqSuffix)) {
462 break;
463 }
464 }
465 }
466
467 if (UseMD5 && WriteEytzingerNameTables) {
468 // Eytzinger name tables do not support CSSPGO profiles
469 // (FunctionSamples::ProfileIsCS).
472 if (auto EC = writeEytzingerNameTableSection(ProfileMap))
473 return EC;
475 }
476
477 if (auto EC = writeNameTable())
478 return EC;
480}
481
482namespace {
483
484// Helper class to construct and write the SecNameTable section in Eytzinger
485// layout for ExtBinary MD5 profiles.
486//
487// The on-disk layout of the Eytzinger name table section consists of symbol
488// counts followed by three contiguous Eytzinger hash arrays:
489// - ULEB128 count of Nested top-level profile symbol keys
490// - ULEB128 count of Flat top-level profile symbol keys
491// - ULEB128 count of Inlinee and auxiliary profile symbol keys
492// - Array of 64-bit little-endian MD5 hash keys for Nested profiles in
493// Eytzinger order
494// - Array of 64-bit little-endian MD5 hash keys for Flat profiles in Eytzinger
495// order
496// - Array of 64-bit little-endian MD5 hash keys for Inlinees in Eytzinger order
497class EytzingerNameTable {
499 std::array<TableT, static_cast<size_t>(EytzingerSpan::NumSpans)> Spans;
500
501public:
502 EytzingerNameTable(std::vector<support::ulittle64_t> NestedKeys,
503 std::vector<support::ulittle64_t> FlatKeys,
504 std::vector<support::ulittle64_t> InlineeKeys)
505 : Spans{TableT::create(std::move(NestedKeys)),
506 TableT::create(std::move(FlatKeys)),
507 TableT::create(std::move(InlineeKeys))} {}
508
509 // Find the global index of GUID across the three Eytzinger table spans.
510 uint64_t findGlobalIdx(uint64_t GUID) const {
511 uint64_t BaseIdx = 0;
512 for (const auto &Table : Spans) {
513 if (std::optional<size_t> LocalIdx = Table.findIndex(GUID))
514 return BaseIdx + *LocalIdx;
515 BaseIdx += Table.size();
516 }
517 llvm_unreachable("Symbol in NameTable missing from Eytzinger spans");
518 }
519
520 void write(raw_ostream &OS) const {
521 for (const auto &Table : Spans)
522 encodeULEB128(uint64_t(Table.size()), OS);
523 for (const auto &Table : Spans)
524 OS.write(reinterpret_cast<const char *>(Table.data()),
525 Table.size() * sizeof(support::ulittle64_t));
526 }
527
528 size_t size(EytzingerSpan S) const {
529 return Spans[static_cast<size_t>(S)].size();
530 }
531};
532
533} // end anonymous namespace
534
535std::error_code
537 const SampleProfileMap &ProfileMap) {
538 DenseSet<uint64_t> TopLevelGUIDs;
539 std::vector<support::ulittle64_t> NestedKeys, FlatKeys, InlineeKeys;
540
541 // Collect top-level Nested and Flat keys directly from ProfileMap.
542 for (const auto &I : ProfileMap) {
543 const SampleContext &Ctx = I.second.getContext();
544 uint64_t GUID = Ctx.getFunction().getHashCode();
545 if (TopLevelGUIDs.insert(GUID).second) {
546 // In single-table default layouts, unify all top-level symbols in the
547 // Nested partition so they match the single unflagged function offset
548 // table.
549 if (SecLayout != CtxSplitLayout || I.second.hasCallsiteSamples())
550 NestedKeys.emplace_back(GUID);
551 else
552 FlatKeys.emplace_back(GUID);
553 }
554 }
555
556 // Collect remaining non-top-level symbols (inlinees, targets, vtables) from
557 // NameTable.
558 for (const auto &Entry : NameTable) {
559 uint64_t GUID = Entry.first.getHashCode();
560 if (!TopLevelGUIDs.contains(GUID))
561 InlineeKeys.emplace_back(GUID);
562 }
563
564 EytzingerNameTable Tables(std::move(NestedKeys), std::move(FlatKeys),
565 std::move(InlineeKeys));
566
567 // Assign each symbol its corresponding index in the Eytzinger layout.
568 for (auto &[FId, Idx] : NameTable)
569 Idx = Tables.findGlobalIdx(FId.getHashCode());
570
571 Tables.write(*OutputStream);
572 NumNested = Tables.size(EytzingerSpan::Nested);
573 NumFlat = Tables.size(EytzingerSpan::Flat);
574
576}
577
579 auto &OS = *OutputStream;
580 encodeULEB128(CSNameTable.size(), OS);
582 for (const auto *Entry : stabilizeTable(CSNameTable)) {
583 auto Frames = Entry->first.getContextFrames();
584 encodeULEB128(Frames.size(), OS);
585 for (auto &Callsite : Frames) {
586 if (std::error_code EC = writeNameIdx(Callsite.Func))
587 return EC;
588 encodeULEB128(Callsite.Location.LineOffset, OS);
589 encodeULEB128(Callsite.Location.Discriminator, OS);
590 }
591 }
592
594}
595
596std::error_code
602
603std::error_code
605 assert((!ProfSymList || !ProfSymList->isMD5()) &&
606 "Writing string-based ProfileSymbolListSection from MD5 table "
607 "not yet implemented");
608 if (ProfSymList && ProfSymList->size() > 0)
609 if (std::error_code EC = ProfSymList->write(*OutputStream))
610 return EC;
611
613}
614
615std::error_code
617 if (!ProfSymList || ProfSymList->size() == 0)
619 assert(!ProfSymList->isMD5() &&
620 "Writing MD5 ProfileSymbolListSection from existing MD5 "
621 "table not yet implemented");
622
623 auto &OS = *OutputStream;
624 std::vector<uint64_t> Keys = ProfSymList->collectGUIDs();
625
626 auto Table =
628
629 OS.write(reinterpret_cast<const char *>(Table.data()),
630 Table.size() * sizeof(support::ulittle64_t));
632}
633
635 SecType Type, uint32_t LayoutIdx, const SampleProfileMap &ProfileMap) {
636 // The setting of SecFlagCompress should happen before markSectionStart.
637 if (Type == SecProfileSymbolList && ProfSymList && ProfSymList->toCompress())
641 if (Type == SecFuncMetadata &&
655 if (Type == SecNameTable && WriteEytzingerNameTables && UseMD5)
657
658 uint64_t SectionStart = markSectionStart(Type, LayoutIdx);
659 switch (Type) {
660 case SecProfSummary:
661 computeSummary(ProfileMap);
662 if (auto EC = writeSummary())
663 return EC;
664 break;
665 case SecNameTable:
666 if (auto EC = writeNameTableSection(ProfileMap))
667 return EC;
668 break;
669 case SecCSNameTable:
670 if (auto EC = writeCSNameTableSection())
671 return EC;
672 break;
673 case SecLBRProfile:
675 if (std::error_code EC = writeFuncProfiles(ProfileMap))
676 return EC;
677 break;
678 case SecFuncOffsetTable: {
679 bool IsFlat =
681 // An unflagged function offset table inherently indexes the primary
682 // Nested symbol span.
683 bool IsNested = !IsFlat;
684 if (auto EC = writeFuncOffsetTable(IsNested))
685 return EC;
686 break;
687 }
688 case SecFuncMetadata:
689 if (std::error_code EC = writeFuncMetadata(ProfileMap))
690 return EC;
691 break;
693 if (auto EC = writeProfileSymbolListSection())
694 return EC;
695 break;
696 default:
697 if (auto EC = writeCustomSection(Type))
698 return EC;
699 break;
700 }
701 if (std::error_code EC = addNewSection(Type, LayoutIdx, SectionStart))
702 return EC;
704}
705
711
712std::error_code SampleProfileWriterExtBinary::writeDefaultLayout(
713 const SampleProfileMap &ProfileMap) {
714 // The const indices passed to writeOneSection below are specifying the
715 // positions of the sections in SectionHdrLayout. Look at
716 // initSectionHdrLayout to find out where each section is located in
717 // SectionHdrLayout.
718 if (auto EC = writeOneSection(SecProfSummary, 0, ProfileMap))
719 return EC;
720 if (auto EC = writeOneSection(SecNameTable, 1, ProfileMap))
721 return EC;
722 if (auto EC = writeOneSection(SecCSNameTable, 2, ProfileMap))
723 return EC;
724 if (auto EC = writeOneSection(SecLBRProfile, 4, ProfileMap))
725 return EC;
726 if (auto EC = writeOneSection(SecProfileSymbolList, 5, ProfileMap))
727 return EC;
728 if (auto EC = writeOneSection(SecFuncOffsetTable, 3, ProfileMap))
729 return EC;
730 if (auto EC = writeOneSection(SecFuncMetadata, 6, ProfileMap))
731 return EC;
733}
734
735static void splitProfileMapToTwo(const SampleProfileMap &ProfileMap,
736 SampleProfileMap &NestedProfileMap,
737 SampleProfileMap &FlatProfileMap) {
738 for (const auto &I : ProfileMap) {
739 if (I.second.hasCallsiteSamples())
740 NestedProfileMap.insert({I.first, I.second});
741 else
742 FlatProfileMap.insert({I.first, I.second});
743 }
744}
745
746std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
747 const SampleProfileMap &ProfileMap) {
748 SampleProfileMap NestedProfileMap, FlatProfileMap;
749 splitProfileMapToTwo(ProfileMap, NestedProfileMap, FlatProfileMap);
750
751 if (auto EC = writeOneSection(SecProfSummary, 0, ProfileMap))
752 return EC;
753 if (auto EC = writeOneSection(SecNameTable, 1, ProfileMap))
754 return EC;
755 if (auto EC = writeOneSection(SecLBRProfile, 3, NestedProfileMap))
756 return EC;
757 if (auto EC = writeOneSection(SecFuncOffsetTable, 2, NestedProfileMap))
758 return EC;
759 // Mark the section as flat (without callsite samples). Note section flag
760 // needs to be set before writing the section.
762 if (auto EC = writeOneSection(SecLBRProfile, 5, FlatProfileMap))
763 return EC;
764 // Mark the section as flat (without callsite samples). Note section flag
765 // needs to be set before writing the section.
767 if (auto EC = writeOneSection(SecFuncOffsetTable, 4, FlatProfileMap))
768 return EC;
769 if (auto EC = writeOneSection(SecProfileSymbolList, 6, ProfileMap))
770 return EC;
771 if (auto EC = writeOneSection(SecFuncMetadata, 7, ProfileMap))
772 return EC;
773
775}
776
777std::error_code SampleProfileWriterExtBinary::writeSections(
778 const SampleProfileMap &ProfileMap) {
779 std::error_code EC;
781 EC = writeDefaultLayout(ProfileMap);
782 else if (SecLayout == CtxSplitLayout)
783 EC = writeCtxSplitLayout(ProfileMap);
784 else
785 llvm_unreachable("Unsupported layout");
786 return EC;
787}
788
789/// Write samples to a text file.
790///
791/// Note: it may be tempting to implement this in terms of
792/// FunctionSamples::print(). Please don't. The dump functionality is intended
793/// for debugging and has no specified form.
794///
795/// The format used here is more structured and deliberate because
796/// it needs to be parsed by the SampleProfileReaderText class.
798 auto &OS = *OutputStream;
800 OS << "[" << S.getContext().toString() << "]:" << S.getTotalSamples();
801 else
802 OS << S.getFunction() << ":" << S.getTotalSamples();
803
804 if (Indent == 0)
805 OS << ":" << S.getHeadSamples();
806 OS << "\n";
807 LineCount++;
808
810 for (const auto &I : SortedSamples.get()) {
811 LineLocation Loc = I->first;
812 const SampleRecord &Sample = I->second;
813 OS.indent(Indent + 1);
814 Loc.print(OS);
815 OS << ": " << Sample.getSamples();
816
817 for (const auto &J : Sample.getSortedCallTargets())
818 OS << " " << J.first << ":" << J.second;
819 OS << "\n";
820 LineCount++;
821
822 if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
823 Map && !Map->empty()) {
824 OS.indent(Indent + 1);
825 Loc.print(OS);
826 OS << ": ";
827 OS << kVTableProfPrefix;
828 for (const auto [TypeName, Count] : *Map) {
829 OS << TypeName << ":" << Count << " ";
830 }
831 OS << "\n";
832 LineCount++;
833 }
834 }
835
838 Indent += 1;
839 for (const auto *Element : SortedCallsiteSamples.get()) {
840 // Element is a pointer to a pair of LineLocation and FunctionSamplesMap.
841 const auto &[Loc, FunctionSamplesMap] = *Element;
842 for (const FunctionSamples &CalleeSamples :
844 OS.indent(Indent);
845 Loc.print(OS);
846 OS << ": ";
847 if (std::error_code EC = writeSample(CalleeSamples))
848 return EC;
849 }
850
851 if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
852 Map && !Map->empty()) {
853 OS.indent(Indent);
854 Loc.print(OS);
855 OS << ": ";
856 OS << kVTableProfPrefix;
857 for (const auto [TypeId, Count] : *Map) {
858 OS << TypeId << ":" << Count << " ";
859 }
860 OS << "\n";
861 LineCount++;
862 }
863 }
864
865 Indent -= 1;
866
868 OS.indent(Indent + 1);
869 OS << "!CFGChecksum: " << S.getFunctionHash() << "\n";
870 LineCount++;
871 }
872
873 if (S.getContext().getAllAttributes()) {
874 OS.indent(Indent + 1);
875 OS << "!Attributes: " << S.getContext().getAllAttributes() << "\n";
876 LineCount++;
877 }
878
879 if (Indent == 0 && MarkFlatProfiles && S.getCallsiteSamples().size() == 0)
880 OS << " !Flat\n";
881
883}
884
885std::error_code
887 assert(!Context.hasContext() && "cs profile is not supported");
888 return writeNameIdx(Context.getFunction());
889}
890
892 auto &NTable = getNameTable();
893 const auto &Ret = NTable.find(FName);
894 if (Ret == NTable.end())
896 encodeULEB128(Ret->second, *OutputStream);
898}
899
901 auto &NTable = getNameTable();
902 NTable.insert(std::make_pair(FName, 0));
903}
904
906 addName(Context.getFunction());
907}
908
910 // Add all the names in indirect call targets.
911 for (const auto &I : S.getBodySamples()) {
912 const SampleRecord &Sample = I.second;
913 for (const auto &J : Sample.getCallTargets())
914 addName(J.first);
915 }
916
917 // Recursively add all the names for inlined callsites.
918 for (const auto &J : S.getCallsiteSamples())
919 for (const auto &FS : J.second) {
920 const FunctionSamples &CalleeSamples = FS.second;
921 addName(CalleeSamples.getFunction());
922 addNames(CalleeSamples);
923 }
924
925 if (!WriteVTableProf)
926 return;
927 // Add all the vtable names to NameTable.
928 for (const auto &VTableAccessCountMap :
930 // Add type name to NameTable.
931 for (const auto Type : llvm::make_first_range(VTableAccessCountMap)) {
932 addName(Type);
933 }
934 }
935}
936
938 const SampleContext &Context) {
939 if (Context.hasContext()) {
940 for (auto &Callsite : Context.getContextFrames())
942 CSNameTable.insert(std::make_pair(Context, 0));
943 } else {
944 SampleProfileWriterBinary::addName(Context.getFunction());
945 }
946}
947
949 auto &OS = *OutputStream;
950
951 // Write out the name table.
952 encodeULEB128(NameTable.size(), OS);
953 for (const auto *Entry : stabilizeTable(NameTable)) {
954 OS << Entry->first;
955 encodeULEB128(0, OS);
956 }
958}
959
960std::error_code
968
969std::error_code
971 // When calling write on a different profile map, existing names should be
972 // cleared.
973 NameTable.clear();
974
976
977 computeSummary(ProfileMap);
978 if (auto EC = writeSummary())
979 return EC;
980
981 // Generate the name table for all the functions referenced in the profile.
982 for (const auto &I : ProfileMap) {
983 addContext(I.second.getContext());
984 addNames(I.second);
985 }
986
989}
990
995
999
1000void SampleProfileWriterExtBinaryBase::allocSecHdrTable() {
1002
1003 Writer.write(static_cast<uint64_t>(SectionHdrLayout.size()));
1004 SecHdrTableOffset = OutputStream->tell();
1005 for (uint32_t i = 0; i < SectionHdrLayout.size(); i++) {
1006 Writer.write(static_cast<uint64_t>(-1));
1007 Writer.write(static_cast<uint64_t>(-1));
1008 Writer.write(static_cast<uint64_t>(-1));
1009 Writer.write(static_cast<uint64_t>(-1));
1010 }
1011}
1012
1013std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
1014 assert(SecHdrTable.size() == SectionHdrLayout.size() &&
1015 "SecHdrTable entries doesn't match SectionHdrLayout");
1016 SmallVector<uint32_t, 16> IndexMap(SecHdrTable.size(), -1);
1017 for (uint32_t TableIdx = 0; TableIdx < SecHdrTable.size(); TableIdx++) {
1018 IndexMap[SecHdrTable[TableIdx].LayoutIndex] = TableIdx;
1019 }
1020
1021 // Write the section header table in the order specified in
1022 // SectionHdrLayout. SectionHdrLayout specifies the sections
1023 // order in which profile reader expect to read, so the section
1024 // header table should be written in the order in SectionHdrLayout.
1025 // Note that the section order in SecHdrTable may be different
1026 // from the order in SectionHdrLayout, for example, SecFuncOffsetTable
1027 // needs to be computed after SecLBRProfile (the order in SecHdrTable),
1028 // but it needs to be read before SecLBRProfile (the order in
1029 // SectionHdrLayout). So we use IndexMap above to switch the order.
1030 support::endian::SeekableWriter Writer(
1031 static_cast<raw_pwrite_stream &>(*OutputStream),
1033 for (uint32_t LayoutIdx = 0; LayoutIdx < SectionHdrLayout.size();
1034 LayoutIdx++) {
1035 assert(IndexMap[LayoutIdx] < SecHdrTable.size() &&
1036 "Incorrect LayoutIdx in SecHdrTable");
1037 auto Entry = SecHdrTable[IndexMap[LayoutIdx]];
1038 Writer.pwrite(static_cast<uint64_t>(Entry.Type),
1039 SecHdrTableOffset + 4 * LayoutIdx * sizeof(uint64_t));
1040 Writer.pwrite(static_cast<uint64_t>(Entry.Flags),
1041 SecHdrTableOffset + (4 * LayoutIdx + 1) * sizeof(uint64_t));
1042 Writer.pwrite(static_cast<uint64_t>(Entry.Offset),
1043 SecHdrTableOffset + (4 * LayoutIdx + 2) * sizeof(uint64_t));
1044 Writer.pwrite(static_cast<uint64_t>(Entry.Size),
1045 SecHdrTableOffset + (4 * LayoutIdx + 3) * sizeof(uint64_t));
1046 }
1047
1049}
1050
1051std::error_code SampleProfileWriterExtBinaryBase::writeHeader(
1052 const SampleProfileMap &ProfileMap) {
1053 auto &OS = *OutputStream;
1054 FileStart = OS.tell();
1056
1057 allocSecHdrTable();
1059}
1060
1064 "writeCallsiteVTableProf should not be called if WriteVTableProf is "
1065 "false");
1066
1067 encodeULEB128(CallsiteTypeMap.size(), OS);
1068 for (const auto &[Loc, TypeMap] : CallsiteTypeMap) {
1069 Loc.serialize(OS);
1070 if (std::error_code EC = serializeTypeMap(TypeMap, getNameTable(), OS))
1071 return EC;
1072 }
1073
1075}
1076
1078 auto &OS = *OutputStream;
1079 encodeULEB128(Summary->getTotalCount(), OS);
1080 encodeULEB128(Summary->getMaxCount(), OS);
1081 encodeULEB128(Summary->getMaxFunctionCount(), OS);
1082 encodeULEB128(Summary->getNumCounts(), OS);
1083 encodeULEB128(Summary->getNumFunctions(), OS);
1084 ArrayRef<ProfileSummaryEntry> Entries = Summary->getDetailedSummary();
1085 encodeULEB128(Entries.size(), OS);
1086 for (auto Entry : Entries) {
1087 encodeULEB128(Entry.Cutoff, OS);
1088 encodeULEB128(Entry.MinCount, OS);
1089 encodeULEB128(Entry.NumCounts, OS);
1090 }
1092}
1094 auto &OS = *OutputStream;
1095 if (std::error_code EC = writeContextIdx(S.getContext()))
1096 return EC;
1097
1099
1100 // Emit all the body samples.
1101 encodeULEB128(S.getBodySamples().size(), OS);
1102 for (const auto &I : S.getBodySamples()) {
1103 LineLocation Loc = I.first;
1104 const SampleRecord &Sample = I.second;
1105 Loc.serialize(OS);
1106 Sample.serialize(OS, getNameTable());
1107 }
1108
1109 // Recursively emit all the callsite samples.
1110 uint64_t NumCallsites = 0;
1111 for (const auto &J : S.getCallsiteSamples())
1112 NumCallsites += J.second.size();
1113 encodeULEB128(NumCallsites, OS);
1114 for (const auto &J : S.getCallsiteSamples())
1115 for (const auto &FS : J.second) {
1116 J.first.serialize(OS);
1117 if (std::error_code EC = writeBody(FS.second))
1118 return EC;
1119 }
1120
1121 if (WriteVTableProf)
1123
1125}
1126
1127/// Write samples of a top-level function to a binary file.
1128///
1129/// \returns true if the samples were written successfully, false otherwise.
1130std::error_code
1135
1136/// Create a sample profile file writer based on the specified format.
1137///
1138/// \param Filename The file to create.
1139///
1140/// \param Format Encoding format for the profile file.
1141///
1142/// \returns an error code indicating the status of the created writer.
1145 std::error_code EC;
1146 std::unique_ptr<raw_ostream> OS;
1148 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_None));
1149 else
1151 if (EC)
1152 return EC;
1153
1154 return create(OS, Format);
1155}
1156
1157/// Create a sample profile stream writer based on the specified format.
1158///
1159/// \param OS The output stream to store the profile data to.
1160///
1161/// \param Format Encoding format for the profile file.
1162///
1163/// \returns an error code indicating the status of the created writer.
1165SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
1167 std::error_code EC;
1168 std::unique_ptr<SampleProfileWriter> Writer;
1169
1170 // Currently only Text and Extended Binary format are supported for CSSPGO.
1172 Format == SPF_Binary)
1174
1175 if (Format == SPF_Binary)
1176 Writer.reset(new SampleProfileWriterRawBinary(OS));
1177 else if (Format == SPF_Ext_Binary)
1178 Writer.reset(new SampleProfileWriterExtBinary(OS));
1179 else if (Format == SPF_Text)
1180 Writer.reset(new SampleProfileWriterText(OS));
1181 else if (Format == SPF_GCC)
1183 else
1185
1186 if (EC)
1187 return EC;
1188
1189 Writer->Format = Format;
1190 if (Format != SPF_Ext_Binary)
1191 Writer->setFormatVersion(DefaultVersion);
1193 Writer->setFormatVersion(RequestedVersion);
1194 else
1196 return std::move(Writer);
1197}
1198
1201 Summary = Builder.computeSummaryForProfiles(ProfileMap);
1202}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Provides ErrorOr<T> smart pointer.
This file defines the EytzingerTableSpan class, a non-owning view of a buffer formatted as a complete...
static uint64_t round(uint64_t Acc, uint64_t Input)
Definition KCFIHash.cpp:29
#define I(x, y, z)
Definition MD5.cpp:57
static constexpr StringLiteral Filename
static cl::opt< bool > WriteEytzingerNameTables("sample-profile-write-eytzinger-name-tables", cl::init(false), cl::Hidden, cl::desc("Write Eytzinger 3-span layout for NameTable and parallel " "FuncOffsetTable"))
static cl::opt< uint64_t > RequestedVersion("sample-profile-format-version", cl::init(DefaultVersion), cl::Hidden, cl::desc("Format version to write for extensible binary profiles"))
static void splitProfileMapToTwo(const SampleProfileMap &ProfileMap, SampleProfileMap &NestedProfileMap, SampleProfileMap &FlatProfileMap)
static SmallVector< std::pair< KeyT, ValT > *, 0 > stabilizeTable(MapVector< KeyT, ValT > &Table)
static cl::opt< bool > ExtBinaryWriteVTableTypeProf("extbinary-write-vtable-type-prof", cl::init(false), cl::Hidden, cl::desc("Write vtable type profile in ext-binary sample profile writer"))
static cl::opt< bool > WriteMD5ProfSymList("md5-prof-sym-list", cl::init(false), cl::Hidden, cl::desc("Write ProfileSymbolList (Cold Symbols) as " "64-bit MD5 hashes in Eytzinger layout"))
#define LLVM_DEBUG(...)
Definition Debug.h:119
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Represents either an error or a value T.
Definition ErrorOr.h:56
Owning container that stores elements in a complete binary search tree formatted in Eytzinger (breadt...
Definition Eytzinger.h:123
static EytzingerTable< T > create(std::vector< KeyT > Keys)
Construct an Eytzinger search tree from a vector of keys by sorting, deduplicating,...
Definition Eytzinger.h:139
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
static LLVM_ABI const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
pointer data()
Return a pointer to the vector's buffer, even if empty().
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
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
An abstract base class for streams implementations that also support a pwrite operation.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
A raw_ostream that writes to an SmallVector or SmallString.
DefaultFunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
void Erase(size_t CurrentOutputSize) override
In this default implementation, functions with fewest samples are dropped first.
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
When writing a profile with size limit, user may want to use a different strategy to reduce function ...
virtual void Erase(size_t CurrentOutputSize)=0
SampleProfileWriter::writeWithSizeLimit() calls this after every write iteration if the output size s...
FunctionPruningStrategy(SampleProfileMap &ProfileMap, size_t OutputSizeLimit)
ProfileMap A reference to the original profile map.
Representation of the samples collected for a function.
Definition SampleProf.h:819
static LLVM_ABI std::atomic< bool > ProfileIsFS
If this profile uses flow sensitive discriminators.
static LLVM_ABI std::atomic< bool > ProfileIsPreInlined
static constexpr const char * UniqSuffix
uint64_t getHeadSamples() const
For top-level functions, return the total number of branch samples that have the function as the bran...
FunctionId getFunction() const
Return the function name.
const CallsiteTypeMap & getCallsiteTypeCounts() const
Returns vtable access samples for the C++ types collected in this function.
const TypeCountMap * findCallsiteTypeSamplesAt(const LineLocation &Loc) const
Returns the TypeCountMap for inlined callsites at the given Loc.
static LLVM_ABI std::atomic< bool > ProfileIsProbeBased
SampleContext & getContext() const
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
const CallsiteSampleMap & getCallsiteSamples() const
Return all the callsite samples collected in the body of the function.
static LLVM_ABI std::atomic< bool > ProfileIsCS
const BodySampleMap & getBodySamples() const
Return all the samples collected in the body of the function.
std::string toString() const
Definition SampleProf.h:707
This class provides operator overloads to the map container using MD5 as the key type,...
virtual void addContext(const SampleContext &Context)
virtual std::error_code writeMagicIdent(SampleProfileFormat Format)
MapVector< FunctionId, uint32_t > NameTable
std::error_code writeCallsiteVTableProf(const CallsiteTypeMap &CallsiteTypeMap, raw_ostream &OS)
Write CallsiteTypeMap to the output stream OS.
virtual std::error_code writeContextIdx(const SampleContext &Context)
std::error_code writeSample(const FunctionSamples &S) override
Write samples of a top-level function to a binary file.
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override
Write a file header for the profile file.
virtual MapVector< FunctionId, uint32_t > & getNameTable()
std::error_code writeBody(const FunctionSamples &S)
std::error_code writeNameIdx(FunctionId FName)
std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap)
SmallVector< SecHdrTableEntry, 8 > SectionHdrLayout
std::error_code writeFuncMetadata(const SampleProfileMap &Profiles)
virtual std::error_code writeCustomSection(SecType Type)=0
virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx, const SampleProfileMap &ProfileMap)
std::error_code writeCSNameIdx(const SampleContext &Context)
virtual std::error_code writeSections(const SampleProfileMap &ProfileMap)=0
void addSectionFlag(SecType Type, SecFlagType Flag)
uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx)
Return the current position and prepare to use it as the start position of a section given the sectio...
std::error_code writeEytzingerFuncOffsetTable(bool IsNested)
void addContext(const SampleContext &Context) override
std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx, uint64_t SectionStart)
Add a new section into section header table given the section type Type, its position LayoutIdx in Se...
std::error_code writeEytzingerNameTableSection(const SampleProfileMap &ProfileMap)
std::error_code write(const SampleProfileMap &ProfileMap) override
Write all the sample profiles in the given map of samples.
std::error_code writeContextIdx(const SampleContext &Context) override
std::error_code writeSample(const FunctionSamples &S) override
Write samples of a top-level function to a binary file.
SampleProfileWriterExtBinary(std::unique_ptr< raw_ostream > &OS)
Sample-based profile writer (text format).
std::error_code writeSample(const FunctionSamples &S) override
Write samples to a text file.
std::unique_ptr< ProfileSummary > Summary
Profile summary.
virtual std::error_code writeSample(const FunctionSamples &S)=0
Write sample profiles in S.
SampleProfileFormat Format
Profile format.
std::error_code writeWithSizeLimitInternal(SampleProfileMap &ProfileMap, size_t OutputSizeLimit, FunctionPruningStrategy *Strategy)
void computeSummary(const SampleProfileMap &ProfileMap)
Compute summary for this profile.
virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap)
std::unique_ptr< raw_ostream > OutputStream
Output stream where to emit the profile to.
uint64_t FormatVersion
Format version to write.
size_t LineCount
For writeWithSizeLimit in text mode, each newline takes 1 additional byte on Windows when actually wr...
static ErrorOr< std::unique_ptr< SampleProfileWriter > > create(StringRef Filename, SampleProfileFormat Format)
Profile writer factory.
virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap)=0
Write a file header for the profile file.
virtual std::error_code write(const SampleProfileMap &ProfileMap)
Write all the sample profiles in the given map of samples.
Representation of a single sample record.
Definition SampleProf.h:393
LLVM_ABI std::error_code serialize(raw_ostream &OS, const MapVector< FunctionId, uint32_t > &NameTable) const
Serialize the sample record to the output stream using ULEB128 encoding.
const CallTargetMap & getCallTargets() const
Definition SampleProf.h:461
SortedCallTargetSet getSortedCallTargets() const
Definition SampleProf.h:462
Sort a LocationT->SampleT map by LocationT.
const SamplesWithLocList & get() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition COFF.h:862
initializer< Ty > init(const Ty &Val)
LLVM_ABI void compress(ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &CompressedBuffer, int Level=DefaultCompression)
LLVM_ABI bool isAvailable()
constexpr int BestSizeCompression
Definition Compression.h:40
LLVM_ABI void sortFuncProfiles(const SampleProfileMap &ProfileMap, std::vector< NameFunctionSamples > &SortedProfiles)
static uint64_t SPMagic(SampleProfileFormat Format=SPF_Binary)
Definition SampleProf.h:113
static bool formatVersionIsSupported(uint64_t Version)
Definition SampleProf.h:131
static void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:290
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:306
std::pair< hash_code, const FunctionSamples * > NameFunctionSamples
@ SecFlagIsPreInlined
SecFlagIsPreInlined means this profile contains ShouldBeInlined contexts thus this is CS preinliner c...
Definition SampleProf.h:236
@ SecFlagHasVTableTypeProf
SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
Definition SampleProf.h:239
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
Definition SampleProf.h:233
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
Definition SampleProf.h:230
std::map< FunctionId, FunctionSamples > FunctionSamplesMap
Definition SampleProf.h:809
static constexpr uint64_t DefaultVersion
Definition SampleProf.h:125
std::map< FunctionId, uint64_t > TypeCountMap
Key represents type of a C++ polymorphic class type by its vtable and value represents its counter.
Definition SampleProf.h:373
constexpr char kVTableProfPrefix[]
Definition SampleProf.h:96
LLVM_ABI std::error_code serializeTypeMap(const TypeCountMap &Map, const MapVector< FunctionId, uint32_t > &NameTable, raw_ostream &OS)
Write Map to the output stream.
std::map< LineLocation, TypeCountMap > CallsiteTypeMap
Definition SampleProf.h:811
detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t
Definition Endian.h:293
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
Definition Endian.h:290
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition FileSystem.h:804
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct an array ref of bytes from a string ref.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
Definition STLExtras.h:1399
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1409
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition LEB128.h:79
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
endianness
Definition bit.h:71
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
Definition DWP.cpp:747
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
Represents the relative location of an instruction.
Definition SampleProf.h:322
Adapter to write values to a stream in a particular byte order.
void write(ArrayRef< value_type > Val)