LLVM 24.0.0git
InstrProfReader.cpp
Go to the documentation of this file.
1//===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains support for reading profiling data for clang's
10// instrumentation based PGO and coverage.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/DenseMap.h"
18#include "llvm/ADT/StringRef.h"
21// #include "llvm/ProfileData/MemProf.h"
25#include "llvm/Support/Endian.h"
26#include "llvm/Support/Error.h"
31#include <algorithm>
32#include <cstddef>
33#include <cstdint>
34#include <limits>
35#include <memory>
36#include <optional>
37#include <system_error>
38#include <utility>
39#include <vector>
40
41using namespace llvm;
42
43// Extracts the variant information from the top 32 bits in the version and
44// returns an enum specifying the variants present.
47 if (Version & VARIANT_MASK_IR_PROF) {
49 }
50 if (Version & VARIANT_MASK_CSIR_PROF) {
52 }
53 if (Version & VARIANT_MASK_INSTR_ENTRY) {
55 }
56 if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) {
58 }
59 if (Version & VARIANT_MASK_BYTE_COVERAGE) {
61 }
64 }
65 if (Version & VARIANT_MASK_MEMPROF) {
66 ProfileKind |= InstrProfKind::MemProf;
67 }
68 if (Version & VARIANT_MASK_TEMPORAL_PROF) {
69 ProfileKind |= InstrProfKind::TemporalProfile;
70 }
71 return ProfileKind;
72}
73
76 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
77 : FS.getBufferForFile(Filename);
78 if (std::error_code EC = BufferOrErr.getError())
79 return errorCodeToError(EC);
80 return std::move(BufferOrErr.get());
81}
82
84 return Reader.readHeader();
85}
86
87/// Read a list of binary ids from a profile that consist of
88/// a. uint64_t binary id length
89/// b. uint8_t binary id data
90/// c. uint8_t padding (if necessary)
91/// This function is shared between raw and indexed profiles.
92/// Raw profiles are in host-endian format, and indexed profiles are in
93/// little-endian format. So, this function takes an argument indicating the
94/// associated endian format to read the binary ids correctly.
95static Error
97 ArrayRef<uint8_t> BinaryIdsBuffer,
98 std::vector<llvm::object::BuildID> &BinaryIds,
99 const llvm::endianness Endian) {
100 using namespace support;
101
102 const uint64_t BinaryIdsSize = BinaryIdsBuffer.size();
103 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.data();
104
105 if (BinaryIdsSize == 0)
106 return Error::success();
107
108 const uint8_t *BI = BinaryIdsStart;
109 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
110 const uint8_t *End =
111 reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
112
113 while (BI < BIEnd) {
114 size_t Remaining = BIEnd - BI;
115 // There should be enough left to read the binary id length.
116 if (Remaining < sizeof(uint64_t))
119 "not enough data to read binary id length");
120
121 uint64_t BILen = endian::readNext<uint64_t>(BI, Endian);
122 if (BILen == 0)
124 "binary id length is 0");
125
126 Remaining = BIEnd - BI;
127 // There should be enough left to read the binary id data.
128 if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
130 instrprof_error::malformed, "not enough data to read binary id data");
131
132 // Add binary id to the binary ids list.
133 BinaryIds.push_back(object::BuildID(BI, BI + BILen));
134
135 // Increment by binary id data length, which aligned to the size of uint64.
136 BI += alignToPowerOf2(BILen, sizeof(uint64_t));
137 if (BI > End)
140 "binary id section is greater than buffer size");
141 }
142
143 return Error::success();
144}
145
148 OS << "Binary IDs: \n";
149 for (const auto &BI : BinaryIds) {
150 for (auto I : BI)
151 OS << format("%02x", I);
152 OS << "\n";
153 }
154}
155
157 const Twine &Path, vfs::FileSystem &FS,
158 const InstrProfCorrelator *Correlator,
159 const object::BuildIDFetcher *BIDFetcher,
160 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
161 std::function<void(Error)> Warn) {
162 // Set up the buffer to read.
163 auto BufferOrError = setupMemoryBuffer(Path, FS);
164 if (Error E = BufferOrError.takeError())
165 return std::move(E);
166 return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
167 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
168}
169
171 std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
172 const object::BuildIDFetcher *BIDFetcher,
173 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
174 std::function<void(Error)> Warn) {
175 if (Buffer->getBufferSize() == 0)
177
178 std::unique_ptr<InstrProfReader> Result;
179 // Create the reader.
181 Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
182 else if (RawInstrProfReader64::hasFormat(*Buffer))
183 Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator,
184 BIDFetcher, BIDFetcherCorrelatorKind,
185 Warn));
186 else if (RawInstrProfReader32::hasFormat(*Buffer))
187 Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator,
188 BIDFetcher, BIDFetcherCorrelatorKind,
189 Warn));
190 else if (TextInstrProfReader::hasFormat(*Buffer))
191 Result.reset(new TextInstrProfReader(std::move(Buffer)));
192 else
194
195 // Initialize the reader and return the result.
196 if (Error E = initializeReader(*Result))
197 return std::move(E);
198
199 return std::move(Result);
200}
201
204 const Twine &RemappingPath) {
205 // Set up the buffer to read.
206 auto BufferOrError = setupMemoryBuffer(Path, FS);
207 if (Error E = BufferOrError.takeError())
208 return std::move(E);
209
210 // Set up the remapping buffer if requested.
211 std::unique_ptr<MemoryBuffer> RemappingBuffer;
212 std::string RemappingPathStr = RemappingPath.str();
213 if (!RemappingPathStr.empty()) {
214 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
215 if (Error E = RemappingBufferOrError.takeError())
216 return std::move(E);
217 RemappingBuffer = std::move(RemappingBufferOrError.get());
218 }
219
220 return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
221 std::move(RemappingBuffer));
222}
223
225IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
226 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
227 // Create the reader.
230 auto Result = std::make_unique<IndexedInstrProfReader>(
231 std::move(Buffer), std::move(RemappingBuffer));
232
233 // Initialize the reader and return the result.
234 if (Error E = initializeReader(*Result))
235 return std::move(E);
236
237 return std::move(Result);
238}
239
241 // Verify that this really looks like plain ASCII text by checking a
242 // 'reasonable' number of characters (up to profile magic size).
243 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
244 StringRef buffer = Buffer.getBufferStart();
245 return count == 0 ||
246 std::all_of(buffer.begin(), buffer.begin() + count,
247 [](char c) { return isPrint(c) || isSpace(c); });
248}
249
250// Read the profile variant flag from the header: ":FE" means this is a FE
251// generated profile. ":IR" means this is an IR level profile. Other strings
252// with a leading ':' will be reported an error format.
254 Symtab.reset(new InstrProfSymtab());
255
256 while (Line->starts_with(":")) {
257 StringRef Str = Line->substr(1);
258 if (Str.equals_insensitive("ir"))
260 else if (Str.equals_insensitive("fe"))
262 else if (Str.equals_insensitive("csir")) {
264 ProfileKind |= InstrProfKind::ContextSensitive;
265 } else if (Str.equals_insensitive("entry_first"))
267 else if (Str.equals_insensitive("not_entry_first"))
269 else if (Str.equals_insensitive("instrument_loop_entries"))
271 else if (Str.equals_insensitive("single_byte_coverage"))
273 else if (Str.equals_insensitive("temporal_prof_traces")) {
274 ProfileKind |= InstrProfKind::TemporalProfile;
275 if (auto Err = readTemporalProfTraceData())
276 return error(std::move(Err));
277 } else
279 ++Line;
280 }
281 return success();
282}
283
284/// Temporal profile trace data is stored in the header immediately after
285/// ":temporal_prof_traces". The first integer is the number of traces, the
286/// second integer is the stream size, then the following lines are the actual
287/// traces which consist of a weight and a comma separated list of function
288/// names.
289Error TextInstrProfReader::readTemporalProfTraceData() {
290 if ((++Line).is_at_end())
292
293 uint32_t NumTraces;
294 if (Line->getAsInteger(0, NumTraces))
296
297 if ((++Line).is_at_end())
299
300 if (Line->getAsInteger(0, TemporalProfTraceStreamSize))
302
303 for (uint32_t i = 0; i < NumTraces; i++) {
304 if ((++Line).is_at_end())
306
308 if (Line->getAsInteger(0, Trace.Weight))
310
311 if ((++Line).is_at_end())
313
314 SmallVector<StringRef> FuncNames;
315 Line->split(FuncNames, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
316 for (auto &FuncName : FuncNames)
317 Trace.FunctionNameRefs.push_back(
318 IndexedInstrProf::ComputeHash(FuncName.trim()));
319 TemporalProfTraces.push_back(std::move(Trace));
320 }
321 return success();
322}
323
324Error
325TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
326
327#define CHECK_LINE_END(Line) \
328 if (Line.is_at_end()) \
329 return error(instrprof_error::truncated);
330#define READ_NUM(Str, Dst) \
331 if ((Str).getAsInteger(10, (Dst))) \
332 return error(instrprof_error::malformed);
333#define VP_READ_ADVANCE(Val) \
334 CHECK_LINE_END(Line); \
335 uint32_t Val; \
336 READ_NUM((*Line), (Val)); \
337 Line++;
338
339 if (Line.is_at_end())
340 return success();
341
342 uint32_t NumValueKinds;
343 if (Line->getAsInteger(10, NumValueKinds)) {
344 // No value profile data
345 return success();
346 }
347 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
349 "number of value kinds is invalid");
350 Line++;
351
352 for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
353 VP_READ_ADVANCE(ValueKind);
354 if (ValueKind > IPVK_Last)
355 return error(instrprof_error::malformed, "value kind is invalid");
356 ;
358 if (!NumValueSites)
359 continue;
360
361 Record.reserveSites(VK, NumValueSites);
362 for (uint32_t S = 0; S < NumValueSites; S++) {
363 VP_READ_ADVANCE(NumValueData);
364
365 std::vector<InstrProfValueData> CurrentValues;
366 for (uint32_t V = 0; V < NumValueData; V++) {
367 CHECK_LINE_END(Line);
368 std::pair<StringRef, StringRef> VD = Line->rsplit(':');
369 uint64_t TakenCount, Value;
370 if (ValueKind == IPVK_IndirectCallTarget) {
371 if (InstrProfSymtab::isExternalSymbol(VD.first)) {
372 Value = 0;
373 } else {
374 if (Error E = Symtab->addFuncName(VD.first))
375 return E;
377 }
378 } else if (ValueKind == IPVK_VTableTarget) {
380 Value = 0;
381 else {
382 if (Error E = Symtab->addVTableName(VD.first))
383 return E;
385 }
386 } else {
387 READ_NUM(VD.first, Value);
388 }
389 READ_NUM(VD.second, TakenCount);
390 CurrentValues.push_back({Value, TakenCount});
391 Line++;
392 }
393 assert(CurrentValues.size() == NumValueData);
394 Record.addValueData(ValueKind, S, CurrentValues, nullptr);
395 }
396 }
397 return success();
398
399#undef CHECK_LINE_END
400#undef READ_NUM
401#undef VP_READ_ADVANCE
402}
403
405 // Skip empty lines and comments.
406 while (!Line.is_at_end() && (Line->empty() || Line->starts_with("#")))
407 ++Line;
408 // If we hit EOF while looking for a name, we're done.
409 if (Line.is_at_end()) {
411 }
412
413 // Read the function name.
414 Record.Name = *Line++;
415 if (Error E = Symtab->addFuncName(Record.Name))
416 return error(std::move(E));
417
418 // Read the function hash.
419 if (Line.is_at_end())
421 if ((Line++)->getAsInteger(0, Record.Hash))
423 "function hash is not a valid integer");
424
425 // Read the number of counters.
426 uint64_t NumCounters;
427 if (Line.is_at_end())
429 if ((Line++)->getAsInteger(10, NumCounters))
431 "number of counters is not a valid integer");
432 if (NumCounters == 0)
433 return error(instrprof_error::malformed, "number of counters is zero");
434
435 // Read each counter and fill our internal storage with the values.
436 Record.Clear();
437 Record.Counts.reserve(NumCounters);
438 for (uint64_t I = 0; I < NumCounters; ++I) {
439 if (Line.is_at_end())
442 if ((Line++)->getAsInteger(10, Count))
443 return error(instrprof_error::malformed, "count is invalid");
444 Record.Counts.push_back(Count);
445 }
446
447 // Bitmap byte information is indicated with special character.
448 if (Line->starts_with("$")) {
449 Record.BitmapBytes.clear();
450 // Read the number of bitmap bytes.
452 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
454 "number of bitmap bytes is not a valid integer");
455 if (NumBitmapBytes != 0) {
456 // Read each bitmap and fill our internal storage with the values.
457 Record.BitmapBytes.reserve(NumBitmapBytes);
458 for (uint8_t I = 0; I < NumBitmapBytes; ++I) {
459 if (Line.is_at_end())
461 uint8_t BitmapByte;
462 if ((Line++)->getAsInteger(0, BitmapByte))
464 "bitmap byte is not a valid integer");
465 Record.BitmapBytes.push_back(BitmapByte);
466 }
467 }
468 }
469
470 // Check if value profile data exists and read it if so.
471 if (Error E = readValueProfileData(Record))
472 return error(std::move(E));
473
474 return success();
475}
476
477template <class IntPtrT>
481
482template <class IntPtrT>
485 std::optional<uint64_t> Weight) {
486 if (TemporalProfTimestamps.empty()) {
487 assert(TemporalProfTraces.empty());
488 return TemporalProfTraces;
489 }
490 // Sort functions by their timestamps to build the trace.
491 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
493 if (Weight)
494 Trace.Weight = *Weight;
495 for (auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
496 Trace.FunctionNameRefs.push_back(NameRef);
497 TemporalProfTraces = {std::move(Trace)};
498 return TemporalProfTraces;
499}
500
501template <class IntPtrT>
503 if (DataBuffer.getBufferSize() < sizeof(uint64_t))
504 return false;
505 uint64_t Magic =
506 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
507 return RawInstrProf::getMagic<IntPtrT>() == Magic ||
509}
510
511template <class IntPtrT>
513 if (!hasFormat(*DataBuffer))
515 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
517 std::string("profile file header is truncated"));
518 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
519 DataBuffer->getBufferStart());
520 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
521 return readHeader(*Header);
522}
523
524template <class IntPtrT>
525Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
526 const char *End = DataBuffer->getBufferEnd();
527 // Skip zero padding between profiles.
528 while (CurrentPos != End && *CurrentPos == 0)
529 ++CurrentPos;
530 // If there's nothing left, we're done.
531 if (CurrentPos == End)
533 // If there isn't enough space for another header, this is probably just
534 // garbage at the end of the file.
535 if (CurrentPos + sizeof(RawInstrProf::Header) > End)
537 "not enough space for another header");
538 // The writer ensures each profile is padded to start at an aligned address.
539 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
541 "insufficient padding");
542 // The magic should have the same byte order as in the previous header.
543 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
544 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
546
547 // There's another profile to read, so we need to process the header.
548 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
549 return readHeader(*Header);
550}
551
552template <class IntPtrT>
553Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
554 if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
555 StringRef(VNamesStart, VNamesEnd - VNamesStart)))
556 return error(std::move(E));
557 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
558 const IntPtrT FPtr = swap(I->FunctionPointer);
559 if (!FPtr)
560 continue;
561 Symtab.mapAddress(FPtr, swap(I->NameRef));
562 }
563
564 if (VTableBegin != nullptr && VTableEnd != nullptr) {
565 for (const RawInstrProf::VTableProfileData<IntPtrT> *I = VTableBegin;
566 I != VTableEnd; ++I) {
567 const IntPtrT VPtr = swap(I->VTablePointer);
568 if (!VPtr)
569 continue;
570 // Map both begin and end address to the name hash, since the instrumented
571 // address could be somewhere in the middle.
572 // VPtr is of type uint32_t or uint64_t so 'VPtr + I->VTableSize' marks
573 // the end of vtable address.
574 Symtab.mapVTableAddress(VPtr, VPtr + swap(I->VTableSize),
575 swap(I->VTableNameHash));
576 }
577 }
578 return success();
579}
580
581template <class IntPtrT>
583 const RawInstrProf::Header &Header) {
584 Version = swap(Header.Version);
587 ("Profile uses raw profile format version = " +
589 "; expected version = " + Twine(RawInstrProf::Version) +
590 "\nPLEASE update this tool to version in the raw profile, or "
591 "regenerate raw profile with expected version.")
592 .str());
593 uint64_t BinaryIdSize = swap(Header.BinaryIdsSize);
594 // Binary id start just after the header if exists.
595 const uint8_t *BinaryIdStart =
596 reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
597 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
598 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
599 if (BinaryIdSize % sizeof(uint64_t))
600 return error(
602 ("BinaryIdSize (" + Twine(BinaryIdSize) + ") is not a multiple of 8")
603 .str());
604 if (BinaryIdEnd > BufferEnd)
606 ("Header.BinaryIdSize = " + Twine(BinaryIdSize) + " bytes; " +
607 Twine(BufferEnd - BinaryIdStart) + " bytes available")
608 .str());
609
610 ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize);
611 if (!BinaryIdsBuffer.empty()) {
612 if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer,
613 BinaryIds, getDataEndianness()))
614 return Err;
615 }
616
617 CountersDelta = swap(Header.CountersDelta);
618 BitmapDelta = swap(Header.BitmapDelta);
619 UniformCountersDelta = swap(Header.UniformCountersDelta);
620 NamesDelta = swap(Header.NamesDelta);
621 auto NumData = swap(Header.NumData);
622 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
623 auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize();
624 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
625 auto NumBitmapBytes = swap(Header.NumBitmapBytes);
626 auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes);
627 auto NumUniformCounters = swap(Header.NumUniformCounters);
628 auto PaddingBytesAfterUniformCounters =
629 swap(Header.PaddingBytesAfterUniformCounters);
630 auto NamesSize = swap(Header.NamesSize);
631 auto VTableNameSize = swap(Header.VNamesSize);
632 auto NumVTables = swap(Header.NumVTables);
633 ValueKindLast = swap(Header.ValueKindLast);
634
635 auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
636 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
637 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
638
639 auto VTableSectionSize =
640 NumVTables * sizeof(RawInstrProf::VTableProfileData<IntPtrT>);
641 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
642 auto UniformCountersSectionSize = NumUniformCounters * sizeof(uint64_t);
643
644 // Profile data starts after profile header and binary ids if exist.
645 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdSize;
646 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
647 ptrdiff_t BitmapOffset =
648 CountersOffset + CountersSize + PaddingBytesAfterCounters;
649 ptrdiff_t UniformCountersOffset =
650 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
651 ptrdiff_t NamesOffset = UniformCountersOffset + UniformCountersSectionSize +
652 PaddingBytesAfterUniformCounters;
653 ptrdiff_t VTableProfDataOffset =
654 NamesOffset + NamesSize + PaddingBytesAfterNames;
655 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
656 PaddingBytesAfterVTableProfData;
657 ptrdiff_t ValueDataOffset =
658 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
659
660 auto *Start = reinterpret_cast<const char *>(&Header);
661 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
662 // clang-format off
663 return error(
665 ("profile file size (" + Twine(DataBuffer->getBufferSize()) +
666 " bytes) smaller than expected (at least " + Twine(ValueDataOffset) +
667 " bytes: " +
668 Twine(sizeof(RawInstrProf::Header)) + "(Header) + " +
669 Twine(BinaryIdSize) + "(BinaryIdSize) + " +
670 Twine(DataSize) + "(DataSize) + " +
671 Twine(CountersSize) + "(CountersSize) + " +
672 Twine(NumBitmapBytes) + "(NumBitmapBytes) + " +
673 Twine(UniformCountersSectionSize) + "(UniformCountersSectionSize) + " +
674 Twine(NamesSize) + "(NamesSize) + " +
675 Twine(VTableSectionSize) + "(VTableSectionSize) + " +
676 Twine(VTableNameSize) + "(VTableNameSize) + " +
677 Twine(PaddingBytesBeforeCounters + PaddingBytesAfterCounters +
678 PaddingBytesAfterBitmapBytes + PaddingBytesAfterUniformCounters +
679 PaddingBytesAfterNames + PaddingBytesAfterVTableProfData +
680 PaddingBytesAfterVTableNames) +
681 "(Padding))")
682 .str());
683 // clang-format on
684
685 if (BIDFetcher) {
686 std::vector<object::BuildID> BinaryIDs;
687 if (Error E = readBinaryIds(BinaryIDs))
688 return E;
689 if (auto E = InstrProfCorrelator::get("", BIDFetcherCorrelatorKind,
690 BIDFetcher, BinaryIDs)
691 .moveInto(BIDFetcherCorrelator)) {
692 return E;
693 }
694 if (auto Err = BIDFetcherCorrelator->correlateProfileData(0))
695 return Err;
696 }
697
698 if (Correlator) {
699 // These sizes in the raw file are zero because we constructed them in the
700 // Correlator.
701 if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
702 BitmapDelta == 0 && NamesDelta == 0))
704 Data = Correlator->getDataPointer();
705 DataEnd = Data + Correlator->getDataSize();
706 NamesStart = Correlator->getNamesPointer();
707 NamesEnd = NamesStart + Correlator->getNamesSize();
708 } else if (BIDFetcherCorrelator) {
709 InstrProfCorrelatorImpl<IntPtrT> *BIDFetcherCorrelatorImpl =
711 BIDFetcherCorrelator.get());
712 Data = BIDFetcherCorrelatorImpl->getDataPointer();
713 DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize();
714 NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer();
715 NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize();
716 } else {
717 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
718 Start + DataOffset);
719 DataEnd = Data + NumData;
720 VTableBegin =
721 reinterpret_cast<const RawInstrProf::VTableProfileData<IntPtrT> *>(
722 Start + VTableProfDataOffset);
723 VTableEnd = VTableBegin + NumVTables;
724 NamesStart = Start + NamesOffset;
725 NamesEnd = NamesStart + NamesSize;
726 VNamesStart = Start + VTableNameOffset;
727 VNamesEnd = VNamesStart + VTableNameSize;
728 }
729
730 CountersStart = Start + CountersOffset;
731 CountersEnd = CountersStart + CountersSize;
732 BitmapStart = Start + BitmapOffset;
733 BitmapEnd = BitmapStart + NumBitmapBytes;
734 UniformCountersStart = Start + UniformCountersOffset;
735 UniformCountersEnd = UniformCountersStart + UniformCountersSectionSize;
736 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
737
738 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
739 if (Error E = createSymtab(*NewSymtab))
740 return E;
741
742 Symtab = std::move(NewSymtab);
743 return success();
744}
745
746template <class IntPtrT>
747Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
748 Record.Name = getName(Data->NameRef);
749 return success();
750}
751
752template <class IntPtrT>
753Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
754 Record.Hash = swap(Data->FuncHash);
755 return success();
756}
757
758template <class IntPtrT>
759Error RawInstrProfReader<IntPtrT>::readRawCounts(
761 uint32_t NumCounters = swap(Data->NumCounters);
762 if (NumCounters == 0)
763 return error(instrprof_error::malformed, "number of counters is zero");
764
765 ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
766 if (CounterBaseOffset < 0)
767 return error(
769 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
770
771 if (CounterBaseOffset >= CountersEnd - CountersStart)
773 ("counter offset " + Twine(CounterBaseOffset) +
774 " is greater than the maximum counter offset " +
775 Twine(CountersEnd - CountersStart - 1))
776 .str());
777
778 uint64_t MaxNumCounters =
779 (CountersEnd - (CountersStart + CounterBaseOffset)) /
780 getCounterTypeSize();
781 if (NumCounters > MaxNumCounters)
783 ("number of counters " + Twine(NumCounters) +
784 " is greater than the maximum number of counters " +
785 Twine(MaxNumCounters))
786 .str());
787
788 Record.Counts.clear();
789 Record.Counts.reserve(NumCounters);
790 for (uint32_t I = 0; I < NumCounters; I++) {
791 const char *Ptr =
792 CountersStart + CounterBaseOffset + I * getCounterTypeSize();
793 if (I == 0 && hasTemporalProfile()) {
794 uint64_t TimestampValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
795 if (TimestampValue != 0 &&
796 TimestampValue != std::numeric_limits<uint64_t>::max()) {
797 TemporalProfTimestamps.emplace_back(TimestampValue,
798 swap(Data->NameRef));
799 TemporalProfTraceStreamSize = 1;
800 }
801 if (hasSingleByteCoverage()) {
802 // In coverage mode, getCounterTypeSize() returns 1 byte but our
803 // timestamp field has size uint64_t. Increment I so that the next
804 // iteration of this for loop points to the byte after the timestamp
805 // field, i.e., I += 8.
806 I += 7;
807 }
808 continue;
809 }
810 if (hasSingleByteCoverage()) {
811 // A value of zero signifies the block is covered.
812 Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
813 } else {
814 uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
815 if (CounterValue > MaxCounterValue && Warn)
818
819 Record.Counts.push_back(CounterValue);
820 }
821 }
822
823 return success();
824}
825
826template <class IntPtrT>
827Error RawInstrProfReader<IntPtrT>::readRawBitmapBytes(InstrProfRecord &Record) {
828 uint32_t NumBitmapBytes = swap(Data->NumBitmapBytes);
829
830 Record.BitmapBytes.clear();
831 Record.BitmapBytes.reserve(NumBitmapBytes);
832
833 // It's possible MCDC is either not enabled or only used for some functions
834 // and not others. So if we record 0 bytes, just move on.
835 if (NumBitmapBytes == 0)
836 return success();
837
838 // BitmapDelta decreases as we advance to the next data record.
839 ptrdiff_t BitmapOffset = swap(Data->BitmapPtr) - BitmapDelta;
840 if (BitmapOffset < 0)
841 return error(
843 ("bitmap offset " + Twine(BitmapOffset) + " is negative").str());
844
845 if (BitmapOffset >= BitmapEnd - BitmapStart)
847 ("bitmap offset " + Twine(BitmapOffset) +
848 " is greater than the maximum bitmap offset " +
849 Twine(BitmapEnd - BitmapStart - 1))
850 .str());
851
852 uint64_t MaxNumBitmapBytes =
853 (BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t);
854 if (NumBitmapBytes > MaxNumBitmapBytes)
856 ("number of bitmap bytes " + Twine(NumBitmapBytes) +
857 " is greater than the maximum number of bitmap bytes " +
858 Twine(MaxNumBitmapBytes))
859 .str());
860
861 for (uint32_t I = 0; I < NumBitmapBytes; I++) {
862 const char *Ptr = BitmapStart + BitmapOffset + I;
863 Record.BitmapBytes.push_back(swap(*Ptr));
864 }
865
866 return success();
867}
868
869template <class IntPtrT>
870Error RawInstrProfReader<IntPtrT>::readRawUniformCounters(
872 Record.UniformCounts.clear();
873
874 if (UniformCountersStart == UniformCountersEnd)
875 return success();
876
877 uint32_t NumCounters = swap(Data->NumCounters);
878
879 ptrdiff_t UniformCounterOffset =
880 swap(Data->UniformCounterPtr) - UniformCountersDelta;
881 if (UniformCounterOffset < 0)
883 ("uniform counter offset " + Twine(UniformCounterOffset) +
884 " is negative")
885 .str());
886
887 if (UniformCounterOffset >= UniformCountersEnd - UniformCountersStart)
889 ("uniform counter offset " + Twine(UniformCounterOffset) +
890 " is greater than the maximum uniform counter offset " +
891 Twine(UniformCountersEnd - UniformCountersStart - 1))
892 .str());
893
894 uint64_t MaxNumCounters =
895 (UniformCountersEnd - (UniformCountersStart + UniformCounterOffset)) /
896 sizeof(uint64_t);
897 if (NumCounters > MaxNumCounters)
899 ("number of uniform counters " + Twine(NumCounters) +
900 " is greater than the maximum number of uniform counters " +
901 Twine(MaxNumCounters))
902 .str());
903
904 Record.UniformCounts.reserve(NumCounters);
905 for (uint32_t I = 0; I < NumCounters; I++) {
906 const char *Ptr =
907 UniformCountersStart + UniformCounterOffset + I * sizeof(uint64_t);
908 uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
909 Record.UniformCounts.push_back(CounterValue);
910 }
911
912 return success();
913}
914
915template <class IntPtrT>
916Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
918 Record.clearValueData();
919 CurValueDataSize = 0;
920 // Need to match the logic in value profile dumper code in compiler-rt:
921 uint32_t NumValueKinds = 0;
922 for (uint32_t I = 0; I < IPVK_Last + 1; I++)
923 NumValueKinds += (Data->NumValueSites[I] != 0);
924
925 if (!NumValueKinds)
926 return success();
927
929 ValueProfData::getValueProfData(
930 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
931 getDataEndianness());
932
933 if (Error E = VDataPtrOrErr.takeError())
934 return E;
935
936 // Note that besides deserialization, this also performs the conversion for
937 // indirect call targets. The function pointers from the raw profile are
938 // remapped into function name hashes.
939 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
940 CurValueDataSize = VDataPtrOrErr.get()->getSize();
941 return success();
942}
943
944template <class IntPtrT>
946 // Keep reading profiles that consist of only headers and no profile data and
947 // counters.
948 while (atEnd())
949 // At this point, ValueDataStart field points to the next header.
950 if (Error E = readNextHeader(getNextHeaderPos()))
951 return error(std::move(E));
952
953 // Read name and set it in Record.
954 if (Error E = readName(Record))
955 return error(std::move(E));
956
957 // Read FuncHash and set it in Record.
958 if (Error E = readFuncHash(Record))
959 return error(std::move(E));
960
961 Record.OffloadDeviceWaveSize = swap(Data->OffloadDeviceWaveSize);
962
963 // Read raw counts and set Record.
964 if (Error E = readRawCounts(Record))
965 return error(std::move(E));
966
967 // Read raw bitmap bytes and set Record.
968 if (Error E = readRawBitmapBytes(Record))
969 return error(std::move(E));
970
971 // Read raw uniform counters and set Record.
972 if (Error E = readRawUniformCounters(Record))
973 return error(std::move(E));
974
975 // Read value data and set Record.
976 if (Error E = readValueProfilingData(Record))
977 return error(std::move(E));
978
979 // Iterate.
980 advanceData();
981 return success();
982}
983
984template <class IntPtrT>
986 std::vector<llvm::object::BuildID> &BinaryIds) {
987 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
988 this->BinaryIds.end());
989 return Error::success();
990}
991
992template <class IntPtrT>
994 if (!BinaryIds.empty())
995 printBinaryIdsInternal(OS, BinaryIds);
996 return Error::success();
997}
998
999namespace llvm {
1000
1001template class RawInstrProfReader<uint32_t>;
1002template class RawInstrProfReader<uint64_t>;
1003
1004} // end namespace llvm
1005
1010
1013
1015 const unsigned char *&D, const unsigned char *const End) {
1017 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
1018
1019 if (VDataPtrOrErr.takeError())
1020 return false;
1021
1022 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
1023 D += VDataPtrOrErr.get()->TotalSize;
1024
1025 return true;
1026}
1027
1029 offset_type N) {
1030 using namespace support;
1031
1032 // Check if the data is corrupt. If so, don't try to read it.
1033 if (N % sizeof(uint64_t))
1034 return data_type();
1035
1036 DataBuffer.clear();
1037 std::vector<uint64_t> CounterBuffer;
1038 std::vector<uint8_t> BitmapByteBuffer;
1039 std::vector<uint8_t> UniformityBitsBuffer;
1040
1041 const unsigned char *End = D + N;
1042 while (D < End) {
1043 // Read hash.
1044 if (D + sizeof(uint64_t) > End)
1045 return data_type();
1047
1048 // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
1049 uint64_t CountsSize = N / sizeof(uint64_t) - 1;
1050 // If format version is different then read the number of counters.
1052 if (D + sizeof(uint64_t) > End)
1053 return data_type();
1055 }
1056 // Read counter values.
1057 if (D + CountsSize * sizeof(uint64_t) > End)
1058 return data_type();
1059
1060 CounterBuffer.clear();
1061 CounterBuffer.reserve(CountsSize);
1062 for (uint64_t J = 0; J < CountsSize; ++J)
1063 CounterBuffer.push_back(
1065
1066 // Read bitmap bytes for GET_VERSION(FormatVersion) > 10.
1068 uint64_t BitmapBytes = 0;
1069 if (D + sizeof(uint64_t) > End)
1070 return data_type();
1072 BitmapByteBuffer.clear();
1073 BitmapByteBuffer.reserve(BitmapBytes);
1074
1075 if (GET_VERSION(FormatVersion) >=
1077 // Version 14+: bitmap bytes stored as uint8_t with padding.
1078 uint64_t PaddedSize = alignTo(BitmapBytes, sizeof(uint64_t));
1079 if (D + PaddedSize > End)
1080 return data_type();
1081 for (uint64_t J = 0; J < BitmapBytes; ++J)
1082 BitmapByteBuffer.push_back(
1084 for (uint64_t J = BitmapBytes; J < PaddedSize; ++J)
1086
1087 // Read uniformity bits (AMDGPU offload profiling).
1088 uint64_t UniformityBitsSize = 0;
1089 if (D + sizeof(uint64_t) > End)
1090 return data_type();
1091 UniformityBitsSize =
1093 uint64_t PaddedUniformitySize =
1094 alignTo(UniformityBitsSize, sizeof(uint64_t));
1095 if (D + PaddedUniformitySize > End)
1096 return data_type();
1097 UniformityBitsBuffer.clear();
1098 UniformityBitsBuffer.reserve(UniformityBitsSize);
1099 for (uint64_t J = 0; J < UniformityBitsSize; ++J)
1100 UniformityBitsBuffer.push_back(
1102 for (uint64_t J = UniformityBitsSize; J < PaddedUniformitySize; ++J)
1104 } else {
1105 // Version 11-13: each bitmap byte stored as a uint64_t.
1106 if (D + BitmapBytes * sizeof(uint64_t) > End)
1107 return data_type();
1108 for (uint64_t J = 0; J < BitmapBytes; ++J)
1109 BitmapByteBuffer.push_back(static_cast<uint8_t>(
1111 }
1112 }
1113
1114 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
1115 std::move(BitmapByteBuffer),
1116 std::move(UniformityBitsBuffer));
1117
1118 // Read value profiling data.
1120 !readValueProfilingData(D, End)) {
1121 DataBuffer.clear();
1122 return data_type();
1123 }
1124 }
1125 return DataBuffer;
1126}
1127
1128template <typename HashTableImpl>
1131 auto Iter = HashTable->find(FuncName);
1132 if (Iter == HashTable->end())
1134
1135 Data = (*Iter);
1136 if (Data.empty())
1138 "profile data is empty");
1139
1140 return Error::success();
1141}
1142
1143template <typename HashTableImpl>
1146 if (atEnd())
1148
1149 Data = *RecordIterator;
1150
1151 if (Data.empty())
1153 "profile data is empty");
1154
1155 return Error::success();
1156}
1157
1158template <typename HashTableImpl>
1160 const unsigned char *Buckets, const unsigned char *const Payload,
1161 const unsigned char *const Base, IndexedInstrProf::HashT HashType,
1162 uint64_t Version) {
1163 FormatVersion = Version;
1164 HashTable.reset(HashTableImpl::Create(
1165 Buckets, Payload, Base,
1166 typename HashTableImpl::InfoType(HashType, Version)));
1167 RecordIterator = HashTable->data_begin();
1168}
1169
1170template <typename HashTableImpl>
1174
1175namespace {
1176/// A remapper that does not apply any remappings.
1177class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
1178 InstrProfReaderIndexBase &Underlying;
1179
1180public:
1181 InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
1182 : Underlying(Underlying) {}
1183
1184 Error getRecords(StringRef FuncName,
1186 return Underlying.getRecords(FuncName, Data);
1187 }
1188};
1189} // namespace
1190
1191/// A remapper that applies remappings based on a symbol remapping file.
1192template <typename HashTableImpl>
1194 : public InstrProfReaderRemapper {
1195public:
1197 std::unique_ptr<MemoryBuffer> RemapBuffer,
1199 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
1200 }
1201
1202 /// Extract the original function name from a PGO function name.
1204 // We can have multiple pieces separated by kGlobalIdentifierDelimiter (
1205 // semicolon now and colon in older profiles); there can be pieces both
1206 // before and after the mangled name. Find the first part that starts with
1207 // '_Z'; we'll assume that's the mangled name we want.
1208 std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
1209 while (true) {
1210 Parts = Parts.second.split(GlobalIdentifierDelimiter);
1211 if (Parts.first.starts_with("_Z"))
1212 return Parts.first;
1213 if (Parts.second.empty())
1214 return Name;
1215 }
1216 }
1217
1218 /// Given a mangled name extracted from a PGO function name, and a new
1219 /// form for that mangled name, reconstitute the name.
1220 static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
1221 StringRef Replacement,
1222 SmallVectorImpl<char> &Out) {
1223 Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
1224 Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
1225 llvm::append_range(Out, Replacement);
1226 Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
1227 }
1228
1230 if (Error E = Remappings.read(*RemapBuffer))
1231 return E;
1232 for (StringRef Name : Underlying.HashTable->keys()) {
1233 StringRef RealName = extractName(Name);
1234 if (auto Key = Remappings.insert(RealName)) {
1235 // FIXME: We could theoretically map the same equivalence class to
1236 // multiple names in the profile data. If that happens, we should
1237 // return NamedInstrProfRecords from all of them.
1238 MappedNames.insert({Key, RealName});
1239 }
1240 }
1241 return Error::success();
1242 }
1243
1246 StringRef RealName = extractName(FuncName);
1247 if (auto Key = Remappings.lookup(RealName)) {
1248 StringRef Remapped = MappedNames.lookup(Key);
1249 if (!Remapped.empty()) {
1250 if (RealName.begin() == FuncName.begin() &&
1251 RealName.end() == FuncName.end())
1252 FuncName = Remapped;
1253 else {
1254 // Try rebuilding the name from the given remapping.
1255 SmallString<256> Reconstituted;
1256 reconstituteName(FuncName, RealName, Remapped, Reconstituted);
1257 Error E = Underlying.getRecords(Reconstituted, Data);
1258 if (!E)
1259 return E;
1260
1261 // If we failed because the name doesn't exist, fall back to asking
1262 // about the original name.
1263 if (Error Unhandled = handleErrors(
1264 std::move(E), [](std::unique_ptr<InstrProfError> Err) {
1265 return Err->get() == instrprof_error::unknown_function
1266 ? Error::success()
1267 : Error(std::move(Err));
1268 }))
1269 return Unhandled;
1270 }
1271 }
1272 }
1273 return Underlying.getRecords(FuncName, Data);
1274 }
1275
1276private:
1277 /// The memory buffer containing the remapping configuration. Remappings
1278 /// holds pointers into this buffer.
1279 std::unique_ptr<MemoryBuffer> RemapBuffer;
1280
1281 /// The mangling remapper.
1282 SymbolRemappingReader Remappings;
1283
1284 /// Mapping from mangled name keys to the name used for the key in the
1285 /// profile data.
1286 /// FIXME: Can we store a location within the on-disk hash table instead of
1287 /// redoing lookup?
1289
1290 /// The real profile data reader.
1292};
1293
1295 using namespace support;
1296
1297 if (DataBuffer.getBufferSize() < 8)
1298 return false;
1299 uint64_t Magic = endian::read<uint64_t, aligned>(DataBuffer.getBufferStart(),
1301 // Verify that it's magical.
1302 return Magic == IndexedInstrProf::Magic;
1303}
1304
1305const unsigned char *
1306IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
1307 const unsigned char *Cur, bool UseCS) {
1308 using namespace IndexedInstrProf;
1309 using namespace support;
1310
1312 const IndexedInstrProf::Summary *SummaryInLE =
1313 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
1318 uint32_t SummarySize =
1319 IndexedInstrProf::Summary::getSize(NFields, NEntries);
1320 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1321 IndexedInstrProf::allocSummary(SummarySize);
1322
1323 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
1324 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
1325 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
1327
1328 SummaryEntryVector DetailedSummary;
1329 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
1330 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
1331 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
1332 Ent.NumBlocks);
1333 }
1334 std::unique_ptr<llvm::ProfileSummary> &Summary =
1335 UseCS ? this->CS_Summary : this->Summary;
1336
1337 // initialize InstrProfSummary using the SummaryData from disk.
1338 Summary = std::make_unique<ProfileSummary>(
1340 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1341 SummaryData->get(Summary::MaxBlockCount),
1342 SummaryData->get(Summary::MaxInternalBlockCount),
1343 SummaryData->get(Summary::MaxFunctionCount),
1344 SummaryData->get(Summary::TotalNumBlocks),
1345 SummaryData->get(Summary::TotalNumFunctions));
1346 return Cur + SummarySize;
1347 } else {
1348 // The older versions do not support a profile summary. This just computes
1349 // an empty summary, which will not result in accurate hot/cold detection.
1350 // We would need to call addRecord for all NamedInstrProfRecords to get the
1351 // correct summary. However, this version is old (prior to early 2016) and
1352 // has not been supporting an accurate summary for several years.
1353 InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
1354 Summary = Builder.getSummary();
1355 return Cur;
1356 }
1357}
1358
1360 using namespace support;
1361
1362 const unsigned char *Start =
1363 (const unsigned char *)DataBuffer->getBufferStart();
1364 const unsigned char *Cur = Start;
1365 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1367
1368 auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
1369 if (!HeaderOr)
1370 return HeaderOr.takeError();
1371
1372 const IndexedInstrProf::Header *Header = &HeaderOr.get();
1373 Cur += Header->size();
1374
1375 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1376 /* UseCS */ false);
1377 if (Header->Version & VARIANT_MASK_CSIR_PROF)
1378 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1379 /* UseCS */ true);
1380 // Read the hash type and start offset.
1381 IndexedInstrProf::HashT HashType =
1382 static_cast<IndexedInstrProf::HashT>(Header->HashType);
1383 if (HashType > IndexedInstrProf::HashT::Last)
1385
1386 // The hash table with profile counts comes next.
1387 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1388 Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1389
1390 // The MemProfOffset field in the header is only valid when the format
1391 // version is higher than 8 (when it was introduced).
1392 if (Header->getIndexedProfileVersion() >= 8 &&
1393 Header->Version & VARIANT_MASK_MEMPROF) {
1394 if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset))
1395 return E;
1396 }
1397
1398 // BinaryIdOffset field in the header is only valid when the format version
1399 // is higher than 9 (when it was introduced).
1400 if (Header->getIndexedProfileVersion() >= 9) {
1401 const unsigned char *Ptr = Start + Header->BinaryIdOffset;
1402 // Read binary ids size.
1403 uint64_t BinaryIdsSize =
1405 if (BinaryIdsSize % sizeof(uint64_t))
1406 return error(
1408 ("BinaryIdSize (" + Twine(BinaryIdsSize) + ") is not a multiple of 8")
1409 .str());
1410 // Set the binary ids start.
1411 BinaryIdsBuffer = ArrayRef<uint8_t>(Ptr, BinaryIdsSize);
1412 if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd())
1414 "corrupted binary ids");
1415 }
1416
1417 if (Header->getIndexedProfileVersion() >= 12) {
1418 const unsigned char *Ptr = Start + Header->VTableNamesOffset;
1419
1420 uint64_t CompressedVTableNamesLen =
1422
1423 // Writer first writes the length of compressed string, and then the actual
1424 // content.
1425 const char *VTableNamePtr = (const char *)Ptr;
1426 if (VTableNamePtr > DataBuffer->getBufferEnd())
1428
1429 VTableName = StringRef(VTableNamePtr, CompressedVTableNamesLen);
1430 }
1431
1432 if (Header->getIndexedProfileVersion() >= 10 &&
1433 Header->Version & VARIANT_MASK_TEMPORAL_PROF) {
1434 const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset;
1435 const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd();
1436 // Expect at least two 64 bit fields: NumTraces, and TraceStreamSize
1437 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1439 const uint64_t NumTraces =
1443 for (unsigned i = 0; i < NumTraces; i++) {
1444 // Expect at least two 64 bit fields: Weight and NumFunctions
1445 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1448 Trace.Weight =
1450 const uint64_t NumFunctions =
1452 // Expect at least NumFunctions 64 bit fields
1453 if (Ptr + NumFunctions * sizeof(uint64_t) > PtrEnd)
1455 for (unsigned j = 0; j < NumFunctions; j++) {
1456 const uint64_t NameRef =
1458 Trace.FunctionNameRefs.push_back(NameRef);
1459 }
1460 TemporalProfTraces.push_back(std::move(Trace));
1461 }
1462 }
1463
1464 // Load the remapping table now if requested.
1465 if (RemappingBuffer) {
1466 Remapper =
1467 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1468 std::move(RemappingBuffer), *IndexPtr);
1469 if (Error E = Remapper->populateRemappings())
1470 return E;
1471 } else {
1472 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1473 }
1474 Index = std::move(IndexPtr);
1475
1476 return success();
1477}
1478
1480 if (Symtab)
1481 return *Symtab;
1482
1483 auto NewSymtab = std::make_unique<InstrProfSymtab>();
1484
1485 if (Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1486 auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1487 consumeError(error(ErrCode, Msg));
1488 }
1489
1490 // finalizeSymtab is called inside populateSymtab.
1491 if (Error E = Index->populateSymtab(*NewSymtab)) {
1492 auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1493 consumeError(error(ErrCode, Msg));
1494 }
1495
1496 Symtab = std::move(NewSymtab);
1497 return *Symtab;
1498}
1499
1501 StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName,
1502 uint64_t *MismatchedFuncSum) {
1504 uint64_t FuncSum = 0;
1505 auto Err = Remapper->getRecords(FuncName, Data);
1506 if (Err) {
1507 // If we don't find FuncName, try DeprecatedFuncName to handle profiles
1508 // built by older compilers.
1509 auto Err2 =
1510 handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error {
1511 if (IE.get() != instrprof_error::unknown_function)
1512 return make_error<InstrProfError>(IE);
1513 if (auto Err = Remapper->getRecords(DeprecatedFuncName, Data))
1514 return Err;
1515 return Error::success();
1516 });
1517 if (Err2)
1518 return std::move(Err2);
1519 }
1520 // Found it. Look for counters with the right hash.
1521
1522 // A flag to indicate if the records are from the same type
1523 // of profile (i.e cs vs nocs).
1524 bool CSBitMatch = false;
1525 auto getFuncSum = [](ArrayRef<uint64_t> Counts) {
1526 uint64_t ValueSum = 0;
1527 for (uint64_t CountValue : Counts) {
1528 if (CountValue == (uint64_t)-1)
1529 continue;
1530 // Handle overflow -- if that happens, return max.
1531 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1532 return std::numeric_limits<uint64_t>::max();
1533 ValueSum += CountValue;
1534 }
1535 return ValueSum;
1536 };
1537
1538 for (const NamedInstrProfRecord &I : Data) {
1539 // Check for a match and fill the vector if there is one.
1540 if (I.Hash == FuncHash)
1541 return std::move(I);
1544 CSBitMatch = true;
1545 if (MismatchedFuncSum == nullptr)
1546 continue;
1547 FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1548 }
1549 }
1550 if (CSBitMatch) {
1551 if (MismatchedFuncSum != nullptr)
1552 *MismatchedFuncSum = FuncSum;
1554 }
1556}
1557
1560 MemProfFrameHashTable &MemProfFrameTable,
1561 MemProfCallStackHashTable &MemProfCallStackTable) {
1563 MemProfFrameTable);
1564
1566 MemProfCallStackTable, FrameIdConv);
1567
1568 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1569
1570 // Check that all call stack ids were successfully converted to call stacks.
1571 if (CSIdConv.LastUnmappedId) {
1574 "memprof call stack not found for call stack id " +
1575 Twine(*CSIdConv.LastUnmappedId));
1576 }
1577
1578 // Check that all frame ids were successfully converted to frames.
1579 if (FrameIdConv.LastUnmappedId) {
1581 "memprof frame not found for frame id " +
1582 Twine(*FrameIdConv.LastUnmappedId));
1583 }
1584
1585 return Record;
1586}
1587
1590 // TODO: Add memprof specific errors.
1591 if (MemProfRecordTable == nullptr)
1593 "no memprof data available in profile");
1594 auto Iter = MemProfRecordTable->find(FuncNameHash);
1595 if (Iter == MemProfRecordTable->end())
1598 "memprof record not found for function hash " + Twine(FuncNameHash));
1599
1600 const memprof::IndexedMemProfRecord &IndexedRecord = *Iter;
1601 switch (Version) {
1602 case memprof::Version2:
1603 assert(MemProfFrameTable && "MemProfFrameTable must be available");
1604 assert(MemProfCallStackTable && "MemProfCallStackTable must be available");
1605 return getMemProfRecordV2(IndexedRecord, *MemProfFrameTable,
1606 *MemProfCallStackTable);
1607 // Combine V3 and V4 cases as the record conversion logic is the same.
1608 case memprof::Version3:
1609 case memprof::Version4:
1610 assert(!MemProfFrameTable && "MemProfFrameTable must not be available");
1611 assert(!MemProfCallStackTable &&
1612 "MemProfCallStackTable must not be available");
1613 assert(FrameBase && "FrameBase must be available");
1614 assert(CallStackBase && "CallStackBase must be available");
1615 {
1616 memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1617 memprof::LinearCallStackIdConverter CSIdConv(CallStackBase, FrameIdConv);
1618 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1619 return Record;
1620 }
1621 }
1622
1625 formatv("MemProf version {} not supported; "
1626 "requires version between {} and {}, inclusive",
1629}
1630
1633 assert(MemProfRecordTable);
1634 assert(Version == memprof::Version3 || Version == memprof::Version4);
1635
1636 memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1637 memprof::CallerCalleePairExtractor Extractor(CallStackBase, FrameIdConv,
1638 RadixTreeSize);
1639
1640 // The set of linear call stack IDs that we need to traverse from. We expect
1641 // the set to be dense, so we use a BitVector.
1642 BitVector Worklist(RadixTreeSize);
1643
1644 // Collect the set of linear call stack IDs. Since we expect a lot of
1645 // duplicates, we first collect them in the form of a bit vector before
1646 // processing them.
1647 for (const memprof::IndexedMemProfRecord &IndexedRecord :
1648 MemProfRecordTable->data()) {
1649 for (const memprof::IndexedAllocationInfo &IndexedAI :
1650 IndexedRecord.AllocSites)
1651 Worklist.set(IndexedAI.CSId);
1652 }
1653
1654 // Collect caller-callee pairs for each linear call stack ID in Worklist.
1655 for (unsigned CS : Worklist.set_bits())
1656 Extractor(CS);
1657
1659 std::move(Extractor.CallerCalleePairs);
1660
1661 // Sort each call list by the source location.
1662 for (auto &[CallerGUID, CallList] : Pairs) {
1663 llvm::sort(CallList);
1664 CallList.erase(llvm::unique(CallList), CallList.end());
1665 }
1666
1667 return Pairs;
1668}
1669
1671 memprof::AllMemProfData AllMemProfData;
1672 AllMemProfData.HeapProfileRecords.reserve(
1673 MemProfRecordTable->getNumEntries());
1674 for (uint64_t Key : MemProfRecordTable->keys()) {
1675 auto Record = getMemProfRecord(Key);
1676 if (Record.takeError())
1677 continue;
1679 Pair.GUID = Key;
1680 Pair.Record = std::move(*Record);
1681 AllMemProfData.HeapProfileRecords.push_back(std::move(Pair));
1682 }
1683 // Populate the data access profiles for yaml output.
1684 if (DataAccessProfileData != nullptr) {
1685 AllMemProfData.YamlifiedDataAccessProfiles.Records.reserve(
1686 DataAccessProfileData->getRecords().size());
1687 AllMemProfData.YamlifiedDataAccessProfiles.KnownColdSymbols.reserve(
1688 DataAccessProfileData->getKnownColdSymbols().size());
1689 AllMemProfData.YamlifiedDataAccessProfiles.KnownColdStrHashes.reserve(
1690 DataAccessProfileData->getKnownColdHashes().size());
1691 for (const auto &[SymHandleRef, RecordRef] :
1692 DataAccessProfileData->getRecords())
1693 AllMemProfData.YamlifiedDataAccessProfiles.Records.push_back(
1694 memprof::DataAccessProfRecord(SymHandleRef, RecordRef.AccessCount,
1695 RecordRef.Locations));
1696 for (StringRef ColdSymbol : DataAccessProfileData->getKnownColdSymbols())
1697 AllMemProfData.YamlifiedDataAccessProfiles.KnownColdSymbols.push_back(
1698 ColdSymbol.str());
1699 for (uint64_t Hash : DataAccessProfileData->getKnownColdHashes())
1700 AllMemProfData.YamlifiedDataAccessProfiles.KnownColdStrHashes.push_back(
1701 Hash);
1705 return lhs.AccessCount > rhs.AccessCount;
1706 });
1709 [](const std::string &lhs, const std::string &rhs) {
1710 return lhs < rhs;
1711 });
1714 [](const uint64_t &lhs, const uint64_t &rhs) { return lhs < rhs; });
1715 }
1716 return AllMemProfData;
1717}
1718
1721 std::vector<uint64_t> &Counts) {
1722 auto Record = getInstrProfRecord(FuncName, FuncHash);
1723 if (Error E = Record.takeError())
1724 return error(std::move(E));
1725
1726 Counts = Record.get().Counts;
1727 return success();
1728}
1729
1732 BitVector &Bitmap) {
1733 auto Record = getInstrProfRecord(FuncName, FuncHash);
1734 if (Error E = Record.takeError())
1735 return error(std::move(E));
1736
1737 const auto &BitmapBytes = Record.get().BitmapBytes;
1738 size_t I = 0, E = BitmapBytes.size();
1739 Bitmap.resize(E * CHAR_BIT);
1741 [&](auto X) {
1742 using XTy = decltype(X);
1743 alignas(XTy) uint8_t W[sizeof(X)];
1744 size_t N = std::min(E - I, sizeof(W));
1745 std::memset(W, 0, sizeof(W));
1746 std::memcpy(W, &BitmapBytes[I], N);
1747 I += N;
1750 },
1751 Bitmap, Bitmap);
1752 assert(I == E);
1753
1754 return success();
1755}
1756
1759
1760 Error E = Index->getRecords(Data);
1761 if (E)
1762 return error(std::move(E));
1763
1764 Record = Data[RecordIndex++];
1765 if (RecordIndex >= Data.size()) {
1766 Index->advanceToNextKey();
1767 RecordIndex = 0;
1768 }
1769 return success();
1770}
1771
1773 std::vector<llvm::object::BuildID> &BinaryIds) {
1774 return readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer, BinaryIds,
1776}
1777
1779 std::vector<llvm::object::BuildID> BinaryIds;
1780 if (Error E = readBinaryIds(BinaryIds))
1781 return E;
1782 printBinaryIdsInternal(OS, BinaryIds);
1783 return Error::success();
1784}
1785
1787 uint64_t NumFuncs = 0;
1788 for (const auto &Func : *this) {
1789 if (isIRLevelProfile()) {
1790 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1791 if (FuncIsCS != IsCS)
1792 continue;
1793 }
1794 Func.accumulateCounts(Sum);
1795 ++NumFuncs;
1796 }
1797 Sum.NumEntries = NumFuncs;
1798}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Provides ErrorOr<T> smart pointer.
InstrProfLookupTrait::offset_type offset_type
static Error initializeReader(InstrProfReader &Reader)
#define READ_NUM(Str, Dst)
#define CHECK_LINE_END(Line)
static Error readBinaryIdsInternal(const MemoryBuffer &DataBuffer, ArrayRef< uint8_t > BinaryIdsBuffer, std::vector< llvm::object::BuildID > &BinaryIds, const llvm::endianness Endian)
Read a list of binary ids from a profile that consist of a.
#define VP_READ_ADVANCE(Val)
InstrProfLookupTrait::data_type data_type
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static Expected< memprof::MemProfRecord > getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, MemProfFrameHashTable &MemProfFrameTable, MemProfCallStackHashTable &MemProfCallStackTable)
static void printBinaryIdsInternal(raw_ostream &OS, ArrayRef< llvm::object::BuildID > BinaryIds)
#define GET_VERSION(V)
#define VARIANT_MASK_CSIR_PROF
#define VARIANT_MASK_MEMPROF
#define VARIANT_MASK_TEMPORAL_PROF
#define VARIANT_MASK_IR_PROF
#define VARIANT_MASK_BYTE_COVERAGE
#define VARIANT_MASK_INSTR_ENTRY
#define VARIANT_MASK_FUNCTION_ENTRY_ONLY
#define VARIANT_MASK_INSTR_LOOP_ENTRIES
#define I(x, y, z)
Definition MD5.cpp:57
static constexpr StringLiteral Filename
static StringRef getName(Value *V)
const char * Msg
This file contains some functions that are useful when dealing with strings.
#define error(X)
Defines the virtual file system interface vfs::FileSystem.
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
const T * data() const
Definition ArrayRef.h:138
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
Definition BitVector.h:355
BitVector & set()
Set all bits in the bitvector.
Definition BitVector.h:366
iterator_range< const_set_bits_iterator > set_bits() const
Definition BitVector.h:159
static BitVector & apply(F &&f, BitVector &Out, BitVector const &Arg, ArgTys const &...Args)
Definition BitVector.h:594
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
Reader for the indexed binary instrprof format.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
Error readHeader() override
Read the file header.
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
Error getFunctionBitmap(StringRef FuncName, uint64_t FuncHash, BitVector &Bitmap)
Fill Bitmap with the profile data for the given function name.
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
static bool hasFormat(const MemoryBuffer &DataBuffer)
Return true if the given buffer is in an indexed instrprof format.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Expected< NamedInstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
LLVM_ABI memprof::AllMemProfData getAllMemProfData() const
LLVM_ABI Expected< memprof::MemProfRecord > getMemProfRecord(const uint64_t FuncNameHash) const
LLVM_ABI DenseMap< uint64_t, SmallVector< memprof::CallEdgeTy, 0 > > getMemProfCallerCalleePairs() const
InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template pointer type so that the Pro...
const RawInstrProf::ProfileData< IntPtrT > * getDataPointer() const
Return a pointer to the underlying ProfileData vector that this class constructs.
size_t getDataSize() const
Return the number of ProfileData elements.
InstrProfCorrelator - A base class used to create raw instrumentation data to their functions.
const char * getNamesPointer() const
Return a pointer to the names string that this class constructs.
ProfCorrelatorKind
Indicate if we should use the debug info or profile metadata sections to correlate.
LLVM_ABI std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static LLVM_ABI llvm::Expected< std::unique_ptr< InstrProfCorrelator > > get(StringRef Filename, ProfCorrelatorKind FileKind, const object::BuildIDFetcher *BIDFetcher=nullptr, const ArrayRef< llvm::object::BuildID > BIs={})
size_t getNamesSize() const
Return the number of bytes in the names string.
static std::pair< instrprof_error, std::string > take(Error E)
Consume an Error and return the raw enum value contained within it, and the optional error message.
Definition InstrProf.h:484
LLVM_ABI data_type ReadData(StringRef K, const unsigned char *D, offset_type N)
LLVM_ABI bool readValueProfilingData(const unsigned char *&D, const unsigned char *const End)
LLVM_ABI hash_value_type ComputeHash(StringRef K)
ArrayRef< NamedInstrProfRecord > data_type
InstrProfKind getProfileKind() const override
Error getRecords(ArrayRef< NamedInstrProfRecord > &Data) override
InstrProfReaderIndex(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, IndexedInstrProf::HashT HashType, uint64_t Version)
bool atEnd() const override
A remapper that applies remappings based on a symbol remapping file.
static StringRef extractName(StringRef Name)
Extract the original function name from a PGO function name.
InstrProfReaderItaniumRemapper(std::unique_ptr< MemoryBuffer > RemapBuffer, InstrProfReaderIndex< HashTableImpl > &Underlying)
static void reconstituteName(StringRef OrigName, StringRef ExtractedName, StringRef Replacement, SmallVectorImpl< char > &Out)
Given a mangled name extracted from a PGO function name, and a new form for that mangled name,...
Error getRecords(StringRef FuncName, ArrayRef< NamedInstrProfRecord > &Data) override
Name matcher supporting fuzzy matching of symbol names to names in profiles.
Base class and interface for reading profiling data of any known instrprof format.
std::unique_ptr< InstrProfSymtab > Symtab
Error success()
Clear the current error and return a successful one.
SmallVector< TemporalProfTraceTy > TemporalProfTraces
A list of temporal profile traces.
uint64_t TemporalProfTraceStreamSize
The total number of temporal profile traces seen.
virtual bool isIRLevelProfile() const =0
virtual Error readHeader()=0
Read the header. Required before reading first record.
LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS)
Compute the sum of counts and return in Sum.
static LLVM_ABI Expected< std::unique_ptr< InstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const InstrProfCorrelator *Correlator=nullptr, const object::BuildIDFetcher *BIDFetcher=nullptr, const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind=InstrProfCorrelator::ProfCorrelatorKind::NONE, std::function< void(Error)> Warn=nullptr)
Factory method to create an appropriately typed reader for the given instrprof file.
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Definition InstrProf.h:519
static bool isExternalSymbol(const StringRef &Symbol)
True if Symbol is the value used to represent external symbols.
Definition InstrProf.h:722
void mapAddress(uint64_t Addr, uint64_t MD5Val)
Map a function address to its name's MD5 hash.
Definition InstrProf.h:689
LLVM_ABI Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
void mapVTableAddress(uint64_t StartAddr, uint64_t EndAddr, uint64_t MD5Val)
Map the address range (i.e., [start_address, end_address)) of a variable to its names' MD5 hash.
Definition InstrProf.h:696
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
const char * getBufferEnd() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
static LLVM_ABI const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Reader for the raw instrprof binary format from runtime.
Error readHeader() override
Read the header. Required before reading first record.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
static bool hasFormat(const MemoryBuffer &DataBuffer)
InstrProfKind getProfileKind() const override
Returns a BitsetEnum describing the attributes of the raw instr profile.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
SmallVector< TemporalProfTraceTy > & getTemporalProfTraces(std::optional< uint64_t > Weight={}) override
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator insert(iterator I, T &&Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
iterator begin() const
Definition StringRef.h:114
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
iterator end() const
Definition StringRef.h:116
Reader for symbol remapping files.
Reader for the simple text based instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if the given buffer is in text instrprof format.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Error readHeader() override
Read the header.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
BuildIDFetcher searches local cache directories for debug info.
Definition BuildID.h:41
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
The virtual file system interface.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
Definition InstrProf.h:1360
uint64_t ComputeHash(StringRef K)
Definition InstrProf.h:1241
const uint64_t Magic
Definition InstrProf.h:1194
uint64_t getMagic()
const uint64_t Version
Definition InstrProf.h:1383
constexpr uint64_t MaximumSupportedVersion
Definition MemProf.h:53
constexpr uint64_t MinimumSupportedVersion
Definition MemProf.h:52
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
Definition BuildID.h:27
value_type byte_swap(value_type value, endianness endian)
Swap the bytes of value to match the given endianness.
Definition Endian.h:45
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition Endian.h:53
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
Definition Endian.h:67
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Definition STLExtras.h:2116
RawInstrProfReader< uint64_t > RawInstrProfReader64
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
RelativeUniformCounterPtr ValuesPtrExpr NumBitmapBytes
Definition InstrProf.h:101
RelativeUniformCounterPtr ValuesPtrExpr NumValueSites[IPVK_Last+1]
Definition InstrProf.h:95
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Definition bit.h:102
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:990
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersDelta
Definition InstrProf.h:210
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2134
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersStart
Definition InstrProf.h:179
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
FuncHash
Definition InstrProf.h:78
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
OnDiskIterableChainedHashTable< memprof::CallStackLookupTrait > MemProfCallStackHashTable
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition MathExtras.h:494
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
OnDiskIterableChainedHashTable< memprof::FrameLookupTrait > MemProfFrameHashTable
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr CountersStart
Definition InstrProf.h:167
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2012
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr NamesStart
Definition InstrProf.h:161
constexpr char GlobalIdentifierDelimiter
Definition GlobalValue.h:47
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
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:107
std::vector< ProfileSummaryEntry > SummaryEntryVector
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
InstrProfKind
An enum describing the attributes of an instrumented profile.
Definition InstrProf.h:385
RawInstrProfReader< uint32_t > RawInstrProfReader32
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
LLVM_ABI size_t size() const
static LLVM_ABI Expected< Header > readFromBuffer(const unsigned char *Buffer)
uint64_t Cutoff
The required percentile of total execution count.
Definition InstrProf.h:1284
uint64_t NumBlocks
Number of blocks >= the minumum execution count.
Definition InstrProf.h:1287
uint64_t MinBlockCount
The minimum execution count for this percentile.
Definition InstrProf.h:1286
static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries)
Definition InstrProf.h:1320
Profiling information for a single function.
Definition InstrProf.h:908
static bool hasCSFlagInHash(uint64_t FuncHash)
Definition InstrProf.h:1127
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.
Definition InstrProf.h:443
YamlDataAccessProfData YamlifiedDataAccessProfiles
Definition MemProfYAML.h:41
std::vector< GUIDMemProfRecordPair > HeapProfileRecords
Definition MemProfYAML.h:40
std::optional< CallStackId > LastUnmappedId
The data access profiles for a symbol.
std::optional< FrameId > LastUnmappedId
LLVM_ABI MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const
Definition MemProf.cpp:323
std::vector< memprof::DataAccessProfRecord > Records
Definition MemProfYAML.h:28
std::vector< uint64_t > KnownColdStrHashes
Definition MemProfYAML.h:29
std::vector< std::string > KnownColdSymbols
Definition MemProfYAML.h:30