blob: 74e921e10c47b9a42a60420b6c9318d262c643b8 [file] [log] [blame]
Yi Kong878f9942023-12-13 12:55:04 +09001//===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
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 instrumentation
10// based PGO and coverage.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
15#define LLVM_PROFILEDATA_INSTRPROFREADER_H
16
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/IR/ProfileSummary.h"
20#include "llvm/Object/BuildID.h"
21#include "llvm/ProfileData/InstrProf.h"
22#include "llvm/ProfileData/InstrProfCorrelator.h"
23#include "llvm/ProfileData/MemProf.h"
24#include "llvm/Support/Endian.h"
25#include "llvm/Support/Error.h"
26#include "llvm/Support/LineIterator.h"
27#include "llvm/Support/MathExtras.h"
28#include "llvm/Support/MemoryBuffer.h"
29#include "llvm/Support/OnDiskHashTable.h"
30#include "llvm/Support/SwapByteOrder.h"
31#include <algorithm>
32#include <cassert>
33#include <cstddef>
34#include <cstdint>
35#include <iterator>
36#include <memory>
37#include <utility>
38#include <vector>
39
40namespace llvm {
41
42class InstrProfReader;
43
44namespace vfs {
45class FileSystem;
46} // namespace vfs
47
48/// A file format agnostic iterator over profiling data.
49template <class record_type = NamedInstrProfRecord,
50 class reader_type = InstrProfReader>
51class InstrProfIterator {
52public:
53 using iterator_category = std::input_iterator_tag;
54 using value_type = record_type;
55 using difference_type = std::ptrdiff_t;
56 using pointer = value_type *;
57 using reference = value_type &;
58
59private:
60 reader_type *Reader = nullptr;
61 value_type Record;
62
63 void increment() {
64 if (Error E = Reader->readNextRecord(Record)) {
65 // Handle errors in the reader.
66 InstrProfError::take(std::move(E));
67 *this = InstrProfIterator();
68 }
69 }
70
71public:
72 InstrProfIterator() = default;
73 InstrProfIterator(reader_type *Reader) : Reader(Reader) { increment(); }
74
75 InstrProfIterator &operator++() {
76 increment();
77 return *this;
78 }
79 bool operator==(const InstrProfIterator &RHS) const {
80 return Reader == RHS.Reader;
81 }
82 bool operator!=(const InstrProfIterator &RHS) const {
83 return Reader != RHS.Reader;
84 }
85 value_type &operator*() { return Record; }
86 value_type *operator->() { return &Record; }
87};
88
89/// Base class and interface for reading profiling data of any known instrprof
90/// format. Provides an iterator over NamedInstrProfRecords.
91class InstrProfReader {
92 instrprof_error LastError = instrprof_error::success;
93 std::string LastErrorMsg;
94
95public:
96 InstrProfReader() = default;
97 virtual ~InstrProfReader() = default;
98
99 /// Read the header. Required before reading first record.
100 virtual Error readHeader() = 0;
101
102 /// Read a single record.
103 virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
104
105 /// Read a list of binary ids.
106 virtual Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) {
107 return success();
108 }
109
110 /// Print binary ids.
111 virtual Error printBinaryIds(raw_ostream &OS) { return success(); };
112
113 /// Iterator over profile data.
114 InstrProfIterator<> begin() { return InstrProfIterator<>(this); }
115 InstrProfIterator<> end() { return InstrProfIterator<>(); }
116
117 /// Return the profile version.
118 virtual uint64_t getVersion() const = 0;
119
120 virtual bool isIRLevelProfile() const = 0;
121
122 virtual bool hasCSIRLevelProfile() const = 0;
123
124 virtual bool instrEntryBBEnabled() const = 0;
125
126 /// Return true if we must provide debug info to create PGO profiles.
127 virtual bool useDebugInfoCorrelate() const { return false; }
128
129 /// Return true if the profile has single byte counters representing coverage.
130 virtual bool hasSingleByteCoverage() const = 0;
131
132 /// Return true if the profile only instruments function entries.
133 virtual bool functionEntryOnly() const = 0;
134
135 /// Return true if profile includes a memory profile.
136 virtual bool hasMemoryProfile() const = 0;
137
138 /// Return true if this has a temporal profile.
139 virtual bool hasTemporalProfile() const = 0;
140
141 /// Returns a BitsetEnum describing the attributes of the profile. To check
142 /// individual attributes prefer using the helpers above.
143 virtual InstrProfKind getProfileKind() const = 0;
144
145 /// Return the PGO symtab. There are three different readers:
146 /// Raw, Text, and Indexed profile readers. The first two types
147 /// of readers are used only by llvm-profdata tool, while the indexed
148 /// profile reader is also used by llvm-cov tool and the compiler (
149 /// backend or frontend). Since creating PGO symtab can create
150 /// significant runtime and memory overhead (as it touches data
151 /// for the whole program), InstrProfSymtab for the indexed profile
152 /// reader should be created on demand and it is recommended to be
153 /// only used for dumping purpose with llvm-proftool, not with the
154 /// compiler.
155 virtual InstrProfSymtab &getSymtab() = 0;
156
157 /// Compute the sum of counts and return in Sum.
158 void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
159
160protected:
161 std::unique_ptr<InstrProfSymtab> Symtab;
162 /// A list of temporal profile traces.
163 SmallVector<TemporalProfTraceTy> TemporalProfTraces;
164 /// The total number of temporal profile traces seen.
165 uint64_t TemporalProfTraceStreamSize = 0;
166
167 /// Set the current error and return same.
168 Error error(instrprof_error Err, const std::string &ErrMsg = "") {
169 LastError = Err;
170 LastErrorMsg = ErrMsg;
171 if (Err == instrprof_error::success)
172 return Error::success();
173 return make_error<InstrProfError>(Err, ErrMsg);
174 }
175
176 Error error(Error &&E) {
177 handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
178 LastError = IPE.get();
179 LastErrorMsg = IPE.getMessage();
180 });
181 return make_error<InstrProfError>(LastError, LastErrorMsg);
182 }
183
184 /// Clear the current error and return a successful one.
185 Error success() { return error(instrprof_error::success); }
186
187public:
188 /// Return true if the reader has finished reading the profile data.
189 bool isEOF() { return LastError == instrprof_error::eof; }
190
191 /// Return true if the reader encountered an error reading profiling data.
192 bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
193
194 /// Get the current error.
195 Error getError() {
196 if (hasError())
197 return make_error<InstrProfError>(LastError, LastErrorMsg);
198 return Error::success();
199 }
200
201 /// Factory method to create an appropriately typed reader for the given
202 /// instrprof file.
203 static Expected<std::unique_ptr<InstrProfReader>>
204 create(const Twine &Path, vfs::FileSystem &FS,
205 const InstrProfCorrelator *Correlator = nullptr);
206
207 static Expected<std::unique_ptr<InstrProfReader>>
208 create(std::unique_ptr<MemoryBuffer> Buffer,
209 const InstrProfCorrelator *Correlator = nullptr);
210
211 /// \param Weight for raw profiles use this as the temporal profile trace
212 /// weight
213 /// \returns a list of temporal profile traces.
214 virtual SmallVector<TemporalProfTraceTy> &
215 getTemporalProfTraces(std::optional<uint64_t> Weight = {}) {
216 // For non-raw profiles we ignore the input weight and instead use the
217 // weights already in the traces.
218 return TemporalProfTraces;
219 }
220 /// \returns the total number of temporal profile traces seen.
221 uint64_t getTemporalProfTraceStreamSize() {
222 return TemporalProfTraceStreamSize;
223 }
224};
225
226/// Reader for the simple text based instrprof format.
227///
228/// This format is a simple text format that's suitable for test data. Records
229/// are separated by one or more blank lines, and record fields are separated by
230/// new lines.
231///
232/// Each record consists of a function name, a function hash, a number of
233/// counters, and then each counter value, in that order.
234class TextInstrProfReader : public InstrProfReader {
235private:
236 /// The profile data file contents.
237 std::unique_ptr<MemoryBuffer> DataBuffer;
238 /// Iterator over the profile data.
239 line_iterator Line;
240 /// The attributes of the current profile.
241 InstrProfKind ProfileKind = InstrProfKind::Unknown;
242
243 Error readValueProfileData(InstrProfRecord &Record);
244
245 Error readTemporalProfTraceData();
246
247public:
248 TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
249 : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
250 TextInstrProfReader(const TextInstrProfReader &) = delete;
251 TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
252
253 /// Return true if the given buffer is in text instrprof format.
254 static bool hasFormat(const MemoryBuffer &Buffer);
255
256 // Text format does not have version, so return 0.
257 uint64_t getVersion() const override { return 0; }
258
259 bool isIRLevelProfile() const override {
260 return static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation);
261 }
262
263 bool hasCSIRLevelProfile() const override {
264 return static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive);
265 }
266
267 bool instrEntryBBEnabled() const override {
268 return static_cast<bool>(ProfileKind &
269 InstrProfKind::FunctionEntryInstrumentation);
270 }
271
272 bool hasSingleByteCoverage() const override {
273 return static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage);
274 }
275
276 bool functionEntryOnly() const override {
277 return static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly);
278 }
279
280 bool hasMemoryProfile() const override {
281 // TODO: Add support for text format memory profiles.
282 return false;
283 }
284
285 bool hasTemporalProfile() const override {
286 return static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile);
287 }
288
289 InstrProfKind getProfileKind() const override { return ProfileKind; }
290
291 /// Read the header.
292 Error readHeader() override;
293
294 /// Read a single record.
295 Error readNextRecord(NamedInstrProfRecord &Record) override;
296
297 InstrProfSymtab &getSymtab() override {
298 assert(Symtab);
299 return *Symtab;
300 }
301};
302
303/// Reader for the raw instrprof binary format from runtime.
304///
305/// This format is a raw memory dump of the instrumentation-based profiling data
306/// from the runtime. It has no index.
307///
308/// Templated on the unsigned type whose size matches pointers on the platform
309/// that wrote the profile.
310template <class IntPtrT>
311class RawInstrProfReader : public InstrProfReader {
312private:
313 /// The profile data file contents.
314 std::unique_ptr<MemoryBuffer> DataBuffer;
315 /// If available, this hold the ProfileData array used to correlate raw
316 /// instrumentation data to their functions.
317 const InstrProfCorrelatorImpl<IntPtrT> *Correlator;
318 /// A list of timestamps paired with a function name reference.
319 std::vector<std::pair<uint64_t, uint64_t>> TemporalProfTimestamps;
320 bool ShouldSwapBytes;
321 // The value of the version field of the raw profile data header. The lower 56
322 // bits specifies the format version and the most significant 8 bits specify
323 // the variant types of the profile.
324 uint64_t Version;
325 uint64_t CountersDelta;
326 uint64_t NamesDelta;
327 const RawInstrProf::ProfileData<IntPtrT> *Data;
328 const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
329 const char *CountersStart;
330 const char *CountersEnd;
331 const char *NamesStart;
332 const char *NamesEnd;
333 // After value profile is all read, this pointer points to
334 // the header of next profile data (if exists)
335 const uint8_t *ValueDataStart;
336 uint32_t ValueKindLast;
337 uint32_t CurValueDataSize;
338
339 /// Total size of binary ids.
340 uint64_t BinaryIdsSize{0};
341 /// Start address of binary id length and data pairs.
342 const uint8_t *BinaryIdsStart;
343
344public:
345 RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer,
346 const InstrProfCorrelator *Correlator)
347 : DataBuffer(std::move(DataBuffer)),
348 Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>(
349 Correlator)) {}
350 RawInstrProfReader(const RawInstrProfReader &) = delete;
351 RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
352
353 static bool hasFormat(const MemoryBuffer &DataBuffer);
354 Error readHeader() override;
355 Error readNextRecord(NamedInstrProfRecord &Record) override;
356 Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override;
357 Error printBinaryIds(raw_ostream &OS) override;
358
359 uint64_t getVersion() const override { return Version; }
360
361 bool isIRLevelProfile() const override {
362 return (Version & VARIANT_MASK_IR_PROF) != 0;
363 }
364
365 bool hasCSIRLevelProfile() const override {
366 return (Version & VARIANT_MASK_CSIR_PROF) != 0;
367 }
368
369 bool instrEntryBBEnabled() const override {
370 return (Version & VARIANT_MASK_INSTR_ENTRY) != 0;
371 }
372
373 bool useDebugInfoCorrelate() const override {
374 return (Version & VARIANT_MASK_DBG_CORRELATE) != 0;
375 }
376
377 bool hasSingleByteCoverage() const override {
378 return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
379 }
380
381 bool functionEntryOnly() const override {
382 return (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
383 }
384
385 bool hasMemoryProfile() const override {
386 // Memory profiles have a separate raw format, so this should never be set.
387 assert(!(Version & VARIANT_MASK_MEMPROF));
388 return false;
389 }
390
391 bool hasTemporalProfile() const override {
392 return (Version & VARIANT_MASK_TEMPORAL_PROF) != 0;
393 }
394
395 /// Returns a BitsetEnum describing the attributes of the raw instr profile.
396 InstrProfKind getProfileKind() const override;
397
398 InstrProfSymtab &getSymtab() override {
399 assert(Symtab.get());
400 return *Symtab.get();
401 }
402
403 SmallVector<TemporalProfTraceTy> &
404 getTemporalProfTraces(std::optional<uint64_t> Weight = {}) override;
405
406private:
407 Error createSymtab(InstrProfSymtab &Symtab);
408 Error readNextHeader(const char *CurrentPos);
409 Error readHeader(const RawInstrProf::Header &Header);
410
411 template <class IntT> IntT swap(IntT Int) const {
412 return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
413 }
414
415 support::endianness getDataEndianness() const {
416 support::endianness HostEndian = getHostEndianness();
417 if (!ShouldSwapBytes)
418 return HostEndian;
419 if (HostEndian == support::little)
420 return support::big;
421 else
422 return support::little;
423 }
424
425 inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
426 return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
427 }
428
429 Error readName(NamedInstrProfRecord &Record);
430 Error readFuncHash(NamedInstrProfRecord &Record);
431 Error readRawCounts(InstrProfRecord &Record);
432 Error readValueProfilingData(InstrProfRecord &Record);
433 bool atEnd() const { return Data == DataEnd; }
434
435 void advanceData() {
436 // `CountersDelta` is a constant zero when using debug info correlation.
437 if (!Correlator) {
438 // The initial CountersDelta is the in-memory address difference between
439 // the data and counts sections:
440 // start(__llvm_prf_cnts) - start(__llvm_prf_data)
441 // As we advance to the next record, we maintain the correct CountersDelta
442 // with respect to the next record.
443 CountersDelta -= sizeof(*Data);
444 }
445 Data++;
446 ValueDataStart += CurValueDataSize;
447 }
448
449 const char *getNextHeaderPos() const {
450 assert(atEnd());
451 return (const char *)ValueDataStart;
452 }
453
454 StringRef getName(uint64_t NameRef) const {
455 return Symtab->getFuncName(swap(NameRef));
456 }
457
458 int getCounterTypeSize() const {
459 return hasSingleByteCoverage() ? sizeof(uint8_t) : sizeof(uint64_t);
460 }
461};
462
463using RawInstrProfReader32 = RawInstrProfReader<uint32_t>;
464using RawInstrProfReader64 = RawInstrProfReader<uint64_t>;
465
466namespace IndexedInstrProf {
467
468enum class HashT : uint32_t;
469
470} // end namespace IndexedInstrProf
471
472/// Trait for lookups into the on-disk hash table for the binary instrprof
473/// format.
474class InstrProfLookupTrait {
475 std::vector<NamedInstrProfRecord> DataBuffer;
476 IndexedInstrProf::HashT HashType;
477 unsigned FormatVersion;
478 // Endianness of the input value profile data.
479 // It should be LE by default, but can be changed
480 // for testing purpose.
481 support::endianness ValueProfDataEndianness = support::little;
482
483public:
484 InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
485 : HashType(HashType), FormatVersion(FormatVersion) {}
486
487 using data_type = ArrayRef<NamedInstrProfRecord>;
488
489 using internal_key_type = StringRef;
490 using external_key_type = StringRef;
491 using hash_value_type = uint64_t;
492 using offset_type = uint64_t;
493
494 static bool EqualKey(StringRef A, StringRef B) { return A == B; }
495 static StringRef GetInternalKey(StringRef K) { return K; }
496 static StringRef GetExternalKey(StringRef K) { return K; }
497
498 hash_value_type ComputeHash(StringRef K);
499
500 static std::pair<offset_type, offset_type>
501 ReadKeyDataLength(const unsigned char *&D) {
502 using namespace support;
503
504 offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
505 offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
506 return std::make_pair(KeyLen, DataLen);
507 }
508
509 StringRef ReadKey(const unsigned char *D, offset_type N) {
510 return StringRef((const char *)D, N);
511 }
512
513 bool readValueProfilingData(const unsigned char *&D,
514 const unsigned char *const End);
515 data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
516
517 // Used for testing purpose only.
518 void setValueProfDataEndianness(support::endianness Endianness) {
519 ValueProfDataEndianness = Endianness;
520 }
521};
522
523struct InstrProfReaderIndexBase {
524 virtual ~InstrProfReaderIndexBase() = default;
525
526 // Read all the profile records with the same key pointed to the current
527 // iterator.
528 virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
529
530 // Read all the profile records with the key equal to FuncName
531 virtual Error getRecords(StringRef FuncName,
532 ArrayRef<NamedInstrProfRecord> &Data) = 0;
533 virtual void advanceToNextKey() = 0;
534 virtual bool atEnd() const = 0;
535 virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
536 virtual uint64_t getVersion() const = 0;
537 virtual bool isIRLevelProfile() const = 0;
538 virtual bool hasCSIRLevelProfile() const = 0;
539 virtual bool instrEntryBBEnabled() const = 0;
540 virtual bool hasSingleByteCoverage() const = 0;
541 virtual bool functionEntryOnly() const = 0;
542 virtual bool hasMemoryProfile() const = 0;
543 virtual bool hasTemporalProfile() const = 0;
544 virtual InstrProfKind getProfileKind() const = 0;
545 virtual Error populateSymtab(InstrProfSymtab &) = 0;
546};
547
548using OnDiskHashTableImplV3 =
549 OnDiskIterableChainedHashTable<InstrProfLookupTrait>;
550
551using MemProfRecordHashTable =
552 OnDiskIterableChainedHashTable<memprof::RecordLookupTrait>;
553using MemProfFrameHashTable =
554 OnDiskIterableChainedHashTable<memprof::FrameLookupTrait>;
555
556template <typename HashTableImpl>
557class InstrProfReaderItaniumRemapper;
558
559template <typename HashTableImpl>
560class InstrProfReaderIndex : public InstrProfReaderIndexBase {
561private:
562 std::unique_ptr<HashTableImpl> HashTable;
563 typename HashTableImpl::data_iterator RecordIterator;
564 uint64_t FormatVersion;
565
566 friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
567
568public:
569 InstrProfReaderIndex(const unsigned char *Buckets,
570 const unsigned char *const Payload,
571 const unsigned char *const Base,
572 IndexedInstrProf::HashT HashType, uint64_t Version);
573 ~InstrProfReaderIndex() override = default;
574
575 Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
576 Error getRecords(StringRef FuncName,
577 ArrayRef<NamedInstrProfRecord> &Data) override;
578 void advanceToNextKey() override { RecordIterator++; }
579
580 bool atEnd() const override {
581 return RecordIterator == HashTable->data_end();
582 }
583
584 void setValueProfDataEndianness(support::endianness Endianness) override {
585 HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
586 }
587
588 uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
589
590 bool isIRLevelProfile() const override {
591 return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
592 }
593
594 bool hasCSIRLevelProfile() const override {
595 return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
596 }
597
598 bool instrEntryBBEnabled() const override {
599 return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0;
600 }
601
602 bool hasSingleByteCoverage() const override {
603 return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0;
604 }
605
606 bool functionEntryOnly() const override {
607 return (FormatVersion & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0;
608 }
609
610 bool hasMemoryProfile() const override {
611 return (FormatVersion & VARIANT_MASK_MEMPROF) != 0;
612 }
613
614 bool hasTemporalProfile() const override {
615 return (FormatVersion & VARIANT_MASK_TEMPORAL_PROF) != 0;
616 }
617
618 InstrProfKind getProfileKind() const override;
619
620 Error populateSymtab(InstrProfSymtab &Symtab) override {
621 return Symtab.create(HashTable->keys());
622 }
623};
624
625/// Name matcher supporting fuzzy matching of symbol names to names in profiles.
626class InstrProfReaderRemapper {
627public:
628 virtual ~InstrProfReaderRemapper() = default;
629 virtual Error populateRemappings() { return Error::success(); }
630 virtual Error getRecords(StringRef FuncName,
631 ArrayRef<NamedInstrProfRecord> &Data) = 0;
632};
633
634/// Reader for the indexed binary instrprof format.
635class IndexedInstrProfReader : public InstrProfReader {
636private:
637 /// The profile data file contents.
638 std::unique_ptr<MemoryBuffer> DataBuffer;
639 /// The profile remapping file contents.
640 std::unique_ptr<MemoryBuffer> RemappingBuffer;
641 /// The index into the profile data.
642 std::unique_ptr<InstrProfReaderIndexBase> Index;
643 /// The profile remapping file contents.
644 std::unique_ptr<InstrProfReaderRemapper> Remapper;
645 /// Profile summary data.
646 std::unique_ptr<ProfileSummary> Summary;
647 /// Context sensitive profile summary data.
648 std::unique_ptr<ProfileSummary> CS_Summary;
649 /// MemProf profile schema (if available).
650 memprof::MemProfSchema Schema;
651 /// MemProf record profile data on-disk indexed via llvm::md5(FunctionName).
652 std::unique_ptr<MemProfRecordHashTable> MemProfRecordTable;
653 /// MemProf frame profile data on-disk indexed via frame id.
654 std::unique_ptr<MemProfFrameHashTable> MemProfFrameTable;
655 /// Total size of binary ids.
656 uint64_t BinaryIdsSize{0};
657 /// Start address of binary id length and data pairs.
658 const uint8_t *BinaryIdsStart = nullptr;
659
660 // Index to the current record in the record array.
661 unsigned RecordIndex;
662
663 // Read the profile summary. Return a pointer pointing to one byte past the
664 // end of the summary data if it exists or the input \c Cur.
665 // \c UseCS indicates whether to use the context-sensitive profile summary.
666 const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
667 const unsigned char *Cur, bool UseCS);
668
669public:
670 IndexedInstrProfReader(
671 std::unique_ptr<MemoryBuffer> DataBuffer,
672 std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
673 : DataBuffer(std::move(DataBuffer)),
674 RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
675 IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
676 IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
677
678 /// Return the profile version.
679 uint64_t getVersion() const override { return Index->getVersion(); }
680 bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
681 bool hasCSIRLevelProfile() const override {
682 return Index->hasCSIRLevelProfile();
683 }
684
685 bool instrEntryBBEnabled() const override {
686 return Index->instrEntryBBEnabled();
687 }
688
689 bool hasSingleByteCoverage() const override {
690 return Index->hasSingleByteCoverage();
691 }
692
693 bool functionEntryOnly() const override { return Index->functionEntryOnly(); }
694
695 bool hasMemoryProfile() const override { return Index->hasMemoryProfile(); }
696
697 bool hasTemporalProfile() const override {
698 return Index->hasTemporalProfile();
699 }
700
701 /// Returns a BitsetEnum describing the attributes of the indexed instr
702 /// profile.
703 InstrProfKind getProfileKind() const override {
704 return Index->getProfileKind();
705 }
706
707 /// Return true if the given buffer is in an indexed instrprof format.
708 static bool hasFormat(const MemoryBuffer &DataBuffer);
709
710 /// Read the file header.
711 Error readHeader() override;
712 /// Read a single record.
713 Error readNextRecord(NamedInstrProfRecord &Record) override;
714
715 /// Return the NamedInstrProfRecord associated with FuncName and FuncHash.
716 /// When return a hash_mismatch error and MismatchedFuncSum is not nullptr,
717 /// the sum of all counters in the mismatched function will be set to
718 /// MismatchedFuncSum. If there are multiple instances of mismatched
719 /// functions, MismatchedFuncSum returns the maximum. If \c FuncName is not
720 /// found, try to lookup \c DeprecatedFuncName to handle profiles built by
721 /// older compilers.
722 Expected<InstrProfRecord>
723 getInstrProfRecord(StringRef FuncName, uint64_t FuncHash,
724 StringRef DeprecatedFuncName = "",
725 uint64_t *MismatchedFuncSum = nullptr);
726
727 /// Return the memprof record for the function identified by
728 /// llvm::md5(Name).
729 Expected<memprof::MemProfRecord> getMemProfRecord(uint64_t FuncNameHash);
730
731 /// Fill Counts with the profile data for the given function name.
732 Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
733 std::vector<uint64_t> &Counts);
734
735 /// Return the maximum of all known function counts.
736 /// \c UseCS indicates whether to use the context-sensitive count.
737 uint64_t getMaximumFunctionCount(bool UseCS) {
738 if (UseCS) {
739 assert(CS_Summary && "No context sensitive profile summary");
740 return CS_Summary->getMaxFunctionCount();
741 } else {
742 assert(Summary && "No profile summary");
743 return Summary->getMaxFunctionCount();
744 }
745 }
746
747 /// Factory method to create an indexed reader.
748 static Expected<std::unique_ptr<IndexedInstrProfReader>>
749 create(const Twine &Path, vfs::FileSystem &FS,
750 const Twine &RemappingPath = "");
751
752 static Expected<std::unique_ptr<IndexedInstrProfReader>>
753 create(std::unique_ptr<MemoryBuffer> Buffer,
754 std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
755
756 // Used for testing purpose only.
757 void setValueProfDataEndianness(support::endianness Endianness) {
758 Index->setValueProfDataEndianness(Endianness);
759 }
760
761 // See description in the base class. This interface is designed
762 // to be used by llvm-profdata (for dumping). Avoid using this when
763 // the client is the compiler.
764 InstrProfSymtab &getSymtab() override;
765
766 /// Return the profile summary.
767 /// \c UseCS indicates whether to use the context-sensitive summary.
768 ProfileSummary &getSummary(bool UseCS) {
769 if (UseCS) {
770 assert(CS_Summary && "No context sensitive summary");
771 return *CS_Summary;
772 } else {
773 assert(Summary && "No profile summary");
774 return *Summary;
775 }
776 }
777
778 Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override;
779 Error printBinaryIds(raw_ostream &OS) override;
780};
781
782} // end namespace llvm
783
784#endif // LLVM_PROFILEDATA_INSTRPROFREADER_H