X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FProfileData%2FInstrProfReader.h;h=304606de67914879e45ff8bef277659457e50e62;hp=e2c59cf186bb1daaf5d200b541a78becca30a5c1;hb=6f139ce20bc911456a8edcaabd408e09bd41c806;hpb=218c7c821b955398baf144199ac69d9c9665e102 diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index e2c59cf186b..304606de679 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -12,28 +12,24 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_READER_H_ -#define LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H +#define LLVM_PROFILEDATA_INSTRPROFREADER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Endian.h" - +#include "llvm/Support/OnDiskHashTable.h" +#include "llvm/Support/raw_ostream.h" #include namespace llvm { class InstrProfReader; -/// Profiling information for a single function. -struct InstrProfRecord { - StringRef Name; - uint64_t Hash; - ArrayRef Counts; -}; - /// A file format agnostic iterator over profiling data. class InstrProfIterator : public std::iterator { @@ -55,28 +51,29 @@ public: /// Base class and interface for reading profiling data of any known instrprof /// format. Provides an iterator over InstrProfRecords. class InstrProfReader { - error_code LastError; + std::error_code LastError; + public: InstrProfReader() : LastError(instrprof_error::success) {} virtual ~InstrProfReader() {} /// Read the header. Required before reading first record. - virtual error_code readHeader() = 0; + virtual std::error_code readHeader() = 0; /// Read a single record. - virtual error_code readNextRecord(InstrProfRecord &Record) = 0; + virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0; /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } -protected: - /// Set the current error_code and return same. - error_code error(error_code EC) { + protected: + /// Set the current std::error_code and return same. + std::error_code error(std::error_code EC) { LastError = EC; return EC; } /// Clear the current error code and return a successful one. - error_code success() { return error(instrprof_error::success); } + std::error_code success() { return error(instrprof_error::success); } public: /// Return true if the reader has finished reading the profile data. @@ -84,12 +81,14 @@ public: /// Return true if the reader encountered an error reading profiling data. bool hasError() { return LastError && !isEOF(); } /// Get the current error code. - error_code getError() { return LastError; } + std::error_code getError() { return LastError; } /// Factory method to create an appropriately typed reader for the given /// instrprof file. - static error_code create(std::string Path, - std::unique_ptr &Result); + static ErrorOr> create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); }; /// Reader for the simple text based instrprof format. @@ -106,82 +105,260 @@ private: std::unique_ptr DataBuffer; /// Iterator over the profile data. line_iterator Line; - /// The current set of counter values. - std::vector Counts; - TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - TextInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; public: - TextInstrProfReader(std::unique_ptr &DataBuffer_) - : DataBuffer(DataBuffer_.release()), Line(*DataBuffer, '#') {} + TextInstrProfReader(std::unique_ptr 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. - error_code readHeader() override { return success(); } + std::error_code readHeader() override { return success(); } /// Read a single record. - error_code readNextRecord(InstrProfRecord &Record) override; + std::error_code readNextRecord(InstrProfRecord &Record) override; }; /// Reader for the raw instrprof binary format from runtime. /// /// This format is a raw memory dump of the instrumentation-baed profiling data /// from the runtime. It has no index. +/// +/// Templated on the unsigned type whose size matches pointers on the platform +/// that wrote the profile. +template class RawInstrProfReader : public InstrProfReader { private: /// The profile data file contents. std::unique_ptr DataBuffer; - /// The current set of counter values. - std::vector Counts; - struct ProfileData { - const uint32_t NameSize; - const uint32_t NumCounters; - const uint64_t FuncHash; - const uint64_t NamePtr; - const uint64_t 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 *Data; + const RawInstrProf::ProfileData *DataEnd; const uint64_t *CountersStart; const char *NamesStart; + const uint8_t *ValueDataStart; + const char *ProfileEnd; + uint32_t ValueKindLast; + uint32_t CurValueDataSize; - RawInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + // String table for holding a unique copy of all the strings in the profile. + InstrProfStringTable StringTable; + InstrProfRecord::ValueMapType FunctionPtrToNameMap; + + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: - RawInstrProfReader(std::unique_ptr &DataBuffer); + RawInstrProfReader(std::unique_ptr DataBuffer) + : DataBuffer(std::move(DataBuffer)) { } - error_code readHeader() override; - error_code readNextRecord(InstrProfRecord &Record) override; + static bool hasFormat(const MemoryBuffer &DataBuffer); + std::error_code readHeader() override; + std::error_code readNextRecord(InstrProfRecord &Record) override; private: - error_code readHeader(const RawHeader &Header); - template - IntT swap(IntT Int) const { - return ShouldSwapBytes ? sys::SwapByteOrder(Int) : Int; + std::error_code readNextHeader(const char *CurrentPos); + std::error_code readHeader(const RawInstrProf::Header &Header); + template 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)); } - const uint64_t *getCounter(uint64_t CounterPtr) const { + 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; } - const char *getName(uint64_t NamePtr) const { + const char *getName(IntPtrT NamePtr) const { ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char); return NamesStart + Offset; } }; +typedef RawInstrProfReader RawInstrProfReader32; +typedef RawInstrProfReader RawInstrProfReader64; + +namespace IndexedInstrProf { +enum class HashT : uint32_t; +} + +/// Trait for lookups into the on-disk hash table for the binary instrprof +/// format. +class InstrProfLookupTrait { + std::vector 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; + std::vector> HashKeys; + +public: + InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) + : HashType(HashType), FormatVersion(FormatVersion), + ValueProfDataEndianness(support::little) {} + + typedef ArrayRef data_type; + + typedef StringRef internal_key_type; + typedef StringRef external_key_type; + typedef uint64_t hash_value_type; + typedef uint64_t offset_type; + + 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); + + void setHashKeys(std::vector> HashKeys) { + this->HashKeys = std::move(HashKeys); + } + static std::pair + ReadKeyDataLength(const unsigned char *&D) { + using namespace support; + offset_type KeyLen = endian::readNext(D); + offset_type DataLen = endian::readNext(D); + return std::make_pair(KeyLen, DataLen); + } + + StringRef ReadKey(const unsigned char *D, offset_type N) { + 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 &Data) = 0; + // Read all the profile records with the key equal to FuncName + virtual std::error_code getRecords(StringRef FuncName, + ArrayRef &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; +}; + +typedef OnDiskIterableChainedHashTable + OnDiskHashTableImplV3; + +template +class InstrProfReaderIndex : public InstrProfReaderIndexBase { + +private: + std::unique_ptr HashTable; + typename HashTableImpl::data_iterator RecordIterator; + uint64_t FormatVersion; + + // String table for holding a unique copy of all the strings in the profile. + InstrProfStringTable StringTable; + +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 &Data) override; + std::error_code getRecords(StringRef FuncName, + ArrayRef &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; } +}; + +/// Reader for the indexed binary instrprof format. +class IndexedInstrProfReader : public InstrProfReader { +private: + /// The profile data file contents. + std::unique_ptr DataBuffer; + /// The index into the profile data. + std::unique_ptr 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 DataBuffer) + : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} + + /// Return true if the given buffer is in an indexed instrprof format. + static bool hasFormat(const MemoryBuffer &DataBuffer); + + /// Read the file header. + std::error_code readHeader() override; + /// Read a single record. + std::error_code readNextRecord(InstrProfRecord &Record) override; + + /// Return the pointer to InstrProfRecord associated with FuncName + /// and FuncHash + ErrorOr 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 &Counts); + + /// Return the maximum of all known function counts. + uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } + + /// Factory method to create an indexed reader. + static ErrorOr> + create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); + + // Used for testing purpose only. + void setValueProfDataEndianness(support::endianness Endianness) { + Index->setValueProfDataEndianness(Endianness); + } +}; + } // end namespace llvm -#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#endif