diff options
Diffstat (limited to 'include/llvm/ProfileData/InstrProfReader.h')
| -rw-r--r-- | include/llvm/ProfileData/InstrProfReader.h | 175 |
1 files changed, 144 insertions, 31 deletions
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index f937e7d08d54..fed3e693e7a0 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -23,6 +23,7 @@ #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" +#include "llvm/Support/raw_ostream.h" #include <iterator> namespace llvm { @@ -53,7 +54,7 @@ class InstrProfReader { std::error_code LastError; public: - InstrProfReader() : LastError(instrprof_error::success) {} + InstrProfReader() : LastError(instrprof_error::success), Symtab() {} virtual ~InstrProfReader() {} /// Read the header. Required before reading first record. @@ -64,7 +65,20 @@ public: InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } + /// Return the PGO symtab. There are three different readers: + /// Raw, Text, and Indexed profile readers. The first two types + /// of readers are used only by llvm-profdata tool, while the indexed + /// profile reader is also used by llvm-cov tool and the compiler ( + /// backend or frontend). Since creating PGO symtab can create + /// significant runtime and memory overhead (as it touches data + /// for the whole program), InstrProfSymtab for the indexed profile + /// reader should be created on demand and it is recommended to be + /// only used for dumping purpose with llvm-proftool, not with the + /// compiler. + virtual InstrProfSymtab &getSymtab() = 0; + protected: + std::unique_ptr<InstrProfSymtab> Symtab; /// Set the current std::error_code and return same. std::error_code error(std::error_code EC) { LastError = EC; @@ -107,14 +121,24 @@ private: TextInstrProfReader(const TextInstrProfReader &) = delete; TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; + std::error_code readValueProfileData(InstrProfRecord &Record); + public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} + /// Return true if the given buffer is in text instrprof format. + static bool hasFormat(const MemoryBuffer &Buffer); + /// Read the header. - std::error_code readHeader() override { return success(); } + std::error_code readHeader() override; /// Read a single record. std::error_code readNextRecord(InstrProfRecord &Record) override; + + InstrProfSymtab &getSymtab() override { + assert(Symtab.get()); + return *Symtab.get(); + } }; /// Reader for the raw instrprof binary format from runtime. @@ -129,31 +153,19 @@ class RawInstrProfReader : public InstrProfReader { private: /// The profile data file contents. std::unique_ptr<MemoryBuffer> DataBuffer; - struct ProfileData { - const uint32_t NameSize; - const uint32_t NumCounters; - const uint64_t FuncHash; - const IntPtrT NamePtr; - const IntPtrT CounterPtr; - }; - struct RawHeader { - const uint64_t Magic; - const uint64_t Version; - const uint64_t DataSize; - const uint64_t CountersSize; - const uint64_t NamesSize; - const uint64_t CountersDelta; - const uint64_t NamesDelta; - }; - bool ShouldSwapBytes; uint64_t CountersDelta; uint64_t NamesDelta; - const ProfileData *Data; - const ProfileData *DataEnd; + const RawInstrProf::ProfileData<IntPtrT> *Data; + const RawInstrProf::ProfileData<IntPtrT> *DataEnd; const uint64_t *CountersStart; const char *NamesStart; + const uint8_t *ValueDataStart; const char *ProfileEnd; + uint32_t ValueKindLast; + uint32_t CurValueDataSize; + + InstrProfRecord::ValueMapType FunctionPtrToNameMap; RawInstrProfReader(const RawInstrProfReader &) = delete; RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; @@ -165,13 +177,41 @@ public: std::error_code readHeader() override; std::error_code readNextRecord(InstrProfRecord &Record) override; + InstrProfSymtab &getSymtab() override { + assert(Symtab.get()); + return *Symtab.get(); + } + private: + void createSymtab(InstrProfSymtab &Symtab); std::error_code readNextHeader(const char *CurrentPos); - std::error_code readHeader(const RawHeader &Header); - template <class IntT> - IntT swap(IntT Int) const { + std::error_code readHeader(const RawInstrProf::Header &Header); + template <class IntT> IntT swap(IntT Int) const { return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; } + support::endianness getDataEndianness() const { + support::endianness HostEndian = getHostEndianness(); + if (!ShouldSwapBytes) + return HostEndian; + if (HostEndian == support::little) + return support::big; + else + return support::little; + } + + inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { + return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); + } + std::error_code readName(InstrProfRecord &Record); + std::error_code readFuncHash(InstrProfRecord &Record); + std::error_code readRawCounts(InstrProfRecord &Record); + std::error_code readValueProfilingData(InstrProfRecord &Record); + bool atEnd() const { return Data == DataEnd; } + void advanceData() { + Data++; + ValueDataStart += CurValueDataSize; + } + const uint64_t *getCounter(IntPtrT CounterPtr) const { ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); return CountersStart + Offset; @@ -195,10 +235,15 @@ class InstrProfLookupTrait { std::vector<InstrProfRecord> DataBuffer; IndexedInstrProf::HashT HashType; unsigned FormatVersion; + // Endianness of the input value profile data. + // It should be LE by default, but can be changed + // for testing purpose. + support::endianness ValueProfDataEndianness; public: InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) - : HashType(HashType), FormatVersion(FormatVersion) {} + : HashType(HashType), FormatVersion(FormatVersion), + ValueProfDataEndianness(support::little) {} typedef ArrayRef<InstrProfRecord> data_type; @@ -209,6 +254,7 @@ public: static bool EqualKey(StringRef A, StringRef B) { return A == B; } static StringRef GetInternalKey(StringRef K) { return K; } + static StringRef GetExternalKey(StringRef K) { return K; } hash_value_type ComputeHash(StringRef K); @@ -224,11 +270,64 @@ public: return StringRef((const char *)D, N); } + bool readValueProfilingData(const unsigned char *&D, + const unsigned char *const End); data_type ReadData(StringRef K, const unsigned char *D, offset_type N); + + // Used for testing purpose only. + void setValueProfDataEndianness(support::endianness Endianness) { + ValueProfDataEndianness = Endianness; + } +}; + +struct InstrProfReaderIndexBase { + // Read all the profile records with the same key pointed to the current + // iterator. + virtual std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) = 0; + // Read all the profile records with the key equal to FuncName + virtual std::error_code getRecords(StringRef FuncName, + ArrayRef<InstrProfRecord> &Data) = 0; + virtual void advanceToNextKey() = 0; + virtual bool atEnd() const = 0; + virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; + virtual ~InstrProfReaderIndexBase() {} + virtual uint64_t getVersion() const = 0; + virtual void populateSymtab(InstrProfSymtab &) = 0; }; typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait> - InstrProfReaderIndex; + OnDiskHashTableImplV3; + +template <typename HashTableImpl> +class InstrProfReaderIndex : public InstrProfReaderIndexBase { + +private: + std::unique_ptr<HashTableImpl> HashTable; + typename HashTableImpl::data_iterator RecordIterator; + uint64_t FormatVersion; + +public: + InstrProfReaderIndex(const unsigned char *Buckets, + const unsigned char *const Payload, + const unsigned char *const Base, + IndexedInstrProf::HashT HashType, uint64_t Version); + + std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) override; + std::error_code getRecords(StringRef FuncName, + ArrayRef<InstrProfRecord> &Data) override; + void advanceToNextKey() override { RecordIterator++; } + bool atEnd() const override { + return RecordIterator == HashTable->data_end(); + } + void setValueProfDataEndianness(support::endianness Endianness) override { + HashTable->getInfoObj().setValueProfDataEndianness(Endianness); + } + ~InstrProfReaderIndex() override {} + uint64_t getVersion() const override { return FormatVersion; } + void populateSymtab(InstrProfSymtab &Symtab) override { + Symtab.create(HashTable->keys()); + } +}; /// Reader for the indexed binary instrprof format. class IndexedInstrProfReader : public InstrProfReader { @@ -236,17 +335,15 @@ private: /// The profile data file contents. std::unique_ptr<MemoryBuffer> DataBuffer; /// The index into the profile data. - std::unique_ptr<InstrProfReaderIndex> Index; - /// Iterator over the profile data. - InstrProfReaderIndex::data_iterator RecordIterator; - /// The file format version of the profile data. - uint64_t FormatVersion; + std::unique_ptr<InstrProfReaderIndexBase> Index; /// The maximal execution count among all functions. uint64_t MaxFunctionCount; IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; + public: + uint64_t getVersion() const { return Index->getVersion(); } IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} @@ -258,9 +355,15 @@ public: /// Read a single record. std::error_code readNextRecord(InstrProfRecord &Record) override; + /// Return the pointer to InstrProfRecord associated with FuncName + /// and FuncHash + ErrorOr<InstrProfRecord> getInstrProfRecord(StringRef FuncName, + uint64_t FuncHash); + /// Fill Counts with the profile data for the given function name. std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector<uint64_t> &Counts); + /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } @@ -270,6 +373,16 @@ public: static ErrorOr<std::unique_ptr<IndexedInstrProfReader>> create(std::unique_ptr<MemoryBuffer> Buffer); + + // Used for testing purpose only. + void setValueProfDataEndianness(support::endianness Endianness) { + Index->setValueProfDataEndianness(Endianness); + } + + // See description in the base class. This interface is designed + // to be used by llvm-profdata (for dumping). Avoid using this when + // the client is the compiler. + InstrProfSymtab &getSymtab() override; }; } // end namespace llvm |
