LLVM  8.0.1
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 public:
203  RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
204  : DataBuffer(std::move(DataBuffer)) {}
205  RawInstrProfReader(const RawInstrProfReader &) = delete;
206  RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
207 
208  static bool hasFormat(const MemoryBuffer &DataBuffer);
209  Error readHeader() override;
210  Error readNextRecord(NamedInstrProfRecord &Record) override;
211 
212  bool isIRLevelProfile() const override {
213  return (Version & VARIANT_MASK_IR_PROF) != 0;
214  }
215 
217  assert(Symtab.get());
218  return *Symtab.get();
219  }
220 
221 private:
222  Error createSymtab(InstrProfSymtab &Symtab);
223  Error readNextHeader(const char *CurrentPos);
224  Error readHeader(const RawInstrProf::Header &Header);
225 
226  template <class IntT> IntT swap(IntT Int) const {
227  return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
228  }
229 
230  support::endianness getDataEndianness() const {
231  support::endianness HostEndian = getHostEndianness();
232  if (!ShouldSwapBytes)
233  return HostEndian;
234  if (HostEndian == support::little)
235  return support::big;
236  else
237  return support::little;
238  }
239 
240  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
241  return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
242  }
243 
244  Error readName(NamedInstrProfRecord &Record);
245  Error readFuncHash(NamedInstrProfRecord &Record);
246  Error readRawCounts(InstrProfRecord &Record);
247  Error readValueProfilingData(InstrProfRecord &Record);
248  bool atEnd() const { return Data == DataEnd; }
249 
250  void advanceData() {
251  Data++;
252  ValueDataStart += CurValueDataSize;
253  }
254 
255  const char *getNextHeaderPos() const {
256  assert(atEnd());
257  return (const char *)ValueDataStart;
258  }
259 
260  const uint64_t *getCounter(IntPtrT CounterPtr) const {
261  ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
262  return CountersStart + Offset;
263  }
264 
265  StringRef getName(uint64_t NameRef) const {
266  return Symtab->getFuncName(swap(NameRef));
267  }
268 };
269 
272 
273 namespace IndexedInstrProf {
274 
275 enum class HashT : uint32_t;
276 
277 } // end namespace IndexedInstrProf
278 
279 /// Trait for lookups into the on-disk hash table for the binary instrprof
280 /// format.
282  std::vector<NamedInstrProfRecord> DataBuffer;
284  unsigned FormatVersion;
285  // Endianness of the input value profile data.
286  // It should be LE by default, but can be changed
287  // for testing purpose.
288  support::endianness ValueProfDataEndianness = support::little;
289 
290 public:
291  InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
292  : HashType(HashType), FormatVersion(FormatVersion) {}
293 
295 
298  using hash_value_type = uint64_t;
299  using offset_type = uint64_t;
300 
301  static bool EqualKey(StringRef A, StringRef B) { return A == B; }
302  static StringRef GetInternalKey(StringRef K) { return K; }
303  static StringRef GetExternalKey(StringRef K) { return K; }
304 
306 
307  static std::pair<offset_type, offset_type>
308  ReadKeyDataLength(const unsigned char *&D) {
309  using namespace support;
310 
311  offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
312  offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
313  return std::make_pair(KeyLen, DataLen);
314  }
315 
316  StringRef ReadKey(const unsigned char *D, offset_type N) {
317  return StringRef((const char *)D, N);
318  }
319 
320  bool readValueProfilingData(const unsigned char *&D,
321  const unsigned char *const End);
322  data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
323 
324  // Used for testing purpose only.
326  ValueProfDataEndianness = Endianness;
327  }
328 };
329 
331  virtual ~InstrProfReaderIndexBase() = default;
332 
333  // Read all the profile records with the same key pointed to the current
334  // iterator.
335  virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
336 
337  // Read all the profile records with the key equal to FuncName
338  virtual Error getRecords(StringRef FuncName,
340  virtual void advanceToNextKey() = 0;
341  virtual bool atEnd() const = 0;
342  virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
343  virtual uint64_t getVersion() const = 0;
344  virtual bool isIRLevelProfile() const = 0;
345  virtual Error populateSymtab(InstrProfSymtab &) = 0;
346 };
347 
348 using OnDiskHashTableImplV3 =
350 
351 template <typename HashTableImpl>
353 
354 template <typename HashTableImpl>
356 private:
357  std::unique_ptr<HashTableImpl> HashTable;
358  typename HashTableImpl::data_iterator RecordIterator;
359  uint64_t FormatVersion;
360 
361  friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
362 
363 public:
364  InstrProfReaderIndex(const unsigned char *Buckets,
365  const unsigned char *const Payload,
366  const unsigned char *const Base,
368  ~InstrProfReaderIndex() override = default;
369 
370  Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
371  Error getRecords(StringRef FuncName,
373  void advanceToNextKey() override { RecordIterator++; }
374 
375  bool atEnd() const override {
376  return RecordIterator == HashTable->data_end();
377  }
378 
380  HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
381  }
382 
383  uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
384 
385  bool isIRLevelProfile() const override {
386  return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
387  }
388 
390  return Symtab.create(HashTable->keys());
391  }
392 };
393 
394 /// Name matcher supporting fuzzy matching of symbol names to names in profiles.
396 public:
398  virtual Error populateRemappings() { return Error::success(); }
399  virtual Error getRecords(StringRef FuncName,
401 };
402 
403 /// Reader for the indexed binary instrprof format.
405 private:
406  /// The profile data file contents.
407  std::unique_ptr<MemoryBuffer> DataBuffer;
408  /// The profile remapping file contents.
409  std::unique_ptr<MemoryBuffer> RemappingBuffer;
410  /// The index into the profile data.
411  std::unique_ptr<InstrProfReaderIndexBase> Index;
412  /// The profile remapping file contents.
413  std::unique_ptr<InstrProfReaderRemapper> Remapper;
414  /// Profile summary data.
415  std::unique_ptr<ProfileSummary> Summary;
416  // Index to the current record in the record array.
417  unsigned RecordIndex;
418 
419  // Read the profile summary. Return a pointer pointing to one byte past the
420  // end of the summary data if it exists or the input \c Cur.
421  const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
422  const unsigned char *Cur);
423 
424 public:
426  std::unique_ptr<MemoryBuffer> DataBuffer,
427  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
428  : DataBuffer(std::move(DataBuffer)),
429  RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
431  IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
432 
433  /// Return the profile version.
434  uint64_t getVersion() const { return Index->getVersion(); }
435  bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
436 
437  /// Return true if the given buffer is in an indexed instrprof format.
438  static bool hasFormat(const MemoryBuffer &DataBuffer);
439 
440  /// Read the file header.
441  Error readHeader() override;
442  /// Read a single record.
443  Error readNextRecord(NamedInstrProfRecord &Record) override;
444 
445  /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
446  Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
447  uint64_t FuncHash);
448 
449  /// Fill Counts with the profile data for the given function name.
450  Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
451  std::vector<uint64_t> &Counts);
452 
453  /// Return the maximum of all known function counts.
454  uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
455 
456  /// Factory method to create an indexed reader.
458  create(const Twine &Path, const Twine &RemappingPath = "");
459 
461  create(std::unique_ptr<MemoryBuffer> Buffer,
462  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
463 
464  // Used for testing purpose only.
466  Index->setValueProfDataEndianness(Endianness);
467  }
468 
469  // See description in the base class. This interface is designed
470  // to be used by llvm-profdata (for dumping). Avoid using this when
471  // the client is the compiler.
472  InstrProfSymtab &getSymtab() override;
473  ProfileSummary &getSummary() { return *(Summary.get()); }
474 };
475 
476 } // end namespace llvm
477 
478 #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
This class represents lattice values for constants.
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
A remapper that applies remappings based on a symbol remapping file.
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)
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:25
block Block Frequency true
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:938
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
const HashT HashType
Definition: InstrProf.h:897
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()
value_type * operator->()
void advanceToNextKey() override
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:899
bool atEnd() const override
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
Name matcher supporting fuzzy matching of symbol names to names in profiles.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
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:42
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:941
unsigned char getSwappedBytes(unsigned char C)
Definition: SwapByteOrder.h:72
TextInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer_)
Profiling information for a single function.
Definition: InstrProf.h:622
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)
IndexedInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer, std::unique_ptr< MemoryBuffer > RemappingBuffer=nullptr)
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:158
support::endianness getHostEndianness()
Definition: InstrProf.h:837
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)
Error error(Error &&E)
const uint64_t Version
Definition: InstrProf.h:895
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.