LLVM 20.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"
24#include "llvm/Support/Endian.h"
25#include "llvm/Support/Error.h"
30#include <algorithm>
31#include <cstddef>
32#include <cstdint>
33#include <limits>
34#include <memory>
35#include <optional>
36#include <system_error>
37#include <utility>
38#include <vector>
39
40using namespace llvm;
41
42// Extracts the variant information from the top 32 bits in the version and
43// returns an enum specifying the variants present.
45 InstrProfKind ProfileKind = InstrProfKind::Unknown;
46 if (Version & VARIANT_MASK_IR_PROF) {
47 ProfileKind |= InstrProfKind::IRInstrumentation;
48 }
49 if (Version & VARIANT_MASK_CSIR_PROF) {
50 ProfileKind |= InstrProfKind::ContextSensitive;
51 }
52 if (Version & VARIANT_MASK_INSTR_ENTRY) {
53 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
54 }
55 if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) {
56 ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
57 }
58 if (Version & VARIANT_MASK_BYTE_COVERAGE) {
59 ProfileKind |= InstrProfKind::SingleByteCoverage;
60 }
61 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
62 ProfileKind |= InstrProfKind::FunctionEntryOnly;
63 }
64 if (Version & VARIANT_MASK_MEMPROF) {
65 ProfileKind |= InstrProfKind::MemProf;
66 }
67 if (Version & VARIANT_MASK_TEMPORAL_PROF) {
68 ProfileKind |= InstrProfKind::TemporalProfile;
69 }
70 return ProfileKind;
71}
72
75 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
76 : FS.getBufferForFile(Filename);
77 if (std::error_code EC = BufferOrErr.getError())
78 return errorCodeToError(EC);
79 return std::move(BufferOrErr.get());
80}
81
83 return Reader.readHeader();
84}
85
86/// Read a list of binary ids from a profile that consist of
87/// a. uint64_t binary id length
88/// b. uint8_t binary id data
89/// c. uint8_t padding (if necessary)
90/// This function is shared between raw and indexed profiles.
91/// Raw profiles are in host-endian format, and indexed profiles are in
92/// little-endian format. So, this function takes an argument indicating the
93/// associated endian format to read the binary ids correctly.
94static Error
96 ArrayRef<uint8_t> BinaryIdsBuffer,
97 std::vector<llvm::object::BuildID> &BinaryIds,
98 const llvm::endianness Endian) {
99 using namespace support;
100
101 const uint64_t BinaryIdsSize = BinaryIdsBuffer.size();
102 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.data();
103
104 if (BinaryIdsSize == 0)
105 return Error::success();
106
107 const uint8_t *BI = BinaryIdsStart;
108 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
109 const uint8_t *End =
110 reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
111
112 while (BI < BIEnd) {
113 size_t Remaining = BIEnd - BI;
114 // There should be enough left to read the binary id length.
115 if (Remaining < sizeof(uint64_t))
116 return make_error<InstrProfError>(
117 instrprof_error::malformed,
118 "not enough data to read binary id length");
119
120 uint64_t BILen = endian::readNext<uint64_t>(BI, Endian);
121 if (BILen == 0)
122 return make_error<InstrProfError>(instrprof_error::malformed,
123 "binary id length is 0");
124
125 Remaining = BIEnd - BI;
126 // There should be enough left to read the binary id data.
127 if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
128 return make_error<InstrProfError>(
129 instrprof_error::malformed, "not enough data to read binary id data");
130
131 // Add binary id to the binary ids list.
132 BinaryIds.push_back(object::BuildID(BI, BI + BILen));
133
134 // Increment by binary id data length, which aligned to the size of uint64.
135 BI += alignToPowerOf2(BILen, sizeof(uint64_t));
136 if (BI > End)
137 return make_error<InstrProfError>(
138 instrprof_error::malformed,
139 "binary id section is greater than buffer size");
140 }
141
142 return Error::success();
143}
144
147 OS << "Binary IDs: \n";
148 for (const auto &BI : BinaryIds) {
149 for (auto I : BI)
150 OS << format("%02x", I);
151 OS << "\n";
152 }
153}
154
156 const Twine &Path, vfs::FileSystem &FS,
157 const InstrProfCorrelator *Correlator,
158 const object::BuildIDFetcher *BIDFetcher,
159 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
160 std::function<void(Error)> Warn) {
161 // Set up the buffer to read.
162 auto BufferOrError = setupMemoryBuffer(Path, FS);
163 if (Error E = BufferOrError.takeError())
164 return std::move(E);
165 return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
166 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
167}
168
170 std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
171 const object::BuildIDFetcher *BIDFetcher,
172 const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
173 std::function<void(Error)> Warn) {
174 if (Buffer->getBufferSize() == 0)
175 return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
176
177 std::unique_ptr<InstrProfReader> Result;
178 // Create the reader.
180 Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
181 else if (RawInstrProfReader64::hasFormat(*Buffer))
182 Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator,
183 BIDFetcher, BIDFetcherCorrelatorKind,
184 Warn));
185 else if (RawInstrProfReader32::hasFormat(*Buffer))
186 Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator,
187 BIDFetcher, BIDFetcherCorrelatorKind,
188 Warn));
189 else if (TextInstrProfReader::hasFormat(*Buffer))
190 Result.reset(new TextInstrProfReader(std::move(Buffer)));
191 else
192 return make_error<InstrProfError>(instrprof_error::unrecognized_format);
193
194 // Initialize the reader and return the result.
195 if (Error E = initializeReader(*Result))
196 return std::move(E);
197
198 return std::move(Result);
199}
200
203 const Twine &RemappingPath) {
204 // Set up the buffer to read.
205 auto BufferOrError = setupMemoryBuffer(Path, FS);
206 if (Error E = BufferOrError.takeError())
207 return std::move(E);
208
209 // Set up the remapping buffer if requested.
210 std::unique_ptr<MemoryBuffer> RemappingBuffer;
211 std::string RemappingPathStr = RemappingPath.str();
212 if (!RemappingPathStr.empty()) {
213 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
214 if (Error E = RemappingBufferOrError.takeError())
215 return std::move(E);
216 RemappingBuffer = std::move(RemappingBufferOrError.get());
217 }
218
219 return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
220 std::move(RemappingBuffer));
221}
222
224IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
225 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
226 // Create the reader.
228 return make_error<InstrProfError>(instrprof_error::bad_magic);
229 auto Result = std::make_unique<IndexedInstrProfReader>(
230 std::move(Buffer), std::move(RemappingBuffer));
231
232 // Initialize the reader and return the result.
233 if (Error E = initializeReader(*Result))
234 return std::move(E);
235
236 return std::move(Result);
237}
238
240 // Verify that this really looks like plain ASCII text by checking a
241 // 'reasonable' number of characters (up to profile magic size).
242 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
243 StringRef buffer = Buffer.getBufferStart();
244 return count == 0 ||
245 std::all_of(buffer.begin(), buffer.begin() + count,
246 [](char c) { return isPrint(c) || isSpace(c); });
247}
248
249// Read the profile variant flag from the header: ":FE" means this is a FE
250// generated profile. ":IR" means this is an IR level profile. Other strings
251// with a leading ':' will be reported an error format.
253 Symtab.reset(new InstrProfSymtab());
254
255 while (Line->starts_with(":")) {
256 StringRef Str = Line->substr(1);
257 if (Str.equals_insensitive("ir"))
259 else if (Str.equals_insensitive("fe"))
261 else if (Str.equals_insensitive("csir")) {
263 ProfileKind |= InstrProfKind::ContextSensitive;
264 } else if (Str.equals_insensitive("entry_first"))
266 else if (Str.equals_insensitive("not_entry_first"))
268 else if (Str.equals_insensitive("instrument_loop_entries"))
270 else if (Str.equals_insensitive("single_byte_coverage"))
272 else if (Str.equals_insensitive("temporal_prof_traces")) {
273 ProfileKind |= InstrProfKind::TemporalProfile;
274 if (auto Err = readTemporalProfTraceData())
275 return error(std::move(Err));
276 } else
278 ++Line;
279 }
280 return success();
281}
282
283/// Temporal profile trace data is stored in the header immediately after
284/// ":temporal_prof_traces". The first integer is the number of traces, the
285/// second integer is the stream size, then the following lines are the actual
286/// traces which consist of a weight and a comma separated list of function
287/// names.
288Error TextInstrProfReader::readTemporalProfTraceData() {
289 if ((++Line).is_at_end())
291
292 uint32_t NumTraces;
293 if (Line->getAsInteger(0, NumTraces))
295
296 if ((++Line).is_at_end())
298
301
302 for (uint32_t i = 0; i < NumTraces; i++) {
303 if ((++Line).is_at_end())
305
307 if (Line->getAsInteger(0, Trace.Weight))
309
310 if ((++Line).is_at_end())
312
313 SmallVector<StringRef> FuncNames;
314 Line->split(FuncNames, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
315 for (auto &FuncName : FuncNames)
316 Trace.FunctionNameRefs.push_back(
317 IndexedInstrProf::ComputeHash(FuncName.trim()));
318 TemporalProfTraces.push_back(std::move(Trace));
319 }
320 return success();
321}
322
323Error
324TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
325
326#define CHECK_LINE_END(Line) \
327 if (Line.is_at_end()) \
328 return error(instrprof_error::truncated);
329#define READ_NUM(Str, Dst) \
330 if ((Str).getAsInteger(10, (Dst))) \
331 return error(instrprof_error::malformed);
332#define VP_READ_ADVANCE(Val) \
333 CHECK_LINE_END(Line); \
334 uint32_t Val; \
335 READ_NUM((*Line), (Val)); \
336 Line++;
337
338 if (Line.is_at_end())
339 return success();
340
341 uint32_t NumValueKinds;
342 if (Line->getAsInteger(10, NumValueKinds)) {
343 // No value profile data
344 return success();
345 }
346 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
348 "number of value kinds is invalid");
349 Line++;
350
351 for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
352 VP_READ_ADVANCE(ValueKind);
353 if (ValueKind > IPVK_Last)
354 return error(instrprof_error::malformed, "value kind is invalid");
355 ;
356 VP_READ_ADVANCE(NumValueSites);
357 if (!NumValueSites)
358 continue;
359
360 Record.reserveSites(VK, NumValueSites);
361 for (uint32_t S = 0; S < NumValueSites; S++) {
362 VP_READ_ADVANCE(NumValueData);
363
364 std::vector<InstrProfValueData> CurrentValues;
365 for (uint32_t V = 0; V < NumValueData; V++) {
366 CHECK_LINE_END(Line);
367 std::pair<StringRef, StringRef> VD = Line->rsplit(':');
368 uint64_t TakenCount, Value;
369 if (ValueKind == IPVK_IndirectCallTarget) {
370 if (InstrProfSymtab::isExternalSymbol(VD.first)) {
371 Value = 0;
372 } else {
373 if (Error E = Symtab->addFuncName(VD.first))
374 return E;
376 }
377 } else if (ValueKind == IPVK_VTableTarget) {
379 Value = 0;
380 else {
381 if (Error E = Symtab->addVTableName(VD.first))
382 return E;
384 }
385 } else {
386 READ_NUM(VD.first, Value);
387 }
388 READ_NUM(VD.second, TakenCount);
389 CurrentValues.push_back({Value, TakenCount});
390 Line++;
391 }
392 assert(CurrentValues.size() == NumValueData);
393 Record.addValueData(ValueKind, S, CurrentValues, nullptr);
394 }
395 }
396 return success();
397
398#undef CHECK_LINE_END
399#undef READ_NUM
400#undef VP_READ_ADVANCE
401}
402
404 // Skip empty lines and comments.
405 while (!Line.is_at_end() && (Line->empty() || Line->starts_with("#")))
406 ++Line;
407 // If we hit EOF while looking for a name, we're done.
408 if (Line.is_at_end()) {
410 }
411
412 // Read the function name.
413 Record.Name = *Line++;
414 if (Error E = Symtab->addFuncName(Record.Name))
415 return error(std::move(E));
416
417 // Read the function hash.
418 if (Line.is_at_end())
420 if ((Line++)->getAsInteger(0, Record.Hash))
422 "function hash is not a valid integer");
423
424 // Read the number of counters.
425 uint64_t NumCounters;
426 if (Line.is_at_end())
428 if ((Line++)->getAsInteger(10, NumCounters))
430 "number of counters is not a valid integer");
431 if (NumCounters == 0)
432 return error(instrprof_error::malformed, "number of counters is zero");
433
434 // Read each counter and fill our internal storage with the values.
435 Record.Clear();
436 Record.Counts.reserve(NumCounters);
437 for (uint64_t I = 0; I < NumCounters; ++I) {
438 if (Line.is_at_end())
440 uint64_t Count;
441 if ((Line++)->getAsInteger(10, Count))
442 return error(instrprof_error::malformed, "count is invalid");
443 Record.Counts.push_back(Count);
444 }
445
446 // Bitmap byte information is indicated with special character.
447 if (Line->starts_with("$")) {
448 Record.BitmapBytes.clear();
449 // Read the number of bitmap bytes.
450 uint64_t NumBitmapBytes;
451 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
453 "number of bitmap bytes is not a valid integer");
454 if (NumBitmapBytes != 0) {
455 // Read each bitmap and fill our internal storage with the values.
456 Record.BitmapBytes.reserve(NumBitmapBytes);
457 for (uint8_t I = 0; I < NumBitmapBytes; ++I) {
458 if (Line.is_at_end())
460 uint8_t BitmapByte;
461 if ((Line++)->getAsInteger(0, BitmapByte))
463 "bitmap byte is not a valid integer");
464 Record.BitmapBytes.push_back(BitmapByte);
465 }
466 }
467 }
468
469 // Check if value profile data exists and read it if so.
470 if (Error E = readValueProfileData(Record))
471 return error(std::move(E));
472
473 return success();
474}
475
476template <class IntPtrT>
479}
480
481template <class IntPtrT>
484 std::optional<uint64_t> Weight) {
485 if (TemporalProfTimestamps.empty()) {
486 assert(TemporalProfTraces.empty());
487 return TemporalProfTraces;
488 }
489 // Sort functions by their timestamps to build the trace.
490 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
492 if (Weight)
493 Trace.Weight = *Weight;
494 for (auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
495 Trace.FunctionNameRefs.push_back(NameRef);
496 TemporalProfTraces = {std::move(Trace)};
497 return TemporalProfTraces;
498}
499
500template <class IntPtrT>
502 if (DataBuffer.getBufferSize() < sizeof(uint64_t))
503 return false;
504 uint64_t Magic =
505 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
506 return RawInstrProf::getMagic<IntPtrT>() == Magic ||
507 llvm::byteswap(RawInstrProf::getMagic<IntPtrT>()) == Magic;
508}
509
510template <class IntPtrT>
512 if (!hasFormat(*DataBuffer))
514 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
516 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
517 DataBuffer->getBufferStart());
518 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
519 return readHeader(*Header);
520}
521
522template <class IntPtrT>
524 const char *End = DataBuffer->getBufferEnd();
525 // Skip zero padding between profiles.
526 while (CurrentPos != End && *CurrentPos == 0)
527 ++CurrentPos;
528 // If there's nothing left, we're done.
529 if (CurrentPos == End)
530 return make_error<InstrProfError>(instrprof_error::eof);
531 // If there isn't enough space for another header, this is probably just
532 // garbage at the end of the file.
533 if (CurrentPos + sizeof(RawInstrProf::Header) > End)
534 return make_error<InstrProfError>(instrprof_error::malformed,
535 "not enough space for another header");
536 // The writer ensures each profile is padded to start at an aligned address.
537 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
538 return make_error<InstrProfError>(instrprof_error::malformed,
539 "insufficient padding");
540 // The magic should have the same byte order as in the previous header.
541 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
542 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
543 return make_error<InstrProfError>(instrprof_error::bad_magic);
544
545 // There's another profile to read, so we need to process the header.
546 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
547 return readHeader(*Header);
548}
549
550template <class IntPtrT>
552 if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
553 StringRef(VNamesStart, VNamesEnd - VNamesStart)))
554 return error(std::move(E));
555 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
556 const IntPtrT FPtr = swap(I->FunctionPointer);
557 if (!FPtr)
558 continue;
559 Symtab.mapAddress(FPtr, swap(I->NameRef));
560 }
561
562 if (VTableBegin != nullptr && VTableEnd != nullptr) {
563 for (const RawInstrProf::VTableProfileData<IntPtrT> *I = VTableBegin;
564 I != VTableEnd; ++I) {
565 const IntPtrT VPtr = swap(I->VTablePointer);
566 if (!VPtr)
567 continue;
568 // Map both begin and end address to the name hash, since the instrumented
569 // address could be somewhere in the middle.
570 // VPtr is of type uint32_t or uint64_t so 'VPtr + I->VTableSize' marks
571 // the end of vtable address.
572 Symtab.mapVTableAddress(VPtr, VPtr + swap(I->VTableSize),
573 swap(I->VTableNameHash));
574 }
575 }
576 return success();
577}
578
579template <class IntPtrT>
581 const RawInstrProf::Header &Header) {
582 Version = swap(Header.Version);
583 if (GET_VERSION(Version) != RawInstrProf::Version)
585 ("Profile uses raw profile format version = " +
586 Twine(GET_VERSION(Version)) +
587 "; expected version = " + Twine(RawInstrProf::Version) +
588 "\nPLEASE update this tool to version in the raw profile, or "
589 "regenerate raw profile with expected version.")
590 .str());
591
592 uint64_t BinaryIdSize = swap(Header.BinaryIdsSize);
593 // Binary id start just after the header if exists.
594 const uint8_t *BinaryIdStart =
595 reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
596 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
597 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
598 if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd)
600 ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize);
601 if (!BinaryIdsBuffer.empty()) {
602 if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer,
603 BinaryIds, getDataEndianness()))
604 return Err;
605 }
606
607 CountersDelta = swap(Header.CountersDelta);
608 BitmapDelta = swap(Header.BitmapDelta);
609 NamesDelta = swap(Header.NamesDelta);
610 auto NumData = swap(Header.NumData);
611 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
612 auto CountersSize = swap(Header.NumCounters) * getCounterTypeSize();
613 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
614 auto NumBitmapBytes = swap(Header.NumBitmapBytes);
615 auto PaddingBytesAfterBitmapBytes = swap(Header.PaddingBytesAfterBitmapBytes);
616 auto NamesSize = swap(Header.NamesSize);
617 auto VTableNameSize = swap(Header.VNamesSize);
618 auto NumVTables = swap(Header.NumVTables);
619 ValueKindLast = swap(Header.ValueKindLast);
620
621 auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
622 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
623 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
624
625 auto VTableSectionSize =
626 NumVTables * sizeof(RawInstrProf::VTableProfileData<IntPtrT>);
627 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
628
629 // Profile data starts after profile header and binary ids if exist.
630 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdSize;
631 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
632 ptrdiff_t BitmapOffset =
633 CountersOffset + CountersSize + PaddingBytesAfterCounters;
634 ptrdiff_t NamesOffset =
635 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
636 ptrdiff_t VTableProfDataOffset =
637 NamesOffset + NamesSize + PaddingBytesAfterNames;
638 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
639 PaddingBytesAfterVTableProfData;
640 ptrdiff_t ValueDataOffset =
641 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
642
643 auto *Start = reinterpret_cast<const char *>(&Header);
644 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
646
647 if (BIDFetcher) {
648 std::vector<object::BuildID> BinaryIDs;
649 if (Error E = readBinaryIds(BinaryIDs))
650 return E;
651 if (auto E = InstrProfCorrelator::get("", BIDFetcherCorrelatorKind,
652 BIDFetcher, BinaryIDs)
653 .moveInto(BIDFetcherCorrelator)) {
654 return E;
655 }
656 if (auto Err = BIDFetcherCorrelator->correlateProfileData(0))
657 return Err;
658 }
659
660 if (Correlator) {
661 // These sizes in the raw file are zero because we constructed them in the
662 // Correlator.
663 if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
664 NamesDelta == 0))
666 Data = Correlator->getDataPointer();
667 DataEnd = Data + Correlator->getDataSize();
668 NamesStart = Correlator->getNamesPointer();
669 NamesEnd = NamesStart + Correlator->getNamesSize();
670 } else if (BIDFetcherCorrelator) {
671 InstrProfCorrelatorImpl<IntPtrT> *BIDFetcherCorrelatorImpl =
672 dyn_cast_or_null<InstrProfCorrelatorImpl<IntPtrT>>(
673 BIDFetcherCorrelator.get());
674 Data = BIDFetcherCorrelatorImpl->getDataPointer();
675 DataEnd = Data + BIDFetcherCorrelatorImpl->getDataSize();
676 NamesStart = BIDFetcherCorrelatorImpl->getNamesPointer();
677 NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->getNamesSize();
678 } else {
679 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
680 Start + DataOffset);
681 DataEnd = Data + NumData;
682 VTableBegin =
683 reinterpret_cast<const RawInstrProf::VTableProfileData<IntPtrT> *>(
684 Start + VTableProfDataOffset);
685 VTableEnd = VTableBegin + NumVTables;
686 NamesStart = Start + NamesOffset;
687 NamesEnd = NamesStart + NamesSize;
688 VNamesStart = Start + VTableNameOffset;
689 VNamesEnd = VNamesStart + VTableNameSize;
690 }
691
692 CountersStart = Start + CountersOffset;
693 CountersEnd = CountersStart + CountersSize;
694 BitmapStart = Start + BitmapOffset;
695 BitmapEnd = BitmapStart + NumBitmapBytes;
696 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
697
698 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
699 if (Error E = createSymtab(*NewSymtab))
700 return E;
701
702 Symtab = std::move(NewSymtab);
703 return success();
704}
705
706template <class IntPtrT>
708 Record.Name = getName(Data->NameRef);
709 return success();
710}
711
712template <class IntPtrT>
714 Record.Hash = swap(Data->FuncHash);
715 return success();
716}
717
718template <class IntPtrT>
721 uint32_t NumCounters = swap(Data->NumCounters);
722 if (NumCounters == 0)
723 return error(instrprof_error::malformed, "number of counters is zero");
724
725 ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
726 if (CounterBaseOffset < 0)
727 return error(
729 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
730
731 if (CounterBaseOffset >= CountersEnd - CountersStart)
733 ("counter offset " + Twine(CounterBaseOffset) +
734 " is greater than the maximum counter offset " +
735 Twine(CountersEnd - CountersStart - 1))
736 .str());
737
738 uint64_t MaxNumCounters =
739 (CountersEnd - (CountersStart + CounterBaseOffset)) /
740 getCounterTypeSize();
741 if (NumCounters > MaxNumCounters)
743 ("number of counters " + Twine(NumCounters) +
744 " is greater than the maximum number of counters " +
745 Twine(MaxNumCounters))
746 .str());
747
748 Record.Counts.clear();
749 Record.Counts.reserve(NumCounters);
750 for (uint32_t I = 0; I < NumCounters; I++) {
751 const char *Ptr =
752 CountersStart + CounterBaseOffset + I * getCounterTypeSize();
753 if (I == 0 && hasTemporalProfile()) {
754 uint64_t TimestampValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
755 if (TimestampValue != 0 &&
756 TimestampValue != std::numeric_limits<uint64_t>::max()) {
757 TemporalProfTimestamps.emplace_back(TimestampValue,
758 swap(Data->NameRef));
759 TemporalProfTraceStreamSize = 1;
760 }
761 if (hasSingleByteCoverage()) {
762 // In coverage mode, getCounterTypeSize() returns 1 byte but our
763 // timestamp field has size uint64_t. Increment I so that the next
764 // iteration of this for loop points to the byte after the timestamp
765 // field, i.e., I += 8.
766 I += 7;
767 }
768 continue;
769 }
770 if (hasSingleByteCoverage()) {
771 // A value of zero signifies the block is covered.
772 Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
773 } else {
774 uint64_t CounterValue = swap(*reinterpret_cast<const uint64_t *>(Ptr));
775 if (CounterValue > MaxCounterValue && Warn)
776 Warn(make_error<InstrProfError>(
778
779 Record.Counts.push_back(CounterValue);
780 }
781 }
782
783 return success();
784}
785
786template <class IntPtrT>
788 uint32_t NumBitmapBytes = swap(Data->NumBitmapBytes);
789
790 Record.BitmapBytes.clear();
791 Record.BitmapBytes.reserve(NumBitmapBytes);
792
793 // It's possible MCDC is either not enabled or only used for some functions
794 // and not others. So if we record 0 bytes, just move on.
795 if (NumBitmapBytes == 0)
796 return success();
797
798 // BitmapDelta decreases as we advance to the next data record.
799 ptrdiff_t BitmapOffset = swap(Data->BitmapPtr) - BitmapDelta;
800 if (BitmapOffset < 0)
801 return error(
803 ("bitmap offset " + Twine(BitmapOffset) + " is negative").str());
804
805 if (BitmapOffset >= BitmapEnd - BitmapStart)
807 ("bitmap offset " + Twine(BitmapOffset) +
808 " is greater than the maximum bitmap offset " +
809 Twine(BitmapEnd - BitmapStart - 1))
810 .str());
811
812 uint64_t MaxNumBitmapBytes =
813 (BitmapEnd - (BitmapStart + BitmapOffset)) / sizeof(uint8_t);
814 if (NumBitmapBytes > MaxNumBitmapBytes)
816 ("number of bitmap bytes " + Twine(NumBitmapBytes) +
817 " is greater than the maximum number of bitmap bytes " +
818 Twine(MaxNumBitmapBytes))
819 .str());
820
821 for (uint32_t I = 0; I < NumBitmapBytes; I++) {
822 const char *Ptr = BitmapStart + BitmapOffset + I;
823 Record.BitmapBytes.push_back(swap(*Ptr));
824 }
825
826 return success();
827}
828
829template <class IntPtrT>
832 Record.clearValueData();
833 CurValueDataSize = 0;
834 // Need to match the logic in value profile dumper code in compiler-rt:
835 uint32_t NumValueKinds = 0;
836 for (uint32_t I = 0; I < IPVK_Last + 1; I++)
837 NumValueKinds += (Data->NumValueSites[I] != 0);
838
839 if (!NumValueKinds)
840 return success();
841
843 ValueProfData::getValueProfData(
844 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
845 getDataEndianness());
846
847 if (Error E = VDataPtrOrErr.takeError())
848 return E;
849
850 // Note that besides deserialization, this also performs the conversion for
851 // indirect call targets. The function pointers from the raw profile are
852 // remapped into function name hashes.
853 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
854 CurValueDataSize = VDataPtrOrErr.get()->getSize();
855 return success();
856}
857
858template <class IntPtrT>
860 // Keep reading profiles that consist of only headers and no profile data and
861 // counters.
862 while (atEnd())
863 // At this point, ValueDataStart field points to the next header.
864 if (Error E = readNextHeader(getNextHeaderPos()))
865 return error(std::move(E));
866
867 // Read name and set it in Record.
868 if (Error E = readName(Record))
869 return error(std::move(E));
870
871 // Read FuncHash and set it in Record.
872 if (Error E = readFuncHash(Record))
873 return error(std::move(E));
874
875 // Read raw counts and set Record.
876 if (Error E = readRawCounts(Record))
877 return error(std::move(E));
878
879 // Read raw bitmap bytes and set Record.
880 if (Error E = readRawBitmapBytes(Record))
881 return error(std::move(E));
882
883 // Read value data and set Record.
884 if (Error E = readValueProfilingData(Record))
885 return error(std::move(E));
886
887 // Iterate.
888 advanceData();
889 return success();
890}
891
892template <class IntPtrT>
894 std::vector<llvm::object::BuildID> &BinaryIds) {
895 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
896 this->BinaryIds.end());
897 return Error::success();
898}
899
900template <class IntPtrT>
902 if (!BinaryIds.empty())
903 printBinaryIdsInternal(OS, BinaryIds);
904 return Error::success();
905}
906
907namespace llvm {
908
909template class RawInstrProfReader<uint32_t>;
910template class RawInstrProfReader<uint64_t>;
911
912} // end namespace llvm
913
916 return IndexedInstrProf::ComputeHash(HashType, K);
917}
918
921
923 const unsigned char *&D, const unsigned char *const End) {
925 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
926
927 if (VDataPtrOrErr.takeError())
928 return false;
929
930 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
931 D += VDataPtrOrErr.get()->TotalSize;
932
933 return true;
934}
935
937 offset_type N) {
938 using namespace support;
939
940 // Check if the data is corrupt. If so, don't try to read it.
941 if (N % sizeof(uint64_t))
942 return data_type();
943
944 DataBuffer.clear();
945 std::vector<uint64_t> CounterBuffer;
946 std::vector<uint8_t> BitmapByteBuffer;
947
948 const unsigned char *End = D + N;
949 while (D < End) {
950 // Read hash.
951 if (D + sizeof(uint64_t) >= End)
952 return data_type();
953 uint64_t Hash = endian::readNext<uint64_t, llvm::endianness::little>(D);
954
955 // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
956 uint64_t CountsSize = N / sizeof(uint64_t) - 1;
957 // If format version is different then read the number of counters.
958 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
959 if (D + sizeof(uint64_t) > End)
960 return data_type();
961 CountsSize = endian::readNext<uint64_t, llvm::endianness::little>(D);
962 }
963 // Read counter values.
964 if (D + CountsSize * sizeof(uint64_t) > End)
965 return data_type();
966
967 CounterBuffer.clear();
968 CounterBuffer.reserve(CountsSize);
969 for (uint64_t J = 0; J < CountsSize; ++J)
970 CounterBuffer.push_back(
971 endian::readNext<uint64_t, llvm::endianness::little>(D));
972
973 // Read bitmap bytes for GET_VERSION(FormatVersion) > 10.
974 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version10) {
975 uint64_t BitmapBytes = 0;
976 if (D + sizeof(uint64_t) > End)
977 return data_type();
978 BitmapBytes = endian::readNext<uint64_t, llvm::endianness::little>(D);
979 // Read bitmap byte values.
980 if (D + BitmapBytes * sizeof(uint8_t) > End)
981 return data_type();
982 BitmapByteBuffer.clear();
983 BitmapByteBuffer.reserve(BitmapBytes);
984 for (uint64_t J = 0; J < BitmapBytes; ++J)
985 BitmapByteBuffer.push_back(static_cast<uint8_t>(
986 endian::readNext<uint64_t, llvm::endianness::little>(D)));
987 }
988
989 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
990 std::move(BitmapByteBuffer));
991
992 // Read value profiling data.
993 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
995 DataBuffer.clear();
996 return data_type();
997 }
998 }
999 return DataBuffer;
1000}
1001
1002template <typename HashTableImpl>
1005 auto Iter = HashTable->find(FuncName);
1006 if (Iter == HashTable->end())
1007 return make_error<InstrProfError>(instrprof_error::unknown_function);
1008
1009 Data = (*Iter);
1010 if (Data.empty())
1011 return make_error<InstrProfError>(instrprof_error::malformed,
1012 "profile data is empty");
1013
1014 return Error::success();
1015}
1016
1017template <typename HashTableImpl>
1020 if (atEnd())
1021 return make_error<InstrProfError>(instrprof_error::eof);
1022
1023 Data = *RecordIterator;
1024
1025 if (Data.empty())
1026 return make_error<InstrProfError>(instrprof_error::malformed,
1027 "profile data is empty");
1028
1029 return Error::success();
1030}
1031
1032template <typename HashTableImpl>
1034 const unsigned char *Buckets, const unsigned char *const Payload,
1035 const unsigned char *const Base, IndexedInstrProf::HashT HashType,
1036 uint64_t Version) {
1037 FormatVersion = Version;
1038 HashTable.reset(HashTableImpl::Create(
1039 Buckets, Payload, Base,
1040 typename HashTableImpl::InfoType(HashType, Version)));
1041 RecordIterator = HashTable->data_begin();
1042}
1043
1044template <typename HashTableImpl>
1046 return getProfileKindFromVersion(FormatVersion);
1047}
1048
1049namespace {
1050/// A remapper that does not apply any remappings.
1051class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
1052 InstrProfReaderIndexBase &Underlying;
1053
1054public:
1055 InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
1056 : Underlying(Underlying) {}
1057
1058 Error getRecords(StringRef FuncName,
1059 ArrayRef<NamedInstrProfRecord> &Data) override {
1060 return Underlying.getRecords(FuncName, Data);
1061 }
1062};
1063} // namespace
1064
1065/// A remapper that applies remappings based on a symbol remapping file.
1066template <typename HashTableImpl>
1068 : public InstrProfReaderRemapper {
1069public:
1071 std::unique_ptr<MemoryBuffer> RemapBuffer,
1073 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
1074 }
1075
1076 /// Extract the original function name from a PGO function name.
1078 // We can have multiple pieces separated by kGlobalIdentifierDelimiter (
1079 // semicolon now and colon in older profiles); there can be pieces both
1080 // before and after the mangled name. Find the first part that starts with
1081 // '_Z'; we'll assume that's the mangled name we want.
1082 std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
1083 while (true) {
1084 Parts = Parts.second.split(GlobalIdentifierDelimiter);
1085 if (Parts.first.starts_with("_Z"))
1086 return Parts.first;
1087 if (Parts.second.empty())
1088 return Name;
1089 }
1090 }
1091
1092 /// Given a mangled name extracted from a PGO function name, and a new
1093 /// form for that mangled name, reconstitute the name.
1094 static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
1095 StringRef Replacement,
1096 SmallVectorImpl<char> &Out) {
1097 Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
1098 Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
1099 Out.insert(Out.end(), Replacement.begin(), Replacement.end());
1100 Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
1101 }
1102
1104 if (Error E = Remappings.read(*RemapBuffer))
1105 return E;
1106 for (StringRef Name : Underlying.HashTable->keys()) {
1107 StringRef RealName = extractName(Name);
1108 if (auto Key = Remappings.insert(RealName)) {
1109 // FIXME: We could theoretically map the same equivalence class to
1110 // multiple names in the profile data. If that happens, we should
1111 // return NamedInstrProfRecords from all of them.
1112 MappedNames.insert({Key, RealName});
1113 }
1114 }
1115 return Error::success();
1116 }
1117
1120 StringRef RealName = extractName(FuncName);
1121 if (auto Key = Remappings.lookup(RealName)) {
1122 StringRef Remapped = MappedNames.lookup(Key);
1123 if (!Remapped.empty()) {
1124 if (RealName.begin() == FuncName.begin() &&
1125 RealName.end() == FuncName.end())
1126 FuncName = Remapped;
1127 else {
1128 // Try rebuilding the name from the given remapping.
1129 SmallString<256> Reconstituted;
1130 reconstituteName(FuncName, RealName, Remapped, Reconstituted);
1131 Error E = Underlying.getRecords(Reconstituted, Data);
1132 if (!E)
1133 return E;
1134
1135 // If we failed because the name doesn't exist, fall back to asking
1136 // about the original name.
1137 if (Error Unhandled = handleErrors(
1138 std::move(E), [](std::unique_ptr<InstrProfError> Err) {
1139 return Err->get() == instrprof_error::unknown_function
1140 ? Error::success()
1141 : Error(std::move(Err));
1142 }))
1143 return Unhandled;
1144 }
1145 }
1146 }
1147 return Underlying.getRecords(FuncName, Data);
1148 }
1149
1150private:
1151 /// The memory buffer containing the remapping configuration. Remappings
1152 /// holds pointers into this buffer.
1153 std::unique_ptr<MemoryBuffer> RemapBuffer;
1154
1155 /// The mangling remapper.
1156 SymbolRemappingReader Remappings;
1157
1158 /// Mapping from mangled name keys to the name used for the key in the
1159 /// profile data.
1160 /// FIXME: Can we store a location within the on-disk hash table instead of
1161 /// redoing lookup?
1163
1164 /// The real profile data reader.
1166};
1167
1169 using namespace support;
1170
1171 if (DataBuffer.getBufferSize() < 8)
1172 return false;
1173 uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
1174 DataBuffer.getBufferStart());
1175 // Verify that it's magical.
1176 return Magic == IndexedInstrProf::Magic;
1177}
1178
1179const unsigned char *
1180IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
1181 const unsigned char *Cur, bool UseCS) {
1182 using namespace IndexedInstrProf;
1183 using namespace support;
1184
1186 const IndexedInstrProf::Summary *SummaryInLE =
1187 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
1188 uint64_t NFields = endian::byte_swap<uint64_t, llvm::endianness::little>(
1189 SummaryInLE->NumSummaryFields);
1190 uint64_t NEntries = endian::byte_swap<uint64_t, llvm::endianness::little>(
1191 SummaryInLE->NumCutoffEntries);
1192 uint32_t SummarySize =
1193 IndexedInstrProf::Summary::getSize(NFields, NEntries);
1194 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1195 IndexedInstrProf::allocSummary(SummarySize);
1196
1197 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
1198 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
1199 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
1200 Dst[I] = endian::byte_swap<uint64_t, llvm::endianness::little>(Src[I]);
1201
1202 SummaryEntryVector DetailedSummary;
1203 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
1204 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
1205 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
1206 Ent.NumBlocks);
1207 }
1208 std::unique_ptr<llvm::ProfileSummary> &Summary =
1209 UseCS ? this->CS_Summary : this->Summary;
1210
1211 // initialize InstrProfSummary using the SummaryData from disk.
1212 Summary = std::make_unique<ProfileSummary>(
1214 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1215 SummaryData->get(Summary::MaxBlockCount),
1216 SummaryData->get(Summary::MaxInternalBlockCount),
1217 SummaryData->get(Summary::MaxFunctionCount),
1218 SummaryData->get(Summary::TotalNumBlocks),
1219 SummaryData->get(Summary::TotalNumFunctions));
1220 return Cur + SummarySize;
1221 } else {
1222 // The older versions do not support a profile summary. This just computes
1223 // an empty summary, which will not result in accurate hot/cold detection.
1224 // We would need to call addRecord for all NamedInstrProfRecords to get the
1225 // correct summary. However, this version is old (prior to early 2016) and
1226 // has not been supporting an accurate summary for several years.
1228 Summary = Builder.getSummary();
1229 return Cur;
1230 }
1231}
1232
1233Error IndexedMemProfReader::deserializeV2(const unsigned char *Start,
1234 const unsigned char *Ptr) {
1235 // The value returned from RecordTableGenerator.Emit.
1236 const uint64_t RecordTableOffset =
1237 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1238 // The offset in the stream right before invoking
1239 // FrameTableGenerator.Emit.
1240 const uint64_t FramePayloadOffset =
1241 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1242 // The value returned from FrameTableGenerator.Emit.
1243 const uint64_t FrameTableOffset =
1244 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1245
1246 // The offset in the stream right before invoking
1247 // CallStackTableGenerator.Emit.
1248 uint64_t CallStackPayloadOffset = 0;
1249 // The value returned from CallStackTableGenerator.Emit.
1250 uint64_t CallStackTableOffset = 0;
1251 if (Version >= memprof::Version2) {
1252 CallStackPayloadOffset =
1253 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1254 CallStackTableOffset =
1255 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1256 }
1257
1258 // Read the schema.
1259 auto SchemaOr = memprof::readMemProfSchema(Ptr);
1260 if (!SchemaOr)
1261 return SchemaOr.takeError();
1262 Schema = SchemaOr.get();
1263
1264 // Now initialize the table reader with a pointer into data buffer.
1265 MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1266 /*Buckets=*/Start + RecordTableOffset,
1267 /*Payload=*/Ptr,
1268 /*Base=*/Start, memprof::RecordLookupTrait(Version, Schema)));
1269
1270 // Initialize the frame table reader with the payload and bucket offsets.
1271 MemProfFrameTable.reset(MemProfFrameHashTable::Create(
1272 /*Buckets=*/Start + FrameTableOffset,
1273 /*Payload=*/Start + FramePayloadOffset,
1274 /*Base=*/Start));
1275
1276 if (Version >= memprof::Version2)
1277 MemProfCallStackTable.reset(MemProfCallStackHashTable::Create(
1278 /*Buckets=*/Start + CallStackTableOffset,
1279 /*Payload=*/Start + CallStackPayloadOffset,
1280 /*Base=*/Start));
1281
1282 return Error::success();
1283}
1284
1285Error IndexedMemProfReader::deserializeV3(const unsigned char *Start,
1286 const unsigned char *Ptr) {
1287 // The offset in the stream right before invoking
1288 // CallStackTableGenerator.Emit.
1289 const uint64_t CallStackPayloadOffset =
1290 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1291 // The offset in the stream right before invoking RecordTableGenerator.Emit.
1292 const uint64_t RecordPayloadOffset =
1293 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1294 // The value returned from RecordTableGenerator.Emit.
1295 const uint64_t RecordTableOffset =
1296 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1297
1298 // Read the schema.
1299 auto SchemaOr = memprof::readMemProfSchema(Ptr);
1300 if (!SchemaOr)
1301 return SchemaOr.takeError();
1302 Schema = SchemaOr.get();
1303
1304 FrameBase = Ptr;
1305 CallStackBase = Start + CallStackPayloadOffset;
1306
1307 // Compute the number of elements in the radix tree array. Since we use this
1308 // to reserve enough bits in a BitVector, it's totally OK if we overestimate
1309 // this number a little bit because of padding just before the next section.
1310 RadixTreeSize = (RecordPayloadOffset - CallStackPayloadOffset) /
1311 sizeof(memprof::LinearFrameId);
1312
1313 // Now initialize the table reader with a pointer into data buffer.
1314 MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1315 /*Buckets=*/Start + RecordTableOffset,
1316 /*Payload=*/Start + RecordPayloadOffset,
1317 /*Base=*/Start, memprof::RecordLookupTrait(memprof::Version3, Schema)));
1318
1319 return Error::success();
1320}
1321
1322Error IndexedMemProfReader::deserialize(const unsigned char *Start,
1323 uint64_t MemProfOffset) {
1324 const unsigned char *Ptr = Start + MemProfOffset;
1325
1326 // Read the MemProf version number.
1327 const uint64_t FirstWord =
1328 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1329
1330 if (FirstWord == memprof::Version2 || FirstWord == memprof::Version3) {
1331 // Everything is good. We can proceed to deserialize the rest.
1332 Version = static_cast<memprof::IndexedVersion>(FirstWord);
1333 } else {
1334 return make_error<InstrProfError>(
1336 formatv("MemProf version {} not supported; "
1337 "requires version between {} and {}, inclusive",
1340 }
1341
1342 switch (Version) {
1343 case memprof::Version2:
1344 if (Error E = deserializeV2(Start, Ptr))
1345 return E;
1346 break;
1347 case memprof::Version3:
1348 if (Error E = deserializeV3(Start, Ptr))
1349 return E;
1350 break;
1351 }
1352
1353 return Error::success();
1354}
1355
1357 using namespace support;
1358
1359 const unsigned char *Start =
1360 (const unsigned char *)DataBuffer->getBufferStart();
1361 const unsigned char *Cur = Start;
1362 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1364
1365 auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
1366 if (!HeaderOr)
1367 return HeaderOr.takeError();
1368
1369 const IndexedInstrProf::Header *Header = &HeaderOr.get();
1370 Cur += Header->size();
1371
1372 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1373 /* UseCS */ false);
1374 if (Header->Version & VARIANT_MASK_CSIR_PROF)
1375 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur,
1376 /* UseCS */ true);
1377 // Read the hash type and start offset.
1378 IndexedInstrProf::HashT HashType =
1379 static_cast<IndexedInstrProf::HashT>(Header->HashType);
1380 if (HashType > IndexedInstrProf::HashT::Last)
1382
1383 // The hash table with profile counts comes next.
1384 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1385 Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1386
1387 // The MemProfOffset field in the header is only valid when the format
1388 // version is higher than 8 (when it was introduced).
1389 if (Header->getIndexedProfileVersion() >= 8 &&
1390 Header->Version & VARIANT_MASK_MEMPROF) {
1391 if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset))
1392 return E;
1393 }
1394
1395 // BinaryIdOffset field in the header is only valid when the format version
1396 // is higher than 9 (when it was introduced).
1397 if (Header->getIndexedProfileVersion() >= 9) {
1398 const unsigned char *Ptr = Start + Header->BinaryIdOffset;
1399 // Read binary ids size.
1400 uint64_t BinaryIdsSize =
1401 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1402 if (BinaryIdsSize % sizeof(uint64_t))
1404 // Set the binary ids start.
1405 BinaryIdsBuffer = ArrayRef<uint8_t>(Ptr, BinaryIdsSize);
1406 if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd())
1407 return make_error<InstrProfError>(instrprof_error::malformed,
1408 "corrupted binary ids");
1409 }
1410
1411 if (Header->getIndexedProfileVersion() >= 12) {
1412 const unsigned char *Ptr = Start + Header->VTableNamesOffset;
1413
1414 uint64_t CompressedVTableNamesLen =
1415 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1416
1417 // Writer first writes the length of compressed string, and then the actual
1418 // content.
1419 const char *VTableNamePtr = (const char *)Ptr;
1420 if (VTableNamePtr > (const char *)DataBuffer->getBufferEnd())
1421 return make_error<InstrProfError>(instrprof_error::truncated);
1422
1423 VTableName = StringRef(VTableNamePtr, CompressedVTableNamesLen);
1424 }
1425
1426 if (Header->getIndexedProfileVersion() >= 10 &&
1427 Header->Version & VARIANT_MASK_TEMPORAL_PROF) {
1428 const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset;
1429 const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd();
1430 // Expect at least two 64 bit fields: NumTraces, and TraceStreamSize
1431 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1433 const uint64_t NumTraces =
1434 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1436 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1437 for (unsigned i = 0; i < NumTraces; i++) {
1438 // Expect at least two 64 bit fields: Weight and NumFunctions
1439 if (Ptr + 2 * sizeof(uint64_t) > PtrEnd)
1442 Trace.Weight =
1443 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1444 const uint64_t NumFunctions =
1445 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1446 // Expect at least NumFunctions 64 bit fields
1447 if (Ptr + NumFunctions * sizeof(uint64_t) > PtrEnd)
1449 for (unsigned j = 0; j < NumFunctions; j++) {
1450 const uint64_t NameRef =
1451 support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
1452 Trace.FunctionNameRefs.push_back(NameRef);
1453 }
1454 TemporalProfTraces.push_back(std::move(Trace));
1455 }
1456 }
1457
1458 // Load the remapping table now if requested.
1459 if (RemappingBuffer) {
1460 Remapper =
1461 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1462 std::move(RemappingBuffer), *IndexPtr);
1463 if (Error E = Remapper->populateRemappings())
1464 return E;
1465 } else {
1466 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1467 }
1468 Index = std::move(IndexPtr);
1469
1470 return success();
1471}
1472
1474 if (Symtab)
1475 return *Symtab;
1476
1477 auto NewSymtab = std::make_unique<InstrProfSymtab>();
1478
1479 if (Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1480 auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1481 consumeError(error(ErrCode, Msg));
1482 }
1483
1484 // finalizeSymtab is called inside populateSymtab.
1485 if (Error E = Index->populateSymtab(*NewSymtab)) {
1486 auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
1487 consumeError(error(ErrCode, Msg));
1488 }
1489
1490 Symtab = std::move(NewSymtab);
1491 return *Symtab;
1492}
1493
1495 StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName,
1496 uint64_t *MismatchedFuncSum) {
1498 uint64_t FuncSum = 0;
1499 auto Err = Remapper->getRecords(FuncName, Data);
1500 if (Err) {
1501 // If we don't find FuncName, try DeprecatedFuncName to handle profiles
1502 // built by older compilers.
1503 auto Err2 =
1504 handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error {
1505 if (IE.get() != instrprof_error::unknown_function)
1506 return make_error<InstrProfError>(IE);
1507 if (auto Err = Remapper->getRecords(DeprecatedFuncName, Data))
1508 return Err;
1509 return Error::success();
1510 });
1511 if (Err2)
1512 return std::move(Err2);
1513 }
1514 // Found it. Look for counters with the right hash.
1515
1516 // A flag to indicate if the records are from the same type
1517 // of profile (i.e cs vs nocs).
1518 bool CSBitMatch = false;
1519 auto getFuncSum = [](ArrayRef<uint64_t> Counts) {
1520 uint64_t ValueSum = 0;
1521 for (uint64_t CountValue : Counts) {
1522 if (CountValue == (uint64_t)-1)
1523 continue;
1524 // Handle overflow -- if that happens, return max.
1525 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1526 return std::numeric_limits<uint64_t>::max();
1527 ValueSum += CountValue;
1528 }
1529 return ValueSum;
1530 };
1531
1532 for (const NamedInstrProfRecord &I : Data) {
1533 // Check for a match and fill the vector if there is one.
1534 if (I.Hash == FuncHash)
1535 return std::move(I);
1538 CSBitMatch = true;
1539 if (MismatchedFuncSum == nullptr)
1540 continue;
1541 FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1542 }
1543 }
1544 if (CSBitMatch) {
1545 if (MismatchedFuncSum != nullptr)
1546 *MismatchedFuncSum = FuncSum;
1548 }
1550}
1551
1554 MemProfFrameHashTable &MemProfFrameTable,
1555 MemProfCallStackHashTable &MemProfCallStackTable) {
1557 MemProfFrameTable);
1558
1560 MemProfCallStackTable, FrameIdConv);
1561
1562 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1563
1564 // Check that all call stack ids were successfully converted to call stacks.
1565 if (CSIdConv.LastUnmappedId) {
1566 return make_error<InstrProfError>(
1568 "memprof call stack not found for call stack id " +
1569 Twine(*CSIdConv.LastUnmappedId));
1570 }
1571
1572 // Check that all frame ids were successfully converted to frames.
1573 if (FrameIdConv.LastUnmappedId) {
1574 return make_error<InstrProfError>(instrprof_error::hash_mismatch,
1575 "memprof frame not found for frame id " +
1576 Twine(*FrameIdConv.LastUnmappedId));
1577 }
1578
1579 return Record;
1580}
1581
1584 const unsigned char *FrameBase,
1585 const unsigned char *CallStackBase) {
1586 memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1587 memprof::LinearCallStackIdConverter CSIdConv(CallStackBase, FrameIdConv);
1588 memprof::MemProfRecord Record = IndexedRecord.toMemProfRecord(CSIdConv);
1589 return Record;
1590}
1591
1594 // TODO: Add memprof specific errors.
1595 if (MemProfRecordTable == nullptr)
1596 return make_error<InstrProfError>(instrprof_error::invalid_prof,
1597 "no memprof data available in profile");
1598 auto Iter = MemProfRecordTable->find(FuncNameHash);
1599 if (Iter == MemProfRecordTable->end())
1600 return make_error<InstrProfError>(
1602 "memprof record not found for function hash " + Twine(FuncNameHash));
1603
1604 const memprof::IndexedMemProfRecord &IndexedRecord = *Iter;
1605 switch (Version) {
1606 case memprof::Version2:
1607 assert(MemProfFrameTable && "MemProfFrameTable must be available");
1608 assert(MemProfCallStackTable && "MemProfCallStackTable must be available");
1609 return getMemProfRecordV2(IndexedRecord, *MemProfFrameTable,
1610 *MemProfCallStackTable);
1611 case memprof::Version3:
1612 assert(!MemProfFrameTable && "MemProfFrameTable must not be available");
1613 assert(!MemProfCallStackTable &&
1614 "MemProfCallStackTable must not be available");
1615 assert(FrameBase && "FrameBase must be available");
1616 assert(CallStackBase && "CallStackBase must be available");
1617 return getMemProfRecordV3(IndexedRecord, FrameBase, CallStackBase);
1618 }
1619
1620 return make_error<InstrProfError>(
1622 formatv("MemProf version {} not supported; "
1623 "requires version between {} and {}, inclusive",
1626}
1627
1630 assert(MemProfRecordTable);
1631 assert(Version == memprof::Version3);
1632
1633 memprof::LinearFrameIdConverter FrameIdConv(FrameBase);
1634 memprof::CallerCalleePairExtractor Extractor(CallStackBase, FrameIdConv,
1635 RadixTreeSize);
1636
1637 // The set of linear call stack IDs that we need to traverse from. We expect
1638 // the set to be dense, so we use a BitVector.
1639 BitVector Worklist(RadixTreeSize);
1640
1641 // Collect the set of linear call stack IDs. Since we expect a lot of
1642 // duplicates, we first collect them in the form of a bit vector before
1643 // processing them.
1644 for (const memprof::IndexedMemProfRecord &IndexedRecord :
1645 MemProfRecordTable->data()) {
1646 for (const memprof::IndexedAllocationInfo &IndexedAI :
1647 IndexedRecord.AllocSites)
1648 Worklist.set(IndexedAI.CSId);
1649 }
1650
1651 // Collect caller-callee pairs for each linear call stack ID in Worklist.
1652 for (unsigned CS : Worklist.set_bits())
1653 Extractor(CS);
1654
1656 std::move(Extractor.CallerCalleePairs);
1657
1658 // Sort each call list by the source location.
1659 for (auto &[CallerGUID, CallList] : Pairs) {
1660 llvm::sort(CallList);
1661 CallList.erase(llvm::unique(CallList), CallList.end());
1662 }
1663
1664 return Pairs;
1665}
1666
1668 memprof::AllMemProfData AllMemProfData;
1669 AllMemProfData.HeapProfileRecords.reserve(
1670 MemProfRecordTable->getNumEntries());
1671 for (uint64_t Key : MemProfRecordTable->keys()) {
1672 auto Record = getMemProfRecord(Key);
1673 if (Record.takeError())
1674 continue;
1676 Pair.GUID = Key;
1677 Pair.Record = std::move(*Record);
1678 AllMemProfData.HeapProfileRecords.push_back(std::move(Pair));
1679 }
1680 return AllMemProfData;
1681}
1682
1684 uint64_t FuncHash,
1685 std::vector<uint64_t> &Counts) {
1687 if (Error E = Record.takeError())
1688 return error(std::move(E));
1689
1690 Counts = Record.get().Counts;
1691 return success();
1692}
1693
1695 uint64_t FuncHash,
1696 BitVector &Bitmap) {
1698 if (Error E = Record.takeError())
1699 return error(std::move(E));
1700
1701 const auto &BitmapBytes = Record.get().BitmapBytes;
1702 size_t I = 0, E = BitmapBytes.size();
1703 Bitmap.resize(E * CHAR_BIT);
1705 [&](auto X) {
1706 using XTy = decltype(X);
1707 alignas(XTy) uint8_t W[sizeof(X)];
1708 size_t N = std::min(E - I, sizeof(W));
1709 std::memset(W, 0, sizeof(W));
1710 std::memcpy(W, &BitmapBytes[I], N);
1711 I += N;
1713 support::aligned>(W);
1714 },
1715 Bitmap, Bitmap);
1716 assert(I == E);
1717
1718 return success();
1719}
1720
1723
1724 Error E = Index->getRecords(Data);
1725 if (E)
1726 return error(std::move(E));
1727
1728 Record = Data[RecordIndex++];
1729 if (RecordIndex >= Data.size()) {
1730 Index->advanceToNextKey();
1731 RecordIndex = 0;
1732 }
1733 return success();
1734}
1735
1737 std::vector<llvm::object::BuildID> &BinaryIds) {
1738 return readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer, BinaryIds,
1740}
1741
1743 std::vector<llvm::object::BuildID> BinaryIds;
1744 if (Error E = readBinaryIds(BinaryIds))
1745 return E;
1746 printBinaryIdsInternal(OS, BinaryIds);
1747 return Error::success();
1748}
1749
1751 uint64_t NumFuncs = 0;
1752 for (const auto &Func : *this) {
1753 if (isIRLevelProfile()) {
1754 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1755 if (FuncIsCS != IsCS)
1756 continue;
1757 }
1758 Func.accumulateCounts(Sum);
1759 ++NumFuncs;
1760 }
1761 Sum.NumEntries = NumFuncs;
1762}
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
std::string Name
bool End
Definition: ELF_riscv.cpp:480
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Provides ErrorOr<T> smart pointer.
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
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)
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static Expected< memprof::MemProfRecord > getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, MemProfFrameHashTable &MemProfFrameTable, MemProfCallStackHashTable &MemProfCallStackTable)
static Expected< memprof::MemProfRecord > getMemProfRecordV3(const memprof::IndexedMemProfRecord &IndexedRecord, const unsigned char *FrameBase, const unsigned char *CallStackBase)
static void printBinaryIdsInternal(raw_ostream &OS, ArrayRef< llvm::object::BuildID > BinaryIds)
#define I(x, y, z)
Definition: MD5.cpp:58
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
endianness Endian
raw_pwrite_stream & OS
This file contains some functions that are useful when dealing with strings.
#define error(X)
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
const T * data() const
Definition: ArrayRef.h:165
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Definition: BitVector.h:341
BitVector & set()
Definition: BitVector.h:351
iterator_range< const_set_bits_iterator > set_bits() const
Definition: BitVector.h:140
static BitVector & apply(F &&f, BitVector &Out, BitVector const &Arg, ArgTys const &...Args)
Definition: BitVector.h:552
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
reference get()
Returns a reference to the stored T value.
Definition: Error.h:578
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.
Expected< InstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
Error deserialize(const unsigned char *Start, uint64_t MemProfOffset)
memprof::AllMemProfData getAllMemProfData() const
Expected< memprof::MemProfRecord > getMemProfRecord(const uint64_t FuncNameHash) const
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.
std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static 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:425
data_type ReadData(StringRef K, const unsigned char *D, offset_type N)
bool readValueProfilingData(const unsigned char *&D, const unsigned char *const End)
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)
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.
void accumulateCounts(CountSumOrPercent &Sum, bool IsCS)
Compute the sum of counts and return in Sum.
static 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:460
static bool isExternalSymbol(const StringRef &Symbol)
True if Symbol is the value used to represent external symbols.
Definition: InstrProf.h:651
void mapAddress(uint64_t Addr, uint64_t MD5Val)
Map a function address to its name's MD5 hash.
Definition: InstrProf.h:619
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:626
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
size_t getBufferSize() const
Definition: MemoryBuffer.h:68
const char * getBufferEnd() const
Definition: MemoryBuffer.h:67
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
Definition: MemoryBuffer.h:66
Provides lookup and iteration over an on disk hash table.
static OnDiskIterableChainedHashTable * Create(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, const Info &InfoObj=Info())
Create the hash table.
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Definition: ProfileCommon.h:70
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...
Definition: SmallVector.h:573
void reserve(size_type N)
Definition: SmallVector.h:663
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:805
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:700
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:470
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:571
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:265
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
iterator begin() const
Definition: StringRef.h:116
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
iterator end() const
Definition: StringRef.h:118
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
Definition: StringRef.h:733
Reader for symbol remapping files.
Key insert(StringRef FunctionName)
Construct a key for the given symbol, or return an existing one if an equivalent name has already bee...
Key lookup(StringRef FunctionName)
Map the given symbol name into the key for the corresponding equivalence class.
Error read(MemoryBuffer &B)
Read remappings from the given buffer, which must live as long as the remapper.
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:81
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
LLVM Value Representation.
Definition: Value.h:74
bool is_at_end() const
Return true if we're an "end" iterator or have reached EOF.
Definition: LineIterator.h:63
BuildIDFetcher searches local cache directories for debug info.
Definition: BuildID.h:39
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
The virtual file system interface.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
Definition: InstrProf.h:1243
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:1124
const uint64_t Magic
Definition: InstrProf.h:1081
const uint64_t Version
Definition: InstrProf.h:1266
constexpr uint64_t MaximumSupportedVersion
Definition: MemProf.h:40
constexpr uint64_t MinimumSupportedVersion
Definition: MemProf.h:39
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
Definition: MemProf.cpp:267
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:58
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
RawInstrProfReader< uint32_t > RawInstrProfReader32
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Definition: bit.h:101
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:954
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:2055
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition: MathExtras.h:502
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
std::vector< ProfileSummaryEntry > SummaryEntryVector
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:1938
constexpr char GlobalIdentifierDelimiter
Definition: GlobalValue.h:46
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:1873
RawInstrProfReader< uint64_t > RawInstrProfReader64
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:111
endianness
Definition: bit.h:70
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1069
InstrProfKind
An enum describing the attributes of an instrumented profile.
Definition: InstrProf.h:329
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
#define N
static Expected< Header > readFromBuffer(const unsigned char *Buffer)
Definition: InstrProf.cpp:1643
uint64_t Cutoff
The required percentile of total execution count.
Definition: InstrProf.h:1167
uint64_t NumBlocks
Number of blocks >= the minumum execution count.
Definition: InstrProf.h:1170
uint64_t MinBlockCount
The minimum execution count for this percentile.
Definition: InstrProf.h:1169
static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries)
Definition: InstrProf.h:1203
Profiling information for a single function.
Definition: InstrProf.h:836
static bool hasCSFlagInHash(uint64_t FuncHash)
Definition: InstrProf.h:1014
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.
Definition: InstrProf.h:385
std::vector< GUIDMemProfRecordPair > HeapProfileRecords
Definition: MemProfYAML.h:24
std::optional< CallStackId > LastUnmappedId
Definition: MemProf.h:803
DenseMap< uint64_t, SmallVector< CallEdgeTy, 0 > > CallerCalleePairs
Definition: MemProf.h:927
std::optional< FrameId > LastUnmappedId
Definition: MemProf.h:779
MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const
Definition: MemProf.cpp:232