1*9880d681SAndroid Build Coastguard Worker //=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker // 10*9880d681SAndroid Build Coastguard Worker // This file contains support for reading profiling data for instrumentation 11*9880d681SAndroid Build Coastguard Worker // based PGO and coverage. 12*9880d681SAndroid Build Coastguard Worker // 13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H 16*9880d681SAndroid Build Coastguard Worker #define LLVM_PROFILEDATA_INSTRPROFREADER_H 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h" 19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h" 20*9880d681SAndroid Build Coastguard Worker #include "llvm/ProfileData/InstrProf.h" 21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h" 22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/LineIterator.h" 23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h" 24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/OnDiskHashTable.h" 25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h" 26*9880d681SAndroid Build Coastguard Worker #include <iterator> 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker namespace llvm { 29*9880d681SAndroid Build Coastguard Worker 30*9880d681SAndroid Build Coastguard Worker class InstrProfReader; 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Worker /// A file format agnostic iterator over profiling data. 33*9880d681SAndroid Build Coastguard Worker class InstrProfIterator : public std::iterator<std::input_iterator_tag, 34*9880d681SAndroid Build Coastguard Worker InstrProfRecord> { 35*9880d681SAndroid Build Coastguard Worker InstrProfReader *Reader; 36*9880d681SAndroid Build Coastguard Worker InstrProfRecord Record; 37*9880d681SAndroid Build Coastguard Worker 38*9880d681SAndroid Build Coastguard Worker void Increment(); 39*9880d681SAndroid Build Coastguard Worker public: InstrProfIterator()40*9880d681SAndroid Build Coastguard Worker InstrProfIterator() : Reader(nullptr) {} InstrProfIterator(InstrProfReader * Reader)41*9880d681SAndroid Build Coastguard Worker InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } 42*9880d681SAndroid Build Coastguard Worker 43*9880d681SAndroid Build Coastguard Worker InstrProfIterator &operator++() { Increment(); return *this; } 44*9880d681SAndroid Build Coastguard Worker bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; } 45*9880d681SAndroid Build Coastguard Worker bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; } 46*9880d681SAndroid Build Coastguard Worker InstrProfRecord &operator*() { return Record; } 47*9880d681SAndroid Build Coastguard Worker InstrProfRecord *operator->() { return &Record; } 48*9880d681SAndroid Build Coastguard Worker }; 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker /// Base class and interface for reading profiling data of any known instrprof 51*9880d681SAndroid Build Coastguard Worker /// format. Provides an iterator over InstrProfRecords. 52*9880d681SAndroid Build Coastguard Worker class InstrProfReader { 53*9880d681SAndroid Build Coastguard Worker instrprof_error LastError; 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker public: InstrProfReader()56*9880d681SAndroid Build Coastguard Worker InstrProfReader() : LastError(instrprof_error::success), Symtab() {} ~InstrProfReader()57*9880d681SAndroid Build Coastguard Worker virtual ~InstrProfReader() {} 58*9880d681SAndroid Build Coastguard Worker 59*9880d681SAndroid Build Coastguard Worker /// Read the header. Required before reading first record. 60*9880d681SAndroid Build Coastguard Worker virtual Error readHeader() = 0; 61*9880d681SAndroid Build Coastguard Worker /// Read a single record. 62*9880d681SAndroid Build Coastguard Worker virtual Error readNextRecord(InstrProfRecord &Record) = 0; 63*9880d681SAndroid Build Coastguard Worker /// Iterator over profile data. begin()64*9880d681SAndroid Build Coastguard Worker InstrProfIterator begin() { return InstrProfIterator(this); } end()65*9880d681SAndroid Build Coastguard Worker InstrProfIterator end() { return InstrProfIterator(); } 66*9880d681SAndroid Build Coastguard Worker virtual bool isIRLevelProfile() const = 0; 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker /// Return the PGO symtab. There are three different readers: 69*9880d681SAndroid Build Coastguard Worker /// Raw, Text, and Indexed profile readers. The first two types 70*9880d681SAndroid Build Coastguard Worker /// of readers are used only by llvm-profdata tool, while the indexed 71*9880d681SAndroid Build Coastguard Worker /// profile reader is also used by llvm-cov tool and the compiler ( 72*9880d681SAndroid Build Coastguard Worker /// backend or frontend). Since creating PGO symtab can create 73*9880d681SAndroid Build Coastguard Worker /// significant runtime and memory overhead (as it touches data 74*9880d681SAndroid Build Coastguard Worker /// for the whole program), InstrProfSymtab for the indexed profile 75*9880d681SAndroid Build Coastguard Worker /// reader should be created on demand and it is recommended to be 76*9880d681SAndroid Build Coastguard Worker /// only used for dumping purpose with llvm-proftool, not with the 77*9880d681SAndroid Build Coastguard Worker /// compiler. 78*9880d681SAndroid Build Coastguard Worker virtual InstrProfSymtab &getSymtab() = 0; 79*9880d681SAndroid Build Coastguard Worker 80*9880d681SAndroid Build Coastguard Worker protected: 81*9880d681SAndroid Build Coastguard Worker std::unique_ptr<InstrProfSymtab> Symtab; 82*9880d681SAndroid Build Coastguard Worker /// Set the current error and return same. error(instrprof_error Err)83*9880d681SAndroid Build Coastguard Worker Error error(instrprof_error Err) { 84*9880d681SAndroid Build Coastguard Worker LastError = Err; 85*9880d681SAndroid Build Coastguard Worker if (Err == instrprof_error::success) 86*9880d681SAndroid Build Coastguard Worker return Error::success(); 87*9880d681SAndroid Build Coastguard Worker return make_error<InstrProfError>(Err); 88*9880d681SAndroid Build Coastguard Worker } error(Error E)89*9880d681SAndroid Build Coastguard Worker Error error(Error E) { return error(InstrProfError::take(std::move(E))); } 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker /// Clear the current error and return a successful one. success()92*9880d681SAndroid Build Coastguard Worker Error success() { return error(instrprof_error::success); } 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker public: 95*9880d681SAndroid Build Coastguard Worker /// Return true if the reader has finished reading the profile data. isEOF()96*9880d681SAndroid Build Coastguard Worker bool isEOF() { return LastError == instrprof_error::eof; } 97*9880d681SAndroid Build Coastguard Worker /// Return true if the reader encountered an error reading profiling data. hasError()98*9880d681SAndroid Build Coastguard Worker bool hasError() { return LastError != instrprof_error::success && !isEOF(); } 99*9880d681SAndroid Build Coastguard Worker /// Get the current error. getError()100*9880d681SAndroid Build Coastguard Worker Error getError() { 101*9880d681SAndroid Build Coastguard Worker if (hasError()) 102*9880d681SAndroid Build Coastguard Worker return make_error<InstrProfError>(LastError); 103*9880d681SAndroid Build Coastguard Worker return Error::success(); 104*9880d681SAndroid Build Coastguard Worker } 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Worker /// Factory method to create an appropriately typed reader for the given 107*9880d681SAndroid Build Coastguard Worker /// instrprof file. 108*9880d681SAndroid Build Coastguard Worker static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path); 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker static Expected<std::unique_ptr<InstrProfReader>> 111*9880d681SAndroid Build Coastguard Worker create(std::unique_ptr<MemoryBuffer> Buffer); 112*9880d681SAndroid Build Coastguard Worker }; 113*9880d681SAndroid Build Coastguard Worker 114*9880d681SAndroid Build Coastguard Worker /// Reader for the simple text based instrprof format. 115*9880d681SAndroid Build Coastguard Worker /// 116*9880d681SAndroid Build Coastguard Worker /// This format is a simple text format that's suitable for test data. Records 117*9880d681SAndroid Build Coastguard Worker /// are separated by one or more blank lines, and record fields are separated by 118*9880d681SAndroid Build Coastguard Worker /// new lines. 119*9880d681SAndroid Build Coastguard Worker /// 120*9880d681SAndroid Build Coastguard Worker /// Each record consists of a function name, a function hash, a number of 121*9880d681SAndroid Build Coastguard Worker /// counters, and then each counter value, in that order. 122*9880d681SAndroid Build Coastguard Worker class TextInstrProfReader : public InstrProfReader { 123*9880d681SAndroid Build Coastguard Worker private: 124*9880d681SAndroid Build Coastguard Worker /// The profile data file contents. 125*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> DataBuffer; 126*9880d681SAndroid Build Coastguard Worker /// Iterator over the profile data. 127*9880d681SAndroid Build Coastguard Worker line_iterator Line; 128*9880d681SAndroid Build Coastguard Worker bool IsIRLevelProfile; 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard Worker TextInstrProfReader(const TextInstrProfReader &) = delete; 131*9880d681SAndroid Build Coastguard Worker TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; 132*9880d681SAndroid Build Coastguard Worker Error readValueProfileData(InstrProfRecord &Record); 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Worker public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)135*9880d681SAndroid Build Coastguard Worker TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) 136*9880d681SAndroid Build Coastguard Worker : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'), 137*9880d681SAndroid Build Coastguard Worker IsIRLevelProfile(false) {} 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Worker /// Return true if the given buffer is in text instrprof format. 140*9880d681SAndroid Build Coastguard Worker static bool hasFormat(const MemoryBuffer &Buffer); 141*9880d681SAndroid Build Coastguard Worker isIRLevelProfile()142*9880d681SAndroid Build Coastguard Worker bool isIRLevelProfile() const override { return IsIRLevelProfile; } 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Worker /// Read the header. 145*9880d681SAndroid Build Coastguard Worker Error readHeader() override; 146*9880d681SAndroid Build Coastguard Worker /// Read a single record. 147*9880d681SAndroid Build Coastguard Worker Error readNextRecord(InstrProfRecord &Record) override; 148*9880d681SAndroid Build Coastguard Worker getSymtab()149*9880d681SAndroid Build Coastguard Worker InstrProfSymtab &getSymtab() override { 150*9880d681SAndroid Build Coastguard Worker assert(Symtab.get()); 151*9880d681SAndroid Build Coastguard Worker return *Symtab.get(); 152*9880d681SAndroid Build Coastguard Worker } 153*9880d681SAndroid Build Coastguard Worker }; 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard Worker /// Reader for the raw instrprof binary format from runtime. 156*9880d681SAndroid Build Coastguard Worker /// 157*9880d681SAndroid Build Coastguard Worker /// This format is a raw memory dump of the instrumentation-baed profiling data 158*9880d681SAndroid Build Coastguard Worker /// from the runtime. It has no index. 159*9880d681SAndroid Build Coastguard Worker /// 160*9880d681SAndroid Build Coastguard Worker /// Templated on the unsigned type whose size matches pointers on the platform 161*9880d681SAndroid Build Coastguard Worker /// that wrote the profile. 162*9880d681SAndroid Build Coastguard Worker template <class IntPtrT> 163*9880d681SAndroid Build Coastguard Worker class RawInstrProfReader : public InstrProfReader { 164*9880d681SAndroid Build Coastguard Worker private: 165*9880d681SAndroid Build Coastguard Worker /// The profile data file contents. 166*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> DataBuffer; 167*9880d681SAndroid Build Coastguard Worker bool ShouldSwapBytes; 168*9880d681SAndroid Build Coastguard Worker // The value of the version field of the raw profile data header. The lower 56 169*9880d681SAndroid Build Coastguard Worker // bits specifies the format version and the most significant 8 bits specify 170*9880d681SAndroid Build Coastguard Worker // the variant types of the profile. 171*9880d681SAndroid Build Coastguard Worker uint64_t Version; 172*9880d681SAndroid Build Coastguard Worker uint64_t CountersDelta; 173*9880d681SAndroid Build Coastguard Worker uint64_t NamesDelta; 174*9880d681SAndroid Build Coastguard Worker const RawInstrProf::ProfileData<IntPtrT> *Data; 175*9880d681SAndroid Build Coastguard Worker const RawInstrProf::ProfileData<IntPtrT> *DataEnd; 176*9880d681SAndroid Build Coastguard Worker const uint64_t *CountersStart; 177*9880d681SAndroid Build Coastguard Worker const char *NamesStart; 178*9880d681SAndroid Build Coastguard Worker uint64_t NamesSize; 179*9880d681SAndroid Build Coastguard Worker // After value profile is all read, this pointer points to 180*9880d681SAndroid Build Coastguard Worker // the header of next profile data (if exists) 181*9880d681SAndroid Build Coastguard Worker const uint8_t *ValueDataStart; 182*9880d681SAndroid Build Coastguard Worker uint32_t ValueKindLast; 183*9880d681SAndroid Build Coastguard Worker uint32_t CurValueDataSize; 184*9880d681SAndroid Build Coastguard Worker 185*9880d681SAndroid Build Coastguard Worker InstrProfRecord::ValueMapType FunctionPtrToNameMap; 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Worker RawInstrProfReader(const RawInstrProfReader &) = delete; 188*9880d681SAndroid Build Coastguard Worker RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; 189*9880d681SAndroid Build Coastguard Worker public: RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)190*9880d681SAndroid Build Coastguard Worker RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) 191*9880d681SAndroid Build Coastguard Worker : DataBuffer(std::move(DataBuffer)) { } 192*9880d681SAndroid Build Coastguard Worker 193*9880d681SAndroid Build Coastguard Worker static bool hasFormat(const MemoryBuffer &DataBuffer); 194*9880d681SAndroid Build Coastguard Worker Error readHeader() override; 195*9880d681SAndroid Build Coastguard Worker Error readNextRecord(InstrProfRecord &Record) override; isIRLevelProfile()196*9880d681SAndroid Build Coastguard Worker bool isIRLevelProfile() const override { 197*9880d681SAndroid Build Coastguard Worker return (Version & VARIANT_MASK_IR_PROF) != 0; 198*9880d681SAndroid Build Coastguard Worker } 199*9880d681SAndroid Build Coastguard Worker getSymtab()200*9880d681SAndroid Build Coastguard Worker InstrProfSymtab &getSymtab() override { 201*9880d681SAndroid Build Coastguard Worker assert(Symtab.get()); 202*9880d681SAndroid Build Coastguard Worker return *Symtab.get(); 203*9880d681SAndroid Build Coastguard Worker } 204*9880d681SAndroid Build Coastguard Worker 205*9880d681SAndroid Build Coastguard Worker private: 206*9880d681SAndroid Build Coastguard Worker Error createSymtab(InstrProfSymtab &Symtab); 207*9880d681SAndroid Build Coastguard Worker Error readNextHeader(const char *CurrentPos); 208*9880d681SAndroid Build Coastguard Worker Error readHeader(const RawInstrProf::Header &Header); swap(IntT Int)209*9880d681SAndroid Build Coastguard Worker template <class IntT> IntT swap(IntT Int) const { 210*9880d681SAndroid Build Coastguard Worker return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; 211*9880d681SAndroid Build Coastguard Worker } getDataEndianness()212*9880d681SAndroid Build Coastguard Worker support::endianness getDataEndianness() const { 213*9880d681SAndroid Build Coastguard Worker support::endianness HostEndian = getHostEndianness(); 214*9880d681SAndroid Build Coastguard Worker if (!ShouldSwapBytes) 215*9880d681SAndroid Build Coastguard Worker return HostEndian; 216*9880d681SAndroid Build Coastguard Worker if (HostEndian == support::little) 217*9880d681SAndroid Build Coastguard Worker return support::big; 218*9880d681SAndroid Build Coastguard Worker else 219*9880d681SAndroid Build Coastguard Worker return support::little; 220*9880d681SAndroid Build Coastguard Worker } 221*9880d681SAndroid Build Coastguard Worker getNumPaddingBytes(uint64_t SizeInBytes)222*9880d681SAndroid Build Coastguard Worker inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { 223*9880d681SAndroid Build Coastguard Worker return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); 224*9880d681SAndroid Build Coastguard Worker } 225*9880d681SAndroid Build Coastguard Worker Error readName(InstrProfRecord &Record); 226*9880d681SAndroid Build Coastguard Worker Error readFuncHash(InstrProfRecord &Record); 227*9880d681SAndroid Build Coastguard Worker Error readRawCounts(InstrProfRecord &Record); 228*9880d681SAndroid Build Coastguard Worker Error readValueProfilingData(InstrProfRecord &Record); atEnd()229*9880d681SAndroid Build Coastguard Worker bool atEnd() const { return Data == DataEnd; } advanceData()230*9880d681SAndroid Build Coastguard Worker void advanceData() { 231*9880d681SAndroid Build Coastguard Worker Data++; 232*9880d681SAndroid Build Coastguard Worker ValueDataStart += CurValueDataSize; 233*9880d681SAndroid Build Coastguard Worker } getNextHeaderPos()234*9880d681SAndroid Build Coastguard Worker const char *getNextHeaderPos() const { 235*9880d681SAndroid Build Coastguard Worker assert(atEnd()); 236*9880d681SAndroid Build Coastguard Worker return (const char *)ValueDataStart; 237*9880d681SAndroid Build Coastguard Worker } 238*9880d681SAndroid Build Coastguard Worker getCounter(IntPtrT CounterPtr)239*9880d681SAndroid Build Coastguard Worker const uint64_t *getCounter(IntPtrT CounterPtr) const { 240*9880d681SAndroid Build Coastguard Worker ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); 241*9880d681SAndroid Build Coastguard Worker return CountersStart + Offset; 242*9880d681SAndroid Build Coastguard Worker } getName(uint64_t NameRef)243*9880d681SAndroid Build Coastguard Worker StringRef getName(uint64_t NameRef) const { 244*9880d681SAndroid Build Coastguard Worker return Symtab->getFuncName(swap(NameRef)); 245*9880d681SAndroid Build Coastguard Worker } 246*9880d681SAndroid Build Coastguard Worker }; 247*9880d681SAndroid Build Coastguard Worker 248*9880d681SAndroid Build Coastguard Worker typedef RawInstrProfReader<uint32_t> RawInstrProfReader32; 249*9880d681SAndroid Build Coastguard Worker typedef RawInstrProfReader<uint64_t> RawInstrProfReader64; 250*9880d681SAndroid Build Coastguard Worker 251*9880d681SAndroid Build Coastguard Worker namespace IndexedInstrProf { 252*9880d681SAndroid Build Coastguard Worker enum class HashT : uint32_t; 253*9880d681SAndroid Build Coastguard Worker } 254*9880d681SAndroid Build Coastguard Worker 255*9880d681SAndroid Build Coastguard Worker /// Trait for lookups into the on-disk hash table for the binary instrprof 256*9880d681SAndroid Build Coastguard Worker /// format. 257*9880d681SAndroid Build Coastguard Worker class InstrProfLookupTrait { 258*9880d681SAndroid Build Coastguard Worker std::vector<InstrProfRecord> DataBuffer; 259*9880d681SAndroid Build Coastguard Worker IndexedInstrProf::HashT HashType; 260*9880d681SAndroid Build Coastguard Worker unsigned FormatVersion; 261*9880d681SAndroid Build Coastguard Worker // Endianness of the input value profile data. 262*9880d681SAndroid Build Coastguard Worker // It should be LE by default, but can be changed 263*9880d681SAndroid Build Coastguard Worker // for testing purpose. 264*9880d681SAndroid Build Coastguard Worker support::endianness ValueProfDataEndianness; 265*9880d681SAndroid Build Coastguard Worker 266*9880d681SAndroid Build Coastguard Worker public: InstrProfLookupTrait(IndexedInstrProf::HashT HashType,unsigned FormatVersion)267*9880d681SAndroid Build Coastguard Worker InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) 268*9880d681SAndroid Build Coastguard Worker : HashType(HashType), FormatVersion(FormatVersion), 269*9880d681SAndroid Build Coastguard Worker ValueProfDataEndianness(support::little) {} 270*9880d681SAndroid Build Coastguard Worker 271*9880d681SAndroid Build Coastguard Worker typedef ArrayRef<InstrProfRecord> data_type; 272*9880d681SAndroid Build Coastguard Worker 273*9880d681SAndroid Build Coastguard Worker typedef StringRef internal_key_type; 274*9880d681SAndroid Build Coastguard Worker typedef StringRef external_key_type; 275*9880d681SAndroid Build Coastguard Worker typedef uint64_t hash_value_type; 276*9880d681SAndroid Build Coastguard Worker typedef uint64_t offset_type; 277*9880d681SAndroid Build Coastguard Worker EqualKey(StringRef A,StringRef B)278*9880d681SAndroid Build Coastguard Worker static bool EqualKey(StringRef A, StringRef B) { return A == B; } GetInternalKey(StringRef K)279*9880d681SAndroid Build Coastguard Worker static StringRef GetInternalKey(StringRef K) { return K; } GetExternalKey(StringRef K)280*9880d681SAndroid Build Coastguard Worker static StringRef GetExternalKey(StringRef K) { return K; } 281*9880d681SAndroid Build Coastguard Worker 282*9880d681SAndroid Build Coastguard Worker hash_value_type ComputeHash(StringRef K); 283*9880d681SAndroid Build Coastguard Worker 284*9880d681SAndroid Build Coastguard Worker static std::pair<offset_type, offset_type> ReadKeyDataLength(const unsigned char * & D)285*9880d681SAndroid Build Coastguard Worker ReadKeyDataLength(const unsigned char *&D) { 286*9880d681SAndroid Build Coastguard Worker using namespace support; 287*9880d681SAndroid Build Coastguard Worker offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D); 288*9880d681SAndroid Build Coastguard Worker offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D); 289*9880d681SAndroid Build Coastguard Worker return std::make_pair(KeyLen, DataLen); 290*9880d681SAndroid Build Coastguard Worker } 291*9880d681SAndroid Build Coastguard Worker ReadKey(const unsigned char * D,offset_type N)292*9880d681SAndroid Build Coastguard Worker StringRef ReadKey(const unsigned char *D, offset_type N) { 293*9880d681SAndroid Build Coastguard Worker return StringRef((const char *)D, N); 294*9880d681SAndroid Build Coastguard Worker } 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard Worker bool readValueProfilingData(const unsigned char *&D, 297*9880d681SAndroid Build Coastguard Worker const unsigned char *const End); 298*9880d681SAndroid Build Coastguard Worker data_type ReadData(StringRef K, const unsigned char *D, offset_type N); 299*9880d681SAndroid Build Coastguard Worker 300*9880d681SAndroid Build Coastguard Worker // Used for testing purpose only. setValueProfDataEndianness(support::endianness Endianness)301*9880d681SAndroid Build Coastguard Worker void setValueProfDataEndianness(support::endianness Endianness) { 302*9880d681SAndroid Build Coastguard Worker ValueProfDataEndianness = Endianness; 303*9880d681SAndroid Build Coastguard Worker } 304*9880d681SAndroid Build Coastguard Worker }; 305*9880d681SAndroid Build Coastguard Worker 306*9880d681SAndroid Build Coastguard Worker struct InstrProfReaderIndexBase { 307*9880d681SAndroid Build Coastguard Worker // Read all the profile records with the same key pointed to the current 308*9880d681SAndroid Build Coastguard Worker // iterator. 309*9880d681SAndroid Build Coastguard Worker virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0; 310*9880d681SAndroid Build Coastguard Worker // Read all the profile records with the key equal to FuncName 311*9880d681SAndroid Build Coastguard Worker virtual Error getRecords(StringRef FuncName, 312*9880d681SAndroid Build Coastguard Worker ArrayRef<InstrProfRecord> &Data) = 0; 313*9880d681SAndroid Build Coastguard Worker virtual void advanceToNextKey() = 0; 314*9880d681SAndroid Build Coastguard Worker virtual bool atEnd() const = 0; 315*9880d681SAndroid Build Coastguard Worker virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; ~InstrProfReaderIndexBaseInstrProfReaderIndexBase316*9880d681SAndroid Build Coastguard Worker virtual ~InstrProfReaderIndexBase() {} 317*9880d681SAndroid Build Coastguard Worker virtual uint64_t getVersion() const = 0; 318*9880d681SAndroid Build Coastguard Worker virtual bool isIRLevelProfile() const = 0; 319*9880d681SAndroid Build Coastguard Worker virtual void populateSymtab(InstrProfSymtab &) = 0; 320*9880d681SAndroid Build Coastguard Worker }; 321*9880d681SAndroid Build Coastguard Worker 322*9880d681SAndroid Build Coastguard Worker typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait> 323*9880d681SAndroid Build Coastguard Worker OnDiskHashTableImplV3; 324*9880d681SAndroid Build Coastguard Worker 325*9880d681SAndroid Build Coastguard Worker template <typename HashTableImpl> 326*9880d681SAndroid Build Coastguard Worker class InstrProfReaderIndex : public InstrProfReaderIndexBase { 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Worker private: 329*9880d681SAndroid Build Coastguard Worker std::unique_ptr<HashTableImpl> HashTable; 330*9880d681SAndroid Build Coastguard Worker typename HashTableImpl::data_iterator RecordIterator; 331*9880d681SAndroid Build Coastguard Worker uint64_t FormatVersion; 332*9880d681SAndroid Build Coastguard Worker 333*9880d681SAndroid Build Coastguard Worker public: 334*9880d681SAndroid Build Coastguard Worker InstrProfReaderIndex(const unsigned char *Buckets, 335*9880d681SAndroid Build Coastguard Worker const unsigned char *const Payload, 336*9880d681SAndroid Build Coastguard Worker const unsigned char *const Base, 337*9880d681SAndroid Build Coastguard Worker IndexedInstrProf::HashT HashType, uint64_t Version); 338*9880d681SAndroid Build Coastguard Worker 339*9880d681SAndroid Build Coastguard Worker Error getRecords(ArrayRef<InstrProfRecord> &Data) override; 340*9880d681SAndroid Build Coastguard Worker Error getRecords(StringRef FuncName, 341*9880d681SAndroid Build Coastguard Worker ArrayRef<InstrProfRecord> &Data) override; advanceToNextKey()342*9880d681SAndroid Build Coastguard Worker void advanceToNextKey() override { RecordIterator++; } atEnd()343*9880d681SAndroid Build Coastguard Worker bool atEnd() const override { 344*9880d681SAndroid Build Coastguard Worker return RecordIterator == HashTable->data_end(); 345*9880d681SAndroid Build Coastguard Worker } setValueProfDataEndianness(support::endianness Endianness)346*9880d681SAndroid Build Coastguard Worker void setValueProfDataEndianness(support::endianness Endianness) override { 347*9880d681SAndroid Build Coastguard Worker HashTable->getInfoObj().setValueProfDataEndianness(Endianness); 348*9880d681SAndroid Build Coastguard Worker } ~InstrProfReaderIndex()349*9880d681SAndroid Build Coastguard Worker ~InstrProfReaderIndex() override {} getVersion()350*9880d681SAndroid Build Coastguard Worker uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } isIRLevelProfile()351*9880d681SAndroid Build Coastguard Worker bool isIRLevelProfile() const override { 352*9880d681SAndroid Build Coastguard Worker return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; 353*9880d681SAndroid Build Coastguard Worker } populateSymtab(InstrProfSymtab & Symtab)354*9880d681SAndroid Build Coastguard Worker void populateSymtab(InstrProfSymtab &Symtab) override { 355*9880d681SAndroid Build Coastguard Worker Symtab.create(HashTable->keys()); 356*9880d681SAndroid Build Coastguard Worker } 357*9880d681SAndroid Build Coastguard Worker }; 358*9880d681SAndroid Build Coastguard Worker 359*9880d681SAndroid Build Coastguard Worker /// Reader for the indexed binary instrprof format. 360*9880d681SAndroid Build Coastguard Worker class IndexedInstrProfReader : public InstrProfReader { 361*9880d681SAndroid Build Coastguard Worker private: 362*9880d681SAndroid Build Coastguard Worker /// The profile data file contents. 363*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> DataBuffer; 364*9880d681SAndroid Build Coastguard Worker /// The index into the profile data. 365*9880d681SAndroid Build Coastguard Worker std::unique_ptr<InstrProfReaderIndexBase> Index; 366*9880d681SAndroid Build Coastguard Worker /// Profile summary data. 367*9880d681SAndroid Build Coastguard Worker std::unique_ptr<ProfileSummary> Summary; 368*9880d681SAndroid Build Coastguard Worker 369*9880d681SAndroid Build Coastguard Worker IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; 370*9880d681SAndroid Build Coastguard Worker IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; 371*9880d681SAndroid Build Coastguard Worker 372*9880d681SAndroid Build Coastguard Worker // Read the profile summary. Return a pointer pointing to one byte past the 373*9880d681SAndroid Build Coastguard Worker // end of the summary data if it exists or the input \c Cur. 374*9880d681SAndroid Build Coastguard Worker const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, 375*9880d681SAndroid Build Coastguard Worker const unsigned char *Cur); 376*9880d681SAndroid Build Coastguard Worker 377*9880d681SAndroid Build Coastguard Worker public: 378*9880d681SAndroid Build Coastguard Worker /// Return the profile version. getVersion()379*9880d681SAndroid Build Coastguard Worker uint64_t getVersion() const { return Index->getVersion(); } isIRLevelProfile()380*9880d681SAndroid Build Coastguard Worker bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)381*9880d681SAndroid Build Coastguard Worker IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) 382*9880d681SAndroid Build Coastguard Worker : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} 383*9880d681SAndroid Build Coastguard Worker 384*9880d681SAndroid Build Coastguard Worker /// Return true if the given buffer is in an indexed instrprof format. 385*9880d681SAndroid Build Coastguard Worker static bool hasFormat(const MemoryBuffer &DataBuffer); 386*9880d681SAndroid Build Coastguard Worker 387*9880d681SAndroid Build Coastguard Worker /// Read the file header. 388*9880d681SAndroid Build Coastguard Worker Error readHeader() override; 389*9880d681SAndroid Build Coastguard Worker /// Read a single record. 390*9880d681SAndroid Build Coastguard Worker Error readNextRecord(InstrProfRecord &Record) override; 391*9880d681SAndroid Build Coastguard Worker 392*9880d681SAndroid Build Coastguard Worker /// Return the pointer to InstrProfRecord associated with FuncName 393*9880d681SAndroid Build Coastguard Worker /// and FuncHash 394*9880d681SAndroid Build Coastguard Worker Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName, 395*9880d681SAndroid Build Coastguard Worker uint64_t FuncHash); 396*9880d681SAndroid Build Coastguard Worker 397*9880d681SAndroid Build Coastguard Worker /// Fill Counts with the profile data for the given function name. 398*9880d681SAndroid Build Coastguard Worker Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, 399*9880d681SAndroid Build Coastguard Worker std::vector<uint64_t> &Counts); 400*9880d681SAndroid Build Coastguard Worker 401*9880d681SAndroid Build Coastguard Worker /// Return the maximum of all known function counts. getMaximumFunctionCount()402*9880d681SAndroid Build Coastguard Worker uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); } 403*9880d681SAndroid Build Coastguard Worker 404*9880d681SAndroid Build Coastguard Worker /// Factory method to create an indexed reader. 405*9880d681SAndroid Build Coastguard Worker static Expected<std::unique_ptr<IndexedInstrProfReader>> 406*9880d681SAndroid Build Coastguard Worker create(const Twine &Path); 407*9880d681SAndroid Build Coastguard Worker 408*9880d681SAndroid Build Coastguard Worker static Expected<std::unique_ptr<IndexedInstrProfReader>> 409*9880d681SAndroid Build Coastguard Worker create(std::unique_ptr<MemoryBuffer> Buffer); 410*9880d681SAndroid Build Coastguard Worker 411*9880d681SAndroid Build Coastguard Worker // Used for testing purpose only. setValueProfDataEndianness(support::endianness Endianness)412*9880d681SAndroid Build Coastguard Worker void setValueProfDataEndianness(support::endianness Endianness) { 413*9880d681SAndroid Build Coastguard Worker Index->setValueProfDataEndianness(Endianness); 414*9880d681SAndroid Build Coastguard Worker } 415*9880d681SAndroid Build Coastguard Worker 416*9880d681SAndroid Build Coastguard Worker // See description in the base class. This interface is designed 417*9880d681SAndroid Build Coastguard Worker // to be used by llvm-profdata (for dumping). Avoid using this when 418*9880d681SAndroid Build Coastguard Worker // the client is the compiler. 419*9880d681SAndroid Build Coastguard Worker InstrProfSymtab &getSymtab() override; getSummary()420*9880d681SAndroid Build Coastguard Worker ProfileSummary &getSummary() { return *(Summary.get()); } 421*9880d681SAndroid Build Coastguard Worker }; 422*9880d681SAndroid Build Coastguard Worker 423*9880d681SAndroid Build Coastguard Worker } // end namespace llvm 424*9880d681SAndroid Build Coastguard Worker 425*9880d681SAndroid Build Coastguard Worker #endif 426