From e153fb33e49bd6d44189d3659287338c410bc0ce Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Fri, 18 Apr 2014 21:48:40 +0000 Subject: ProfileData: Add support for the indexed instrprof format This adds support for an indexed instrumentation based profiling format, which is just a small header and an on disk hash table. This format will be used by clang's -fprofile-instr-use= for PGO. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206656 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/InstrProf.h | 1 + include/llvm/ProfileData/InstrProfReader.h | 107 ++++++++++++++++++++++++++++- include/llvm/ProfileData/InstrProfWriter.h | 2 +- 3 files changed, 108 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index d8f3ca6b9d..8457678c4e 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -29,6 +29,7 @@ struct instrprof_error { bad_magic, bad_header, unsupported_version, + unsupported_hash_type, too_large, truncated, malformed, diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 2c070b9706..a9793cf28f 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -16,10 +16,12 @@ #define LLVM_PROFILEDATA_INSTRPROF_READER_H_ #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/OnDiskHashTable.h" #include @@ -29,6 +31,9 @@ class InstrProfReader; /// Profiling information for a single function. struct InstrProfRecord { + InstrProfRecord() {} + InstrProfRecord(StringRef Name, uint64_t Hash, ArrayRef Counts) + : Name(Name), Hash(Hash), Counts(Counts) {} StringRef Name; uint64_t Hash; ArrayRef Counts; @@ -191,6 +196,106 @@ private: typedef RawInstrProfReader RawInstrProfReader32; typedef RawInstrProfReader RawInstrProfReader64; +namespace IndexedInstrProf { +enum class HashT : uint32_t; +uint64_t ComputeHash(HashT Type, StringRef K); +} + +/// Trait for lookups into the on-disk hash table for the binary instrprof +/// format. +class InstrProfLookupTrait { + std::vector CountBuffer; + IndexedInstrProf::HashT HashType; +public: + InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {} + + typedef InstrProfRecord 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; } + + hash_value_type ComputeHash(StringRef K) { + return IndexedInstrProf::ComputeHash(HashType, K); + } + + static std::pair + ReadKeyDataLength(const unsigned char *&D) { + using namespace support; + return std::make_pair(endian::readNext(D), + endian::readNext(D)); + } + + StringRef ReadKey(const unsigned char *D, unsigned N) { + return StringRef((const char *)D, N); + } + + InstrProfRecord ReadData(StringRef K, const unsigned char *D, unsigned N) { + if (N < 2 * sizeof(uint64_t) || N % sizeof(uint64_t)) { + // The data is corrupt, don't try to read it. + CountBuffer.clear(); + return InstrProfRecord("", 0, CountBuffer); + } + + using namespace support; + + // The first stored value is the hash. + uint64_t Hash = endian::readNext(D); + // Each counter follows. + unsigned NumCounters = N / sizeof(uint64_t) - 1; + CountBuffer.clear(); + CountBuffer.reserve(NumCounters - 1); + for (unsigned I = 0; I < NumCounters; ++I) + CountBuffer.push_back(endian::readNext(D)); + + return InstrProfRecord(K, Hash, CountBuffer); + } +}; +typedef OnDiskIterableChainedHashTable + InstrProfReaderIndex; + +/// 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; + /// Iterator over the profile data. + InstrProfReaderIndex::data_iterator RecordIterator; + /// The maximal execution count among all fucntions. + uint64_t MaxFunctionCount; + + IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) + LLVM_DELETED_FUNCTION; +public: + IndexedInstrProfReader(std::unique_ptr DataBuffer) + : DataBuffer(std::move(DataBuffer)), Index(nullptr), + RecordIterator(InstrProfReaderIndex::data_iterator()) {} + + /// Return true if the given buffer is in an indexed instrprof format. + static bool hasFormat(const MemoryBuffer &DataBuffer); + + /// Read the file header. + error_code readHeader() override; + /// Read a single record. + error_code readNextRecord(InstrProfRecord &Record) override; + + /// Fill Counts with the profile data for the given function name. + 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 error_code create(std::string Path, + std::unique_ptr &Result); +}; + } // end namespace llvm #endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index f818fa08fa..fa37bf116d 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -41,7 +41,7 @@ public: error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef Counters); /// Ensure that all data is written to disk. - void write(raw_ostream &OS); + void write(raw_fd_ostream &OS); }; } // end namespace llvm -- cgit v1.2.3