LLVM  6.0.0svn
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/StringRef.h"
20 #include "llvm/IR/ProfileSummary.h"
22 #include "llvm/Support/Endian.h"
23 #include "llvm/Support/Error.h"
28 #include <algorithm>
29 #include <cassert>
30 #include <cstddef>
31 #include <cstdint>
32 #include <iterator>
33 #include <memory>
34 #include <utility>
35 #include <vector>
36 
37 namespace llvm {
38 
39 class InstrProfReader;
40 
41 /// A file format agnostic iterator over profiling data.
42 class InstrProfIterator : public std::iterator<std::input_iterator_tag,
43  NamedInstrProfRecord> {
44  InstrProfReader *Reader = nullptr;
45  value_type Record;
46 
47  void Increment();
48 
49 public:
50  InstrProfIterator() = default;
51  InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
52 
53  InstrProfIterator &operator++() { Increment(); return *this; }
54  bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
55  bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
56  value_type &operator*() { return Record; }
57  value_type *operator->() { return &Record; }
58 };
59 
60 /// Base class and interface for reading profiling data of any known instrprof
61 /// format. Provides an iterator over NamedInstrProfRecords.
64 
65 public:
66  InstrProfReader() = default;
67  virtual ~InstrProfReader() = default;
68 
69  /// Read the header. Required before reading first record.
70  virtual Error readHeader() = 0;
71 
72  /// Read a single record.
73  virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
74 
75  /// Iterator over profile data.
78 
79  virtual bool isIRLevelProfile() const = 0;
80 
81  /// Return the PGO symtab. There are three different readers:
82  /// Raw, Text, and Indexed profile readers. The first two types
83  /// of readers are used only by llvm-profdata tool, while the indexed
84  /// profile reader is also used by llvm-cov tool and the compiler (
85  /// backend or frontend). Since creating PGO symtab can create
86  /// significant runtime and memory overhead (as it touches data
87  /// for the whole program), InstrProfSymtab for the indexed profile
88  /// reader should be created on demand and it is recommended to be
89  /// only used for dumping purpose with llvm-proftool, not with the
90  /// compiler.
91  virtual InstrProfSymtab &getSymtab() = 0;
92 
93 protected:
94  std::unique_ptr<InstrProfSymtab> Symtab;
95 
96  /// Set the current error and return same.
98  LastError = Err;
99  if (Err == instrprof_error::success)
100  return Error::success();
101  return make_error<InstrProfError>(Err);
102  }
103 
104  Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
105 
106  /// Clear the current error and return a successful one.
108 
109 public:
110  /// Return true if the reader has finished reading the profile data.
111  bool isEOF() { return LastError == instrprof_error::eof; }
112 
113  /// Return true if the reader encountered an error reading profiling data.
114  bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
115 
116  /// Get the current error.
118  if (hasError())
119  return make_error<InstrProfError>(LastError);
120  return Error::success();
121  }
122 
123  /// Factory method to create an appropriately typed reader for the given
124  /// instrprof file.
125  static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
126 
128  create(std::unique_ptr<MemoryBuffer> Buffer);
129 };
130 
131 /// Reader for the simple text based instrprof format.
132 ///
133 /// This format is a simple text format that's suitable for test data. Records
134 /// are separated by one or more blank lines, and record fields are separated by
135 /// new lines.
136 ///
137 /// Each record consists of a function name, a function hash, a number of
138 /// counters, and then each counter value, in that order.
140 private:
141  /// The profile data file contents.
142  std::unique_ptr<MemoryBuffer> DataBuffer;
143  /// Iterator over the profile data.
144  line_iterator Line;
145  bool IsIRLevelProfile = false;
146 
147  Error readValueProfileData(InstrProfRecord &Record);
148 
149 public:
150  TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
151  : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
152  TextInstrProfReader(const TextInstrProfReader &) = delete;
153  TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
154 
155  /// Return true if the given buffer is in text instrprof format.
156  static bool hasFormat(const MemoryBuffer &Buffer);
157 
158  bool isIRLevelProfile() const override { return IsIRLevelProfile; }
159 
160  /// Read the header.
161  Error readHeader() override;
162 
163  /// Read a single record.
164  Error readNextRecord(NamedInstrProfRecord &Record) override;
165 
167  assert(Symtab.get());
168  return *Symtab.get();
169  }
170 };
171 
172 /// Reader for the raw instrprof binary format from runtime.
173 ///
174 /// This format is a raw memory dump of the instrumentation-baed profiling data
175 /// from the runtime. It has no index.
176 ///
177 /// Templated on the unsigned type whose size matches pointers on the platform
178 /// that wrote the profile.
179 template <class IntPtrT>
181 private:
182  /// The profile data file contents.
183  std::unique_ptr<MemoryBuffer> DataBuffer;
184  bool ShouldSwapBytes;
185  // The value of the version field of the raw profile data header. The lower 56
186  // bits specifies the format version and the most significant 8 bits specify
187  // the variant types of the profile.
188  uint64_t Version;
189  uint64_t CountersDelta;
190  uint64_t NamesDelta;
192  const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
193  const uint64_t *CountersStart;
194  const char *NamesStart;
195  uint64_t NamesSize;
196  // After value profile is all read, this pointer points to
197  // the header of next profile data (if exists)
198  const uint8_t *ValueDataStart;
199  uint32_t ValueKindLast;
200  uint32_t CurValueDataSize;
201 
202  InstrProfRecord::ValueMapType FunctionPtrToNameMap;
203 
204 public:
205  RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
206  : DataBuffer(std::move(DataBuffer)) {}
207  RawInstrProfReader(const RawInstrProfReader &) = delete;
208  RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
209 
210  static bool hasFormat(const MemoryBuffer &DataBuffer);
211  Error readHeader() override;
212  Error readNextRecord(NamedInstrProfRecord &Record) override;
213 
214  bool isIRLevelProfile() const override {
215  return (Version & VARIANT_MASK_IR_PROF) != 0;
216  }
217 
219  assert(Symtab.get());
220  return *Symtab.get();
221  }
222 
223 private:
224  Error createSymtab(InstrProfSymtab &Symtab);
225  Error readNextHeader(const char *CurrentPos);
226  Error readHeader(const RawInstrProf::Header &Header);
227 
228  template <class IntT> IntT swap(IntT Int) const {
229  return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
230  }
231 
232  support::endianness getDataEndianness() const {
233  support::endianness HostEndian = getHostEndianness();
234  if (!ShouldSwapBytes)
235  return HostEndian;
236  if (HostEndian == support::little)
237  return support::big;
238  else
239  return support::little;
240  }
241 
242  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
243  return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
244  }
245 
246  Error readName(NamedInstrProfRecord &Record);
247  Error readFuncHash(NamedInstrProfRecord &Record);
248  Error readRawCounts(InstrProfRecord &Record);
249  Error readValueProfilingData(InstrProfRecord &Record);
250  bool atEnd() const { return Data == DataEnd; }
251 
252  void advanceData() {
253  Data++;
254  ValueDataStart += CurValueDataSize;
255  }
256 
257  const char *getNextHeaderPos() const {
258  assert(atEnd());
259  return (const char *)ValueDataStart;
260  }
261 
262  const uint64_t *getCounter(IntPtrT CounterPtr) const {
263  ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
264  return CountersStart + Offset;
265  }
266 
267  StringRef getName(uint64_t NameRef) const {
268  return Symtab->getFuncName(swap(NameRef));
269  }
270 };
271 
274 
275 namespace IndexedInstrProf {
276 
277 enum class HashT : uint32_t;
278 
279 } // end namespace IndexedInstrProf
280 
281 /// Trait for lookups into the on-disk hash table for the binary instrprof
282 /// format.
284  std::vector<NamedInstrProfRecord> DataBuffer;
286  unsigned FormatVersion;
287  // Endianness of the input value profile data.
288  // It should be LE by default, but can be changed
289  // for testing purpose.
290  support::endianness ValueProfDataEndianness = support::little;
291 
292 public:
293  InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
294  : HashType(HashType), FormatVersion(FormatVersion) {}
295 
297 
300  using hash_value_type = uint64_t;
301  using offset_type = uint64_t;
302 
303  static bool EqualKey(StringRef A, StringRef B) { return A == B; }
304  static StringRef GetInternalKey(StringRef K) { return K; }
305  static StringRef GetExternalKey(StringRef K) { return K; }
306 
308 
309  static std::pair<offset_type, offset_type>
310  ReadKeyDataLength(const unsigned char *&D) {
311  using namespace support;
312 
313  offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
314  offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
315  return std::make_pair(KeyLen, DataLen);
316  }
317 
318  StringRef ReadKey(const unsigned char *D, offset_type N) {
319  return StringRef((const char *)D, N);
320  }
321 
322  bool readValueProfilingData(const unsigned char *&D,
323  const unsigned char *const End);
324  data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
325 
326  // Used for testing purpose only.
328  ValueProfDataEndianness = Endianness;
329  }
330 };
331 
333  virtual ~InstrProfReaderIndexBase() = default;
334 
335  // Read all the profile records with the same key pointed to the current
336  // iterator.
337  virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
338 
339  // Read all the profile records with the key equal to FuncName
340  virtual Error getRecords(StringRef FuncName,
342  virtual void advanceToNextKey() = 0;
343  virtual bool atEnd() const = 0;
344  virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
345  virtual uint64_t getVersion() const = 0;
346  virtual bool isIRLevelProfile() const = 0;
347  virtual Error populateSymtab(InstrProfSymtab &) = 0;
348 };
349 
350 using OnDiskHashTableImplV3 =
352 
353 template <typename HashTableImpl>
355 private:
356  std::unique_ptr<HashTableImpl> HashTable;
357  typename HashTableImpl::data_iterator RecordIterator;
358  uint64_t FormatVersion;
359 
360 public:
361  InstrProfReaderIndex(const unsigned char *Buckets,
362  const unsigned char *const Payload,
363  const unsigned char *const Base,
365  ~InstrProfReaderIndex() override = default;
366 
367  Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
368  Error getRecords(StringRef FuncName,
369  ArrayRef<NamedInstrProfRecord> &Data) override;
370  void advanceToNextKey() override { RecordIterator++; }
371 
372  bool atEnd() const override {
373  return RecordIterator == HashTable->data_end();
374  }
375 
377  HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
378  }
379 
380  uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
381 
382  bool isIRLevelProfile() const override {
383  return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
384  }
385 
387  return Symtab.create(HashTable->keys());
388  }
389 };
390 
391 /// Reader for the indexed binary instrprof format.
393 private:
394  /// The profile data file contents.
395  std::unique_ptr<MemoryBuffer> DataBuffer;
396  /// The index into the profile data.
397  std::unique_ptr<InstrProfReaderIndexBase> Index;
398  /// Profile summary data.
399  std::unique_ptr<ProfileSummary> Summary;
400  // Index to the current record in the record array.
401  unsigned RecordIndex;
402 
403  // Read the profile summary. Return a pointer pointing to one byte past the
404  // end of the summary data if it exists or the input \c Cur.
405  const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
406  const unsigned char *Cur);
407 
408 public:
409  IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
410  : DataBuffer(std::move(DataBuffer)), RecordIndex(0) {}
412  IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
413 
414  /// Return the profile version.
415  uint64_t getVersion() const { return Index->getVersion(); }
416  bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
417 
418  /// Return true if the given buffer is in an indexed instrprof format.
419  static bool hasFormat(const MemoryBuffer &DataBuffer);
420 
421  /// Read the file header.
422  Error readHeader() override;
423  /// Read a single record.
424  Error readNextRecord(NamedInstrProfRecord &Record) override;
425 
426  /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
427  Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
428  uint64_t FuncHash);
429 
430  /// Fill Counts with the profile data for the given function name.
431  Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
432  std::vector<uint64_t> &Counts);
433 
434  /// Return the maximum of all known function counts.
435  uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
436 
437  /// Factory method to create an indexed reader.
439  create(const Twine &Path);
440 
442  create(std::unique_ptr<MemoryBuffer> Buffer);
443 
444  // Used for testing purpose only.
446  Index->setValueProfDataEndianness(Endianness);
447  }
448 
449  // See description in the base class. This interface is designed
450  // to be used by llvm-profdata (for dumping). Avoid using this when
451  // the client is the compiler.
452  InstrProfSymtab &getSymtab() override;
453  ProfileSummary &getSummary() { return *(Summary.get()); }
454 };
455 
456 } // end namespace llvm
457 
458 #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
Definition: InstrProf.h:411
uint64_t getVersion() const
Return the profile version.
void setValueProfDataEndianness(support::endianness Endianness)
bool isIRLevelProfile() const override
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
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:324
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
#define error(X)
InstrProfIterator(InstrProfReader *Reader)
bool operator==(const InstrProfIterator &RHS)
bool isIRLevelProfile() const override
bool operator!=(const InstrProfIterator &RHS)
bool isEOF()
Return true if the reader has finished reading the profile data.
Definition: BitVector.h:920
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
const HashT HashType
Definition: InstrProf.h:869
static StringRef getName(Value *V)
Error populateSymtab(InstrProfSymtab &Symtab) override
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
void setValueProfDataEndianness(support::endianness Endianness)
bool isIRLevelProfile() const override
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function&#39;s PGO name from the function name&#39;s symbol address in the object file.
RawInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer)
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)
Reader for the simple text based instrprof format.
StringRef ReadKey(const unsigned char *D, offset_type N)
uint64_t getVersion() const override
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Base class and interface for reading profiling data of any known instrprof format.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::unique_ptr< InstrProfSymtab > Symtab
InstrProfIterator end()
std::vector< std::pair< uint64_t, uint64_t > > ValueMapType
Definition: InstrProf.h:617
static const unsigned End
value_type * operator->()
void advanceToNextKey() override
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:871
bool atEnd() const override
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
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.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:40
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:923
unsigned char getSwappedBytes(unsigned char C)
Definition: SwapByteOrder.h:72
Basic Alias true
TextInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer_)
Profiling information for a single function.
Definition: InstrProf.h:592
instrprof_error
Definition: InstrProf.h:280
#define N
InstrProfIterator begin()
Iterator over profile data.
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
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.
Definition: Error.h:156
support::endianness getHostEndianness()
Definition: InstrProf.h:809
IndexedInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer)
value_type & operator*()
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Reader for the indexed binary instrprof format.
void setValueProfDataEndianness(support::endianness Endianness) override
static StringRef GetExternalKey(StringRef K)
const uint64_t Version
Definition: InstrProf.h:867
Provides lookup and iteration over an on disk hash table.
bool isIRLevelProfile() const override
Error success()
Clear the current error and return a successful one.