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
54namespace llvm {
55namespace support {
56namespace endian {
57namespace {
58
59// Adapter class to llvm::support::endian::Writer for pwrite().
60struct SeekableWriter {
62 endianness Endian;
63 SeekableWriter(raw_pwrite_stream &OS, endianness Endian)
64 : OS(OS), Endian(Endian) {}
65
66 template <typename ValueType> void pwrite(ValueType Val, size_t Offset) {
67 std::string StringBuf;
68 raw_string_ostream SStream(StringBuf);
69 Writer(SStream, Endian).write(Val);
70 OS.pwrite(StringBuf.data(), StringBuf.size(), Offset);
71 }
72};
73
74} // namespace
75} // namespace endian
76} // namespace support
77} // namespace llvm
78
84
85void DefaultFunctionPruningStrategy::Erase(size_t CurrentOutputSize) {
86 double D = (double)OutputSizeLimit / CurrentOutputSize;
87 size_t NewSize = (size_t)round(ProfileMap.size() * D * D);
88 size_t NumToRemove = ProfileMap.size() - NewSize;
89 if (NumToRemove < 1)
90 NumToRemove = 1;
91
92 assert(NumToRemove <= SortedFunctions.size());
93 for (const NameFunctionSamples &E :
94 llvm::drop_begin(SortedFunctions, SortedFunctions.size() - NumToRemove))
95 ProfileMap.erase(E.first);
96 SortedFunctions.resize(SortedFunctions.size() - NumToRemove);
97}
98
100 SampleProfileMap &ProfileMap, size_t OutputSizeLimit,
101 FunctionPruningStrategy *Strategy) {
102 if (OutputSizeLimit == 0)
103 return write(ProfileMap);
104
105 size_t OriginalFunctionCount = ProfileMap.size();
106
107 std::unique_ptr<raw_ostream> OriginalOutputStream;
108 OutputStream.swap(OriginalOutputStream);
109
110 size_t IterationCount = 0;
111 size_t TotalSize;
112
113 SmallVector<char> StringBuffer;
114 do {
115 StringBuffer.clear();
116 OutputStream.reset(new raw_svector_ostream(StringBuffer));
117 if (std::error_code EC = write(ProfileMap))
118 return EC;
119
120 TotalSize = StringBuffer.size();
121 // On Windows every "\n" is actually written as "\r\n" to disk but not to
122 // memory buffer, this difference should be added when considering the total
123 // output size.
124#ifdef _WIN32
125 if (Format == SPF_Text)
126 TotalSize += LineCount;
127#endif
128 if (TotalSize <= OutputSizeLimit)
129 break;
130
131 Strategy->Erase(TotalSize);
132 IterationCount++;
133 } while (ProfileMap.size() != 0);
134
135 if (ProfileMap.size() == 0)
137
138 OutputStream.swap(OriginalOutputStream);
139 OutputStream->write(StringBuffer.data(), StringBuffer.size());
140 LLVM_DEBUG(dbgs() << "Profile originally has " << OriginalFunctionCount
141 << " functions, reduced to " << ProfileMap.size() << " in "
142 << IterationCount << " iterations\n");
143 // Silence warning on Release build.
144 (void)OriginalFunctionCount;
145 (void)IterationCount;
147}
148
149std::error_code
151 std::vector<NameFunctionSamples> V;
152 sortFuncProfiles(ProfileMap, V);
153 for (const auto &I : V) {
154 if (std::error_code EC = writeSample(*I.second))
155 return EC;
156 }
158}
159
160std::error_code SampleProfileWriter::write(const SampleProfileMap &ProfileMap) {
161 if (std::error_code EC = writeHeader(ProfileMap))
162 return EC;
163
164 if (std::error_code EC = writeFuncProfiles(ProfileMap))
165 return EC;
166
168}
169
170/// Return the current position and prepare to use it as the start
171/// position of a section given the section type \p Type and its position
172/// \p LayoutIdx in SectionHdrLayout.
173uint64_t
175 uint32_t LayoutIdx) {
176 uint64_t SectionStart = OutputStream->tell();
177 assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
178 const auto &Entry = SectionHdrLayout[LayoutIdx];
179 assert(Entry.Type == Type && "Unexpected section type");
180 // Use LocalBuf as a temporary output for writting data.
182 LocalBufStream.swap(OutputStream);
183 return SectionStart;
184}
185
186std::error_code SampleProfileWriterExtBinaryBase::compressAndOutput() {
189 std::string &UncompressedStrings =
190 static_cast<raw_string_ostream *>(LocalBufStream.get())->str();
191 if (UncompressedStrings.size() == 0)
193 auto &OS = *OutputStream;
194 SmallVector<uint8_t, 128> CompressedStrings;
196 CompressedStrings,
198 encodeULEB128(UncompressedStrings.size(), OS);
199 encodeULEB128(CompressedStrings.size(), OS);
200 OS << toStringRef(CompressedStrings);
201 UncompressedStrings.clear();
203}
204
205/// Add a new section into section header table given the section type
206/// \p Type, its position \p LayoutIdx in SectionHdrLayout and the
207/// location \p SectionStart where the section should be written to.
209 SecType Type, uint32_t LayoutIdx, uint64_t SectionStart) {
210 assert(LayoutIdx < SectionHdrLayout.size() && "LayoutIdx out of range");
211 const auto &Entry = SectionHdrLayout[LayoutIdx];
212 assert(Entry.Type == Type && "Unexpected section type");
214 LocalBufStream.swap(OutputStream);
215 if (std::error_code EC = compressAndOutput())
216 return EC;
217 }
218 SecHdrTable.push_back({Type, Entry.Flags, SectionStart - FileStart,
219 OutputStream->tell() - SectionStart, LayoutIdx});
221}
222
223std::error_code
225 // When calling write on a different profile map, existing states should be
226 // cleared.
227 NameTable.clear();
228 CSNameTable.clear();
229 SecHdrTable.clear();
230
231 if (std::error_code EC = writeHeader(ProfileMap))
232 return EC;
233
234 std::string LocalBuf;
235 LocalBufStream = std::make_unique<raw_string_ostream>(LocalBuf);
236 if (std::error_code EC = writeSections(ProfileMap))
237 return EC;
238
239 if (std::error_code EC = writeSecHdrTable())
240 return EC;
241
243}
244
246 const SampleContext &Context) {
247 if (Context.hasContext())
248 return writeCSNameIdx(Context);
249 else
250 return SampleProfileWriterBinary::writeNameIdx(Context.getFunction());
251}
252
253std::error_code
255 const auto &Ret = CSNameTable.find(Context);
256 if (Ret == CSNameTable.end())
258 encodeULEB128(Ret->second, *OutputStream);
260}
261
262std::error_code
264 uint64_t Offset = OutputStream->tell();
265 auto &Context = S.getContext();
266 FuncOffsetTable[Context] = Offset - SecLBRProfileStart;
268 return writeBody(S);
269}
270
271std::error_code
273 if (UseMD5IndexedTables) {
274 // Eytzinger layout requires MD5 representation and does not support
275 // multi-context Context-Sensitive profiles.
276 if (!UseMD5 || FunctionSamples::ProfileIsCS)
278 return writeEytzingerFuncOffsetTable(IsNested);
279 }
281}
282
283std::error_code
285 assert((NumNested + NumFlat > 0 || FuncOffsetTable.empty()) &&
286 "SecNameTable must be written before SecFuncOffsetTable to establish "
287 "Eytzinger indices!");
288
289 size_t SpanSize = IsNested ? NumNested : NumFlat;
290 size_t BaseIdx = IsNested ? 0 : NumNested;
291
292 std::vector<support::ulittle32_t> FuncOffsets(
293 SpanSize, support::ulittle32_t(UINT32_MAX));
294
295 // Populate the function offset array parallel to the Eytzinger span.
296 for (const auto &[Context, RelativeOffset] : FuncOffsetTable) {
297 if (RelativeOffset >= UINT32_MAX)
299
300 FunctionId FId = Context.getFunction();
301 auto It = NameTable.find(FId);
302 if (It == NameTable.end())
303 continue;
304
305 size_t GlobalIdx = It->second;
306 if (GlobalIdx < BaseIdx || (GlobalIdx - BaseIdx) >= SpanSize)
307 continue;
308
309 size_t LocalIdx = GlobalIdx - BaseIdx;
310 assert(
311 FuncOffsets[LocalIdx] == UINT32_MAX &&
312 "Function offset slot already populated; duplicate GUID or collision!");
313 FuncOffsets[LocalIdx] = static_cast<uint32_t>(RelativeOffset);
314 }
315
316 assert(!llvm::is_contained(FuncOffsets, support::ulittle32_t(UINT32_MAX)) &&
317 "Unpopulated slot in Eytzinger function offset array!");
318
319 OutputStream->write(reinterpret_cast<const char *>(FuncOffsets.data()),
320 SpanSize * sizeof(support::ulittle32_t));
322 FuncOffsetTable.clear();
324}
325
327 auto &OS = *OutputStream;
328
329 // Write out the table size.
330 encodeULEB128(FuncOffsetTable.size(), OS);
331
332 // Write out FuncOffsetTable.
333 auto WriteItem = [&](const SampleContext &Context, uint64_t Offset) {
334 if (std::error_code EC = writeContextIdx(Context))
335 return EC;
337 return (std::error_code)sampleprof_error::success;
338 };
339
341 // Sort the contexts before writing them out. This is to help fast load all
342 // context profiles for a function as well as their callee contexts which
343 // can help profile-guided importing for ThinLTO.
344 std::map<SampleContext, uint64_t> OrderedFuncOffsetTable(
345 FuncOffsetTable.begin(), FuncOffsetTable.end());
346 for (const auto &Entry : OrderedFuncOffsetTable) {
347 if (std::error_code EC = WriteItem(Entry.first, Entry.second))
348 return EC;
349 }
351 } else {
352 for (const auto &Entry : FuncOffsetTable) {
353 if (std::error_code EC = WriteItem(Entry.first, Entry.second))
354 return EC;
355 }
356 }
357
358 FuncOffsetTable.clear();
360}
361
363 const FunctionSamples &FunctionProfile) {
364 auto &OS = *OutputStream;
365 if (std::error_code EC = writeContextIdx(FunctionProfile.getContext()))
366 return EC;
367
369 encodeULEB128(FunctionProfile.getFunctionHash(), OS);
371 encodeULEB128(FunctionProfile.getContext().getAllAttributes(), OS);
372 }
373
375 // Recursively emit attributes for all callee samples.
376 uint64_t NumCallsites = 0;
377 for (const auto &J : FunctionProfile.getCallsiteSamples())
378 NumCallsites += J.second.size();
379 encodeULEB128(NumCallsites, OS);
380 for (const auto &J : FunctionProfile.getCallsiteSamples()) {
381 for (const auto &FS : J.second) {
382 LineLocation Loc = J.first;
383 encodeULEB128(Loc.LineOffset, OS);
384 encodeULEB128(Loc.Discriminator, OS);
385 if (std::error_code EC = writeFuncMetadata(FS.second))
386 return EC;
387 }
388 }
389 }
390
392}
393
395 const SampleProfileMap &Profiles) {
399 for (const auto &Entry : Profiles) {
400 if (std::error_code EC = writeFuncMetadata(Entry.second))
401 return EC;
402 }
404}
405
406template <class KeyT, class ValT>
411
412 llvm::sort(Entries,
413 [](const auto *L, const auto *R) { return L->first < R->first; });
414
415 for (const auto &[I, Entry] : llvm::enumerate(Entries))
416 Entry->second = I;
417
418 return Entries;
419}
420
422 if (!UseMD5)
424
425 auto &OS = *OutputStream;
426
427 // Write out the MD5 name table. We wrote unencoded MD5 so reader can
428 // retrieve the name using the name index without having to read the
429 // whole name table.
430 encodeULEB128(NameTable.size(), OS);
432 for (const auto *Entry : stabilizeTable(NameTable))
433 Writer.write(Entry->first.getHashCode());
435}
436
438 const SampleProfileMap &ProfileMap) {
439 for (const auto &I : ProfileMap) {
440 addContext(I.second.getContext());
441 addNames(I.second);
442 }
443
444 // If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag
445 // so compiler won't strip the suffix during profile matching after
446 // seeing the flag in the profile.
447 // Original names are unavailable if using MD5, so this option has no use.
448 if (!UseMD5) {
449 for (const auto &I : NameTable) {
450 if (I.first.stringRef().contains(FunctionSamples::UniqSuffix)) {
452 break;
453 }
454 }
455 }
456
457 if (UseMD5 && UseMD5IndexedTables) {
458 // Eytzinger name tables do not support CSSPGO profiles
459 // (FunctionSamples::ProfileIsCS).
462 if (auto EC = writeEytzingerNameTableSection(ProfileMap))
463 return EC;
465 }
466
467 if (auto EC = writeNameTable())
468 return EC;
470}
471
472namespace {
473
474// Helper class to construct and write the SecNameTable section in Eytzinger
475// layout for ExtBinary MD5 profiles.
476//
477// The on-disk layout of the Eytzinger name table section consists of symbol
478// counts followed by three contiguous Eytzinger hash arrays:
479// - ULEB128 count of Nested top-level profile symbol keys
480// - ULEB128 count of Flat top-level profile symbol keys
481// - ULEB128 count of Inlinee and auxiliary profile symbol keys
482// - Array of 64-bit little-endian MD5 hash keys for Nested profiles in
483// Eytzinger order
484// - Array of 64-bit little-endian MD5 hash keys for Flat profiles in Eytzinger
485// order
486// - Array of 64-bit little-endian MD5 hash keys for Inlinees in Eytzinger order
487class EytzingerNameTable {
489 std::array<TableT, static_cast<size_t>(EytzingerSpan::NumSpans)> Spans;
490
491public:
492 EytzingerNameTable(std::vector<support::ulittle64_t> NestedKeys,
493 std::vector<support::ulittle64_t> FlatKeys,
494 std::vector<support::ulittle64_t> InlineeKeys)
495 : Spans{TableT::create(std::move(NestedKeys)),
496 TableT::create(std::move(FlatKeys)),
497 TableT::create(std::move(InlineeKeys))} {}
498
499 // Find the global index of GUID across the three Eytzinger table spans.
500 uint64_t findGlobalIdx(uint64_t GUID) const {
501 uint64_t BaseIdx = 0;
502 for (const auto &Table : Spans) {
503 if (std::optional<size_t> LocalIdx = Table.findIndex(GUID))
504 return BaseIdx + *LocalIdx;
505 BaseIdx += Table.size();
506 }
507 llvm_unreachable("Symbol in NameTable missing from Eytzinger spans");
508 }
509
510 void write(raw_ostream &OS) const {
511 for (const auto &Table : Spans)
512 encodeULEB128(uint64_t(Table.size()), OS);
513 for (const auto &Table : Spans)
514 OS.write(reinterpret_cast<const char *>(Table.data()),
515 Table.size() * sizeof(support::ulittle64_t));
516 }
517
518 size_t size(EytzingerSpan S) const {
519 return Spans[static_cast<size_t>(S)].size();
520 }
521};
522
523} // end anonymous namespace
524
525std::error_code
527 const SampleProfileMap &ProfileMap) {
528 DenseSet<uint64_t> TopLevelGUIDs;
529 std::vector<support::ulittle64_t> NestedKeys, FlatKeys, InlineeKeys;
530
531 // Collect top-level Nested and Flat keys directly from ProfileMap.
532 for (const auto &I : ProfileMap) {
533 const SampleContext &Ctx = I.second.getContext();
534 uint64_t GUID = Ctx.getFunction().getHashCode();
535 if (TopLevelGUIDs.insert(GUID).second) {
536 // In single-table default layouts, unify all top-level symbols in the
537 // Nested partition so they match the single unflagged function offset
538 // table.
539 if (SecLayout != CtxSplitLayout || I.second.hasCallsiteSamples())
540 NestedKeys.emplace_back(GUID);
541 else
542 FlatKeys.emplace_back(GUID);
543 }
544 }
545
546 // Collect remaining non-top-level symbols (inlinees, targets, vtables) from
547 // NameTable.
548 for (const auto &Entry : NameTable) {
549 uint64_t GUID = Entry.first.getHashCode();
550 if (!TopLevelGUIDs.contains(GUID))
551 InlineeKeys.emplace_back(GUID);
552 }
553
554 EytzingerNameTable Tables(std::move(NestedKeys), std::move(FlatKeys),
555 std::move(InlineeKeys));
556
557 // Assign each symbol its corresponding index in the Eytzinger layout.
558 for (auto &[FId, Idx] : NameTable)
559 Idx = Tables.findGlobalIdx(FId.getHashCode());
560
561 Tables.write(*OutputStream);
562 NumNested = Tables.size(EytzingerSpan::Nested);
563 NumFlat = Tables.size(EytzingerSpan::Flat);
564
566}
567
569 auto &OS = *OutputStream;
570 encodeULEB128(CSNameTable.size(), OS);
572 for (const auto *Entry : stabilizeTable(CSNameTable)) {
573 auto Frames = Entry->first.getContextFrames();
574 encodeULEB128(Frames.size(), OS);
575 for (auto &Callsite : Frames) {
576 if (std::error_code EC = writeNameIdx(Callsite.Func))
577 return EC;
578 encodeULEB128(Callsite.Location.LineOffset, OS);
579 encodeULEB128(Callsite.Location.Discriminator, OS);
580 }
581 }
582
584}
585
586std::error_code
592
593std::error_code
595 assert((!ProfSymList || !ProfSymList->isMD5()) &&
596 "Writing string-based ProfileSymbolListSection from MD5 table "
597 "not yet implemented");
598 if (ProfSymList && ProfSymList->size() > 0)
599 if (std::error_code EC = ProfSymList->write(*OutputStream))
600 return EC;
601
603}
604
605std::error_code
607 if (!ProfSymList || ProfSymList->size() == 0)
609 assert(!ProfSymList->isMD5() &&
610 "Writing MD5 ProfileSymbolListSection from existing MD5 "
611 "table not yet implemented");
612
613 auto &OS = *OutputStream;
614 std::vector<uint64_t> Keys = ProfSymList->collectGUIDs();
615
616 auto Table =
618
619 OS.write(reinterpret_cast<const char *>(Table.data()),
620 Table.size() * sizeof(support::ulittle64_t));
622}
623
625 auto WrittenIndices =
627 for (auto [I, Entry] : llvm::enumerate(SectionHdrLayout))
628 if (Entry.Type == Type && !llvm::is_contained(WrittenIndices, I))
629 return I;
630 llvm_unreachable("Matching section not found in SectionHdrLayout");
631}
632
634 SecType Type, const SampleProfileMap &ProfileMap) {
635 unsigned LayoutIdx = findUnwrittenEntry(Type);
636 SecHdrTableEntry &Entry = SectionHdrLayout[LayoutIdx];
637
638 // The setting of SecFlagCompress should happen before markSectionStart.
641 if (Type == SecFuncMetadata &&
653 if (Type == SecProfileSymbolList && UseMD5ProfSymList)
655 if (Type == SecNameTable && UseMD5IndexedTables && 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 = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
680 // An unflagged function offset table inherently indexes the primary
681 // Nested symbol span.
682 bool IsNested = !IsFlat;
683 if (auto EC = writeFuncOffsetTable(IsNested))
684 return EC;
685 break;
686 }
687 case SecFuncMetadata:
688 if (std::error_code EC = writeFuncMetadata(ProfileMap))
689 return EC;
690 break;
692 if (auto EC = writeProfileSymbolListSection())
693 return EC;
694 break;
695 default:
696 if (auto EC = writeCustomSection(Type))
697 return EC;
698 break;
699 }
700 if (std::error_code EC = addNewSection(Type, LayoutIdx, SectionStart))
701 return EC;
703}
704
710
711std::error_code SampleProfileWriterExtBinary::writeDefaultLayout(
712 const SampleProfileMap &ProfileMap) {
713 static constexpr SecType Sections[] = {
716 };
717 for (SecType Type : Sections)
718 if (std::error_code EC = writeOneSection(Type, ProfileMap))
719 return EC;
721}
722
723static void splitProfileMapToTwo(const SampleProfileMap &ProfileMap,
724 SampleProfileMap &NestedProfileMap,
725 SampleProfileMap &FlatProfileMap) {
726 for (const auto &I : ProfileMap) {
727 if (I.second.hasCallsiteSamples())
728 NestedProfileMap.insert({I.first, I.second});
729 else
730 FlatProfileMap.insert({I.first, I.second});
731 }
732}
733
734std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
735 const SampleProfileMap &ProfileMap) {
736 SampleProfileMap NestedProfileMap, FlatProfileMap;
737 splitProfileMapToTwo(ProfileMap, NestedProfileMap, FlatProfileMap);
738
739 const std::pair<SecType, const SampleProfileMap &> Sections[] = {
740 {SecProfSummary, ProfileMap},
741 {SecNameTable, ProfileMap},
742 {SecLBRProfile, NestedProfileMap},
743 {SecFuncOffsetTable, NestedProfileMap},
744 {SecLBRProfile, FlatProfileMap},
745 {SecFuncOffsetTable, FlatProfileMap},
746 {SecProfileSymbolList, ProfileMap},
747 {SecFuncMetadata, ProfileMap},
748 };
749 for (const auto &[Type, Map] : Sections)
750 if (std::error_code EC = writeOneSection(Type, Map))
751 return EC;
752
754}
755
756std::error_code SampleProfileWriterExtBinary::writeSections(
757 const SampleProfileMap &ProfileMap) {
758 std::error_code EC;
760 EC = writeDefaultLayout(ProfileMap);
761 else if (SecLayout == CtxSplitLayout)
762 EC = writeCtxSplitLayout(ProfileMap);
763 else
764 llvm_unreachable("Unsupported layout");
765 return EC;
766}
767
768/// Write samples to a text file.
769///
770/// Note: it may be tempting to implement this in terms of
771/// FunctionSamples::print(). Please don't. The dump functionality is intended
772/// for debugging and has no specified form.
773///
774/// The format used here is more structured and deliberate because
775/// it needs to be parsed by the SampleProfileReaderText class.
777 auto &OS = *OutputStream;
779 OS << "[" << S.getContext().toString() << "]:" << S.getTotalSamples();
780 else
781 OS << S.getFunction() << ":" << S.getTotalSamples();
782
783 if (Indent == 0)
784 OS << ":" << S.getHeadSamples();
785 OS << "\n";
786 LineCount++;
787
788 for (const auto &[Loc, Sample] : S.getBodySamples()) {
789 OS.indent(Indent + 1);
790 Loc.print(OS);
791 OS << ": " << Sample.getSamples();
792
793 for (const auto &J : Sample.getSortedCallTargets())
794 OS << " " << J.first << ":" << J.second;
795 OS << "\n";
796 LineCount++;
797
798 if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
799 Map && !Map->empty()) {
800 OS.indent(Indent + 1);
801 Loc.print(OS);
802 OS << ": ";
803 OS << kVTableProfPrefix;
804 for (const auto [TypeName, Count] : *Map) {
805 OS << TypeName << ":" << Count << " ";
806 }
807 OS << "\n";
808 LineCount++;
809 }
810 }
811
812 Indent += 1;
813 for (const auto &[Loc, FunctionSamplesMap] : S.getCallsiteSamples()) {
814 for (const FunctionSamples &CalleeSamples :
816 OS.indent(Indent);
817 Loc.print(OS);
818 OS << ": ";
819 if (std::error_code EC = writeSample(CalleeSamples))
820 return EC;
821 }
822
823 if (const TypeCountMap *Map = S.findCallsiteTypeSamplesAt(Loc);
824 Map && !Map->empty()) {
825 OS.indent(Indent);
826 Loc.print(OS);
827 OS << ": ";
828 OS << kVTableProfPrefix;
829 for (const auto [TypeId, Count] : *Map) {
830 OS << TypeId << ":" << Count << " ";
831 }
832 OS << "\n";
833 LineCount++;
834 }
835 }
836
837 Indent -= 1;
838
840 OS.indent(Indent + 1);
841 OS << "!CFGChecksum: " << S.getFunctionHash() << "\n";
842 LineCount++;
843 }
844
845 if (S.getContext().getAllAttributes()) {
846 OS.indent(Indent + 1);
847 OS << "!Attributes: " << S.getContext().getAllAttributes() << "\n";
848 LineCount++;
849 }
850
851 if (Indent == 0 && MarkFlatProfiles && S.getCallsiteSamples().size() == 0)
852 OS << " !Flat\n";
853
855}
856
857std::error_code
859 assert(!Context.hasContext() && "cs profile is not supported");
860 return writeNameIdx(Context.getFunction());
861}
862
864 auto &NTable = getNameTable();
865 const auto &Ret = NTable.find(FName);
866 if (Ret == NTable.end())
868 encodeULEB128(Ret->second, *OutputStream);
870}
871
873 auto &NTable = getNameTable();
874 NTable.insert(std::make_pair(FName, 0));
875}
876
878 addName(Context.getFunction());
879}
880
882 // Add all the names in indirect call targets.
883 for (const auto &I : S.getBodySamples()) {
884 const SampleRecord &Sample = I.second;
885 for (const auto &J : Sample.getCallTargets())
886 addName(J.first);
887 }
888
889 // Recursively add all the names for inlined callsites.
890 for (const auto &J : S.getCallsiteSamples())
891 for (const auto &FS : J.second) {
892 const FunctionSamples &CalleeSamples = FS.second;
893 addName(CalleeSamples.getFunction());
894 addNames(CalleeSamples);
895 }
896
897 if (!WriteVTableProf)
898 return;
899 // Add all the vtable names to NameTable.
900 for (const auto &VTableAccessCountMap :
902 // Add type name to NameTable.
903 for (const auto Type : llvm::make_first_range(VTableAccessCountMap)) {
904 addName(Type);
905 }
906 }
907}
908
910 const SampleContext &Context) {
911 if (Context.hasContext()) {
912 for (auto &Callsite : Context.getContextFrames())
914 CSNameTable.insert(std::make_pair(Context, 0));
915 } else {
916 SampleProfileWriterBinary::addName(Context.getFunction());
917 }
918}
919
921 auto &OS = *OutputStream;
922
923 // Write out the name table.
924 encodeULEB128(NameTable.size(), OS);
925 for (const auto *Entry : stabilizeTable(NameTable)) {
926 OS << Entry->first;
927 encodeULEB128(0, OS);
928 }
930}
931
932std::error_code
940
941std::error_code
943 // When calling write on a different profile map, existing names should be
944 // cleared.
945 NameTable.clear();
946
948
949 computeSummary(ProfileMap);
950 if (auto EC = writeSummary())
951 return EC;
952
953 // Generate the name table for all the functions referenced in the profile.
954 for (const auto &I : ProfileMap) {
955 addContext(I.second.getContext());
956 addNames(I.second);
957 }
958
961}
962
967
971
972void SampleProfileWriterExtBinaryBase::allocSecHdrTable() {
974
975 Writer.write(static_cast<uint64_t>(SectionHdrLayout.size()));
976 SecHdrTableOffset = OutputStream->tell();
977 for (uint32_t i = 0; i < SectionHdrLayout.size(); i++) {
978 Writer.write(static_cast<uint64_t>(-1));
979 Writer.write(static_cast<uint64_t>(-1));
980 Writer.write(static_cast<uint64_t>(-1));
981 Writer.write(static_cast<uint64_t>(-1));
982 }
983}
984
985std::error_code SampleProfileWriterExtBinaryBase::writeSecHdrTable() {
986 assert(SecHdrTable.size() == SectionHdrLayout.size() &&
987 "SecHdrTable entries doesn't match SectionHdrLayout");
988 SmallVector<uint32_t, 16> IndexMap(SecHdrTable.size(), -1);
989 for (uint32_t TableIdx = 0; TableIdx < SecHdrTable.size(); TableIdx++) {
990 IndexMap[SecHdrTable[TableIdx].LayoutIndex] = TableIdx;
991 }
992
993 // Write the section header table in the order specified in
994 // SectionHdrLayout. SectionHdrLayout specifies the sections
995 // order in which profile reader expect to read, so the section
996 // header table should be written in the order in SectionHdrLayout.
997 // Note that the section order in SecHdrTable may be different
998 // from the order in SectionHdrLayout, for example, SecFuncOffsetTable
999 // needs to be computed after SecLBRProfile (the order in SecHdrTable),
1000 // but it needs to be read before SecLBRProfile (the order in
1001 // SectionHdrLayout). So we use IndexMap above to switch the order.
1002 support::endian::SeekableWriter Writer(
1003 static_cast<raw_pwrite_stream &>(*OutputStream),
1005 for (uint32_t LayoutIdx = 0; LayoutIdx < SectionHdrLayout.size();
1006 LayoutIdx++) {
1007 assert(IndexMap[LayoutIdx] < SecHdrTable.size() &&
1008 "Incorrect LayoutIdx in SecHdrTable");
1009 auto Entry = SecHdrTable[IndexMap[LayoutIdx]];
1010 Writer.pwrite(static_cast<uint64_t>(Entry.Type),
1011 SecHdrTableOffset + 4 * LayoutIdx * sizeof(uint64_t));
1012 Writer.pwrite(static_cast<uint64_t>(Entry.Flags),
1013 SecHdrTableOffset + (4 * LayoutIdx + 1) * sizeof(uint64_t));
1014 Writer.pwrite(static_cast<uint64_t>(Entry.Offset),
1015 SecHdrTableOffset + (4 * LayoutIdx + 2) * sizeof(uint64_t));
1016 Writer.pwrite(static_cast<uint64_t>(Entry.Size),
1017 SecHdrTableOffset + (4 * LayoutIdx + 3) * sizeof(uint64_t));
1018 }
1019
1021}
1022
1023std::error_code SampleProfileWriterExtBinaryBase::writeHeader(
1024 const SampleProfileMap &ProfileMap) {
1025 auto &OS = *OutputStream;
1026 FileStart = OS.tell();
1028
1029 allocSecHdrTable();
1031}
1032
1036 "writeCallsiteVTableProf should not be called if WriteVTableProf is "
1037 "false");
1038
1039 encodeULEB128(CallsiteTypeMap.size(), OS);
1040 for (const auto &[Loc, TypeMap] : CallsiteTypeMap) {
1041 Loc.serialize(OS);
1042 if (std::error_code EC = serializeTypeMap(TypeMap, getNameTable(), OS))
1043 return EC;
1044 }
1045
1047}
1048
1050 auto &OS = *OutputStream;
1051 encodeULEB128(Summary->getTotalCount(), OS);
1052 encodeULEB128(Summary->getMaxCount(), OS);
1053 encodeULEB128(Summary->getMaxFunctionCount(), OS);
1054 encodeULEB128(Summary->getNumCounts(), OS);
1055 encodeULEB128(Summary->getNumFunctions(), OS);
1056 ArrayRef<ProfileSummaryEntry> Entries = Summary->getDetailedSummary();
1057 encodeULEB128(Entries.size(), OS);
1058 for (auto Entry : Entries) {
1059 encodeULEB128(Entry.Cutoff, OS);
1060 encodeULEB128(Entry.MinCount, OS);
1061 encodeULEB128(Entry.NumCounts, OS);
1062 }
1064}
1066 auto &OS = *OutputStream;
1067 if (std::error_code EC = writeContextIdx(S.getContext()))
1068 return EC;
1069
1071
1072 // Emit all the body samples.
1074 for (const auto &I : S.getBodySamples()) {
1075 LineLocation Loc = I.first;
1076 const SampleRecord &Sample = I.second;
1077 Loc.serialize(OS);
1078 Sample.serialize(OS, getNameTable());
1079 }
1080
1081 // Recursively emit all the callsite samples.
1082 uint64_t NumCallsites = 0;
1083 for (const auto &J : S.getCallsiteSamples())
1084 NumCallsites += J.second.size();
1085 encodeULEB128(NumCallsites, OS);
1086 for (const auto &J : S.getCallsiteSamples())
1087 for (const auto &FS : J.second) {
1088 J.first.serialize(OS);
1089 if (std::error_code EC = writeBody(FS.second))
1090 return EC;
1091 }
1092
1093 if (WriteVTableProf)
1095
1097}
1098
1099/// Write samples of a top-level function to a binary file.
1100///
1101/// \returns true if the samples were written successfully, false otherwise.
1102std::error_code
1107
1108/// Create a sample profile file writer based on the specified format.
1109///
1110/// \param Filename The file to create.
1111///
1112/// \param Format Encoding format for the profile file.
1113///
1114/// \returns an error code indicating the status of the created writer.
1117 std::error_code EC;
1118 std::unique_ptr<raw_ostream> OS;
1120 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::OF_None));
1121 else
1123 if (EC)
1124 return EC;
1125
1126 return create(OS, Format);
1127}
1128
1129/// Create a sample profile stream writer based on the specified format.
1130///
1131/// \param OS The output stream to store the profile data to.
1132///
1133/// \param Format Encoding format for the profile file.
1134///
1135/// \returns an error code indicating the status of the created writer.
1137SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
1139 std::error_code EC;
1140 std::unique_ptr<SampleProfileWriter> Writer;
1141
1142 // Currently only Text and Extended Binary format are supported for CSSPGO.
1144 Format == SPF_Binary)
1146
1147 if (Format == SPF_Binary)
1148 Writer.reset(new SampleProfileWriterRawBinary(OS));
1149 else if (Format == SPF_Ext_Binary)
1150 Writer.reset(new SampleProfileWriterExtBinary(OS));
1151 else if (Format == SPF_Text)
1152 Writer.reset(new SampleProfileWriterText(OS));
1153 else if (Format == SPF_GCC)
1155 else
1157
1158 if (EC)
1159 return EC;
1160
1161 Writer->Format = Format;
1162 if (Format != SPF_Ext_Binary)
1163 Writer->setFormatVersion(DefaultVersion);
1165 Writer->setFormatVersion(RequestedVersion);
1166 else
1168 return std::move(Writer);
1169}
1170
1173 Summary = Builder.computeSummaryForProfiles(ProfileMap);
1174}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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< 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"))
#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.
size_type size() const
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:826
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...
const CallsiteSampleMap & getCallsiteSamples() const LLVM_LIFETIME_BOUND
Return all the callsite samples collected in the body of the function.
FunctionId getFunction() const
Return the function name.
SampleContext & getContext() const LLVM_LIFETIME_BOUND
const TypeCountMap * findCallsiteTypeSamplesAt(const LineLocation &Loc) const LLVM_LIFETIME_BOUND
Returns the TypeCountMap for inlined callsites at the given Loc.
static LLVM_ABI std::atomic< bool > ProfileIsProbeBased
const CallsiteTypeMap & getCallsiteTypeCounts() const LLVM_LIFETIME_BOUND
Returns vtable access samples for the C++ types collected in this function.
const BodySampleMap & getBodySamples() const LLVM_LIFETIME_BOUND
Return all the samples collected in the body of the function.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
static LLVM_ABI std::atomic< bool > ProfileIsCS
std::string toString() const
Definition SampleProf.h:714
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, 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:395
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 LLVM_LIFETIME_BOUND
Return the call targets collected in this sample record.
Definition SampleProf.h:466
#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:114
static bool formatVersionIsSupported(uint64_t Version)
Definition SampleProf.h:132
SortedVectorMap< LineLocation, TypeCountMap, 0 > CallsiteTypeMap
Definition SampleProf.h:818
static void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:292
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
Definition SampleProf.h:308
std::pair< hash_code, const FunctionSamples * > NameFunctionSamples
@ SecFlagIsPreInlined
SecFlagIsPreInlined means this profile contains ShouldBeInlined contexts thus this is CS preinliner c...
Definition SampleProf.h:237
@ SecFlagHasVTableTypeProf
SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
Definition SampleProf.h:240
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
Definition SampleProf.h:234
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
Definition SampleProf.h:231
std::map< FunctionId, FunctionSamples > FunctionSamplesMap
Definition SampleProf.h:816
static constexpr uint64_t DefaultVersion
Definition SampleProf.h:126
constexpr char kVTableProfPrefix[]
Definition SampleProf.h:97
LLVM_ABI std::error_code serializeTypeMap(const TypeCountMap &Map, const MapVector< FunctionId, uint32_t > &NameTable, raw_ostream &OS)
Write Map to the output stream.
SortedVectorMap< FunctionId, uint64_t, 0 > TypeCountMap
Key represents type of a C++ polymorphic class type by its vtable and value represents its counter.
Definition SampleProf.h:375
detail::packed_endian_specific_integral< uint64_t, llvm::endianness::little, unaligned > ulittle64_t
Definition Endian.h:273
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
Definition Endian.h:270
@ 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
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:365
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:324
Adapter to write values to a stream in a particular byte order.
void write(ArrayRef< value_type > Val)