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