1 //===- 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 40 namespace llvm { 41 42 class InstrProfReader; 43 44 namespace vfs { 45 class FileSystem; 46 } // namespace vfs 47 48 /// A file format agnostic iterator over profiling data. 49 template <class record_type = NamedInstrProfRecord, 50 class reader_type = InstrProfReader> 51 class InstrProfIterator { 52 public: 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 59 private: 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 71 public: 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. 91 class InstrProfReader { 92 instrprof_error LastError = instrprof_error::success; 93 std::string LastErrorMsg; 94 95 public: 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 160 protected: 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 187 public: 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. 234 class TextInstrProfReader : public InstrProfReader { 235 private: 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 247 public: 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. 310 template <class IntPtrT> 311 class RawInstrProfReader : public InstrProfReader { 312 private: 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 344 public: 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 406 private: 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 463 using RawInstrProfReader32 = RawInstrProfReader<uint32_t>; 464 using RawInstrProfReader64 = RawInstrProfReader<uint64_t>; 465 466 namespace IndexedInstrProf { 467 468 enum 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. 474 class 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 483 public: 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 523 struct 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 548 using OnDiskHashTableImplV3 = 549 OnDiskIterableChainedHashTable<InstrProfLookupTrait>; 550 551 using MemProfRecordHashTable = 552 OnDiskIterableChainedHashTable<memprof::RecordLookupTrait>; 553 using MemProfFrameHashTable = 554 OnDiskIterableChainedHashTable<memprof::FrameLookupTrait>; 555 556 template <typename HashTableImpl> 557 class InstrProfReaderItaniumRemapper; 558 559 template <typename HashTableImpl> 560 class InstrProfReaderIndex : public InstrProfReaderIndexBase { 561 private: 562 std::unique_ptr<HashTableImpl> HashTable; 563 typename HashTableImpl::data_iterator RecordIterator; 564 uint64_t FormatVersion; 565 566 friend class InstrProfReaderItaniumRemapper<HashTableImpl>; 567 568 public: 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. 626 class InstrProfReaderRemapper { 627 public: 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. 635 class IndexedInstrProfReader : public InstrProfReader { 636 private: 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 669 public: 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. 720 Expected<InstrProfRecord> 721 getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, 722 uint64_t *MismatchedFuncSum = nullptr); 723 724 /// Return the memprof record for the function identified by 725 /// llvm::md5(Name). 726 Expected<memprof::MemProfRecord> getMemProfRecord(uint64_t FuncNameHash); 727 728 /// Fill Counts with the profile data for the given function name. 729 Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, 730 std::vector<uint64_t> &Counts); 731 732 /// Return the maximum of all known function counts. 733 /// \c UseCS indicates whether to use the context-sensitive count. 734 uint64_t getMaximumFunctionCount(bool UseCS) { 735 if (UseCS) { 736 assert(CS_Summary && "No context sensitive profile summary"); 737 return CS_Summary->getMaxFunctionCount(); 738 } else { 739 assert(Summary && "No profile summary"); 740 return Summary->getMaxFunctionCount(); 741 } 742 } 743 744 /// Factory method to create an indexed reader. 745 static Expected<std::unique_ptr<IndexedInstrProfReader>> 746 create(const Twine &Path, vfs::FileSystem &FS, 747 const Twine &RemappingPath = ""); 748 749 static Expected<std::unique_ptr<IndexedInstrProfReader>> 750 create(std::unique_ptr<MemoryBuffer> Buffer, 751 std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr); 752 753 // Used for testing purpose only. 754 void setValueProfDataEndianness(support::endianness Endianness) { 755 Index->setValueProfDataEndianness(Endianness); 756 } 757 758 // See description in the base class. This interface is designed 759 // to be used by llvm-profdata (for dumping). Avoid using this when 760 // the client is the compiler. 761 InstrProfSymtab &getSymtab() override; 762 763 /// Return the profile summary. 764 /// \c UseCS indicates whether to use the context-sensitive summary. 765 ProfileSummary &getSummary(bool UseCS) { 766 if (UseCS) { 767 assert(CS_Summary && "No context sensitive summary"); 768 return *CS_Summary; 769 } else { 770 assert(Summary && "No profile summary"); 771 return *Summary; 772 } 773 } 774 775 Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override; 776 Error printBinaryIds(raw_ostream &OS) override; 777 }; 778 779 } // end namespace llvm 780 781 #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H 782