LLVM  9.0.0svn
InstrProfReader.h
Go to the documentation of this file.
1 //===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for reading profiling data for instrumentation
10 // based PGO and coverage.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H
15 #define LLVM_PROFILEDATA_INSTRPROFREADER_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/IR/ProfileSummary.h"
21 #include "llvm/Support/Endian.h"
22 #include "llvm/Support/Error.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstddef>
30 #include <cstdint>
31 #include <iterator>
32 #include <memory>
33 #include <utility>
34 #include <vector>
35 
36 namespace llvm {
37 
38 class InstrProfReader;
39 
40 /// A file format agnostic iterator over profiling data.
41 class InstrProfIterator : public std::iterator<std::input_iterator_tag,
42  NamedInstrProfRecord> {
43  InstrProfReader *Reader = nullptr;
44  value_type Record;
45 
46  void Increment();
47 
48 public:
49  InstrProfIterator() = default;
50  InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
51 
52  InstrProfIterator &operator++() { Increment(); return *this; }
53  bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
54  bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
55  value_type &operator*() { return Record; }
56  value_type *operator->() { return &Record; }
57 };
58 
59 /// Base class and interface for reading profiling data of any known instrprof
60 /// format. Provides an iterator over NamedInstrProfRecords.
63 
64 public:
65  InstrProfReader() = default;
66  virtual ~InstrProfReader() = default;
67 
68  /// Read the header. Required before reading first record.
69  virtual Error readHeader() = 0;
70 
71  /// Read a single record.
72  virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
73 
74  /// Iterator over profile data.
77 
78  virtual bool isIRLevelProfile() const = 0;
79 
80  virtual bool hasCSIRLevelProfile() const = 0;
81 
82  /// Return the PGO symtab. There are three different readers:
83  /// Raw, Text, and Indexed profile readers. The first two types
84  /// of readers are used only by llvm-profdata tool, while the indexed
85  /// profile reader is also used by llvm-cov tool and the compiler (
86  /// backend or frontend). Since creating PGO symtab can create
87  /// significant runtime and memory overhead (as it touches data
88  /// for the whole program), InstrProfSymtab for the indexed profile
89  /// reader should be created on demand and it is recommended to be
90  /// only used for dumping purpose with llvm-proftool, not with the
91  /// compiler.
92  virtual InstrProfSymtab &getSymtab() = 0;
93 
94 protected:
95  std::unique_ptr<InstrProfSymtab> Symtab;
96 
97  /// Set the current error and return same.
99  LastError = Err;
100  if (Err == instrprof_error::success)
101  return Error::success();
102  return make_error<InstrProfError>(Err);
103  }
104 
105  Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
106 
107  /// Clear the current error and return a successful one.
109 
110 public:
111  /// Return true if the reader has finished reading the profile data.
112  bool isEOF() { return LastError == instrprof_error::eof; }
113 
114  /// Return true if the reader encountered an error reading profiling data.
115  bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
116 
117  /// Get the current error.
119  if (hasError())
120  return make_error<InstrProfError>(LastError);
121  return Error::success();
122  }
123 
124  /// Factory method to create an appropriately typed reader for the given
125  /// instrprof file.
126  static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
127 
129  create(std::unique_ptr<MemoryBuffer> Buffer);
130 };
131 
132 /// Reader for the simple text based instrprof format.
133 ///
134 /// This format is a simple text format that's suitable for test data. Records
135 /// are separated by one or more blank lines, and record fields are separated by
136 /// new lines.
137 ///
138 /// Each record consists of a function name, a function hash, a number of
139 /// counters, and then each counter value, in that order.
141 private:
142  /// The profile data file contents.
143  std::unique_ptr<MemoryBuffer> DataBuffer;
144  /// Iterator over the profile data.
145  line_iterator Line;
146  bool IsIRLevelProfile = false;
147  bool HasCSIRLevelProfile = false;
148 
149  Error readValueProfileData(InstrProfRecord &Record);
150 
151 public:
152  TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
153  : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
154  TextInstrProfReader(const TextInstrProfReader &) = delete;
155  TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
156 
157  /// Return true if the given buffer is in text instrprof format.
158  static bool hasFormat(const MemoryBuffer &Buffer);
159 
160  bool isIRLevelProfile() const override { return IsIRLevelProfile; }
161 
162  bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; }
163 
164  /// Read the header.
165  Error readHeader() override;
166 
167  /// Read a single record.
168  Error readNextRecord(NamedInstrProfRecord &Record) override;
169 
171  assert(Symtab.get());
172  return *Symtab.get();
173  }
174 };
175 
176 /// Reader for the raw instrprof binary format from runtime.
177 ///
178 /// This format is a raw memory dump of the instrumentation-baed profiling data
179 /// from the runtime. It has no index.
180 ///
181 /// Templated on the unsigned type whose size matches pointers on the platform
182 /// that wrote the profile.
183 template <class IntPtrT>
185 private:
186  /// The profile data file contents.
187  std::unique_ptr<MemoryBuffer> DataBuffer;
188  bool ShouldSwapBytes;
189  // The value of the version field of the raw profile data header. The lower 56
190  // bits specifies the format version and the most significant 8 bits specify
191  // the variant types of the profile.
192  uint64_t Version;
193  uint64_t CountersDelta;
194  uint64_t NamesDelta;
196  const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
197  const uint64_t *CountersStart;
198  const char *NamesStart;
199  uint64_t NamesSize;
200  // After value profile is all read, this pointer points to
201  // the header of next profile data (if exists)
202  const uint8_t *ValueDataStart;
203  uint32_t ValueKindLast;
204  uint32_t CurValueDataSize;
205 
206 public:
207  RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
208  : DataBuffer(std::move(DataBuffer)) {}
209  RawInstrProfReader(const RawInstrProfReader &) = delete;
210  RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
211 
212  static bool hasFormat(const MemoryBuffer &DataBuffer);
213  Error readHeader() override;
214  Error readNextRecord(NamedInstrProfRecord &Record) override;
215 
216  bool isIRLevelProfile() const override {
217  return (Version & VARIANT_MASK_IR_PROF) != 0;
218  }
219 
220  bool hasCSIRLevelProfile() const override {
221  return (Version & VARIANT_MASK_CSIR_PROF) != 0;
222  }
223 
225  assert(Symtab.get());
226  return *Symtab.get();
227  }
228 
229 private:
230  Error createSymtab(InstrProfSymtab &Symtab);
231  Error readNextHeader(const char *CurrentPos);
232  Error readHeader(const RawInstrProf::Header &Header);
233 
234  template <class IntT> IntT swap(IntT Int) const {
235  return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
236  }
237 
238  support::endianness getDataEndianness() const {
239  support::endianness HostEndian = getHostEndianness();
240  if (!ShouldSwapBytes)
241  return HostEndian;
242  if (HostEndian == support::little)
243  return support::big;
244  else
245  return support::little;
246  }
247 
248  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
249  return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
250  }
251 
252  Error readName(NamedInstrProfRecord &Record);
253  Error readFuncHash(NamedInstrProfRecord &Record);
254  Error readRawCounts(InstrProfRecord &Record);
255  Error readValueProfilingData(InstrProfRecord &Record);
256  bool atEnd() const { return Data == DataEnd; }
257 
258  void advanceData() {
259  Data++;
260  ValueDataStart += CurValueDataSize;
261  }
262 
263  const char *getNextHeaderPos() const {
264  assert(atEnd());
265  return (const char *)ValueDataStart;
266  }
267 
268  const uint64_t *getCounter(IntPtrT CounterPtr) const {
269  ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
270  return CountersStart + Offset;
271  }
272 
273  StringRef getName(uint64_t NameRef) const {
274  return Symtab->getFuncName(swap(NameRef));
275  }
276 };
277 
280 
281 namespace IndexedInstrProf {
282 
283 enum class HashT : uint32_t;
284 
285 } // end namespace IndexedInstrProf
286 
287 /// Trait for lookups into the on-disk hash table for the binary instrprof
288 /// format.
290  std::vector<NamedInstrProfRecord> DataBuffer;
292  unsigned FormatVersion;
293  // Endianness of the input value profile data.
294  // It should be LE by default, but can be changed
295  // for testing purpose.
296  support::endianness ValueProfDataEndianness = support::little;
297 
298 public:
299  InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
300  : HashType(HashType), FormatVersion(FormatVersion) {}
301 
303 
306  using hash_value_type = uint64_t;
307  using offset_type = uint64_t;
308 
309  static bool EqualKey(StringRef A, StringRef B) { return A == B; }
310  static StringRef GetInternalKey(StringRef K) { return K; }
311  static StringRef GetExternalKey(StringRef K) { return K; }
312 
314 
315  static std::pair<offset_type, offset_type>
316  ReadKeyDataLength(const unsigned char *&D) {
317  using namespace support;
318 
319  offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
320  offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
321  return std::make_pair(KeyLen, DataLen);
322  }
323 
324  StringRef ReadKey(const unsigned char *D, offset_type N) {
325  return StringRef((const char *)D, N);
326  }
327 
328  bool readValueProfilingData(const unsigned char *&D,
329  const unsigned char *const End);
330  data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
331 
332  // Used for testing purpose only.
334  ValueProfDataEndianness = Endianness;
335  }
336 };
337 
339  virtual ~InstrProfReaderIndexBase() = default;
340 
341  // Read all the profile records with the same key pointed to the current
342  // iterator.
343  virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
344 
345  // Read all the profile records with the key equal to FuncName
346  virtual Error getRecords(StringRef FuncName,
348  virtual void advanceToNextKey() = 0;
349  virtual bool atEnd() const = 0;
350  virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
351  virtual uint64_t getVersion() const = 0;
352  virtual bool isIRLevelProfile() const = 0;
353  virtual bool hasCSIRLevelProfile() const = 0;
354  virtual Error populateSymtab(InstrProfSymtab &) = 0;
355 };
356 
357 using OnDiskHashTableImplV3 =
359 
360 template <typename HashTableImpl>
362 
363 template <typename HashTableImpl>
365 private:
366  std::unique_ptr<HashTableImpl> HashTable;
367  typename HashTableImpl::data_iterator RecordIterator;
368  uint64_t FormatVersion;
369 
370  friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
371 
372 public:
373  InstrProfReaderIndex(const unsigned char *Buckets,
374  const unsigned char *const Payload,
375  const unsigned char *const Base,
377  ~InstrProfReaderIndex() override = default;
378 
379  Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
380  Error getRecords(StringRef FuncName,
382  void advanceToNextKey() override { RecordIterator++; }
383 
384  bool atEnd() const override {
385  return RecordIterator == HashTable->data_end();
386  }
387 
389  HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
390  }
391 
392  uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
393 
394  bool isIRLevelProfile() const override {
395  return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
396  }
397 
398  bool hasCSIRLevelProfile() const override {
399  return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
400  }
401 
403  return Symtab.create(HashTable->keys());
404  }
405 };
406 
407 /// Name matcher supporting fuzzy matching of symbol names to names in profiles.
409 public:
411  virtual Error populateRemappings() { return Error::success(); }
412  virtual Error getRecords(StringRef FuncName,
414 };
415 
416 /// Reader for the indexed binary instrprof format.
418 private:
419  /// The profile data file contents.
420  std::unique_ptr<MemoryBuffer> DataBuffer;
421  /// The profile remapping file contents.
422  std::unique_ptr<MemoryBuffer> RemappingBuffer;
423  /// The index into the profile data.
424  std::unique_ptr<InstrProfReaderIndexBase> Index;
425  /// The profile remapping file contents.
426  std::unique_ptr<InstrProfReaderRemapper> Remapper;
427  /// Profile summary data.
428  std::unique_ptr<ProfileSummary> Summary;
429  /// Context sensitive profile summary data.
430  std::unique_ptr<ProfileSummary> CS_Summary;
431  // Index to the current record in the record array.
432  unsigned RecordIndex;
433 
434  // Read the profile summary. Return a pointer pointing to one byte past the
435  // end of the summary data if it exists or the input \c Cur.
436  // \c UseCS indicates whether to use the context-sensitive profile summary.
437  const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
438  const unsigned char *Cur, bool UseCS);
439 
440 public:
442  std::unique_ptr<MemoryBuffer> DataBuffer,
443  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
444  : DataBuffer(std::move(DataBuffer)),
445  RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
447  IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
448 
449  /// Return the profile version.
450  uint64_t getVersion() const { return Index->getVersion(); }
451  bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
452  bool hasCSIRLevelProfile() const override {
453  return Index->hasCSIRLevelProfile();
454  }
455 
456  /// Return true if the given buffer is in an indexed instrprof format.
457  static bool hasFormat(const MemoryBuffer &DataBuffer);
458 
459  /// Read the file header.
460  Error readHeader() override;
461  /// Read a single record.
462  Error readNextRecord(NamedInstrProfRecord &Record) override;
463 
464  /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
465  Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
466  uint64_t FuncHash);
467 
468  /// Fill Counts with the profile data for the given function name.
469  Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
470  std::vector<uint64_t> &Counts);
471 
472  /// Return the maximum of all known function counts.
473  /// \c UseCS indicates whether to use the context-sensitive count.
474  uint64_t getMaximumFunctionCount(bool UseCS) {
475  if (UseCS) {
476  assert(CS_Summary && "No context sensitive profile summary");
477  return CS_Summary->getMaxFunctionCount();
478  } else {
479  assert(Summary && "No profile summary");
480  return Summary->getMaxFunctionCount();
481  }
482  }
483 
484  /// Factory method to create an indexed reader.
486  create(const Twine &Path, const Twine &RemappingPath = "");
487 
489  create(std::unique_ptr<MemoryBuffer> Buffer,
490  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
491 
492  // Used for testing purpose only.
494  Index->setValueProfDataEndianness(Endianness);
495  }
496 
497  // See description in the base class. This interface is designed
498  // to be used by llvm-profdata (for dumping). Avoid using this when
499  // the client is the compiler.
500  InstrProfSymtab &getSymtab() override;
501 
502  /// Return the profile summary.
503  /// \c UseCS indicates whether to use the context-sensitive summary.
504  ProfileSummary &getSummary(bool UseCS) {
505  if (UseCS) {
506  assert(CS_Summary && "No context sensitive summary");
507  return *(CS_Summary.get());
508  } else {
509  assert(Summary && "No profile summary");
510  return *(Summary.get());
511  }
512  }
513 };
514 
515 } // end namespace llvm
516 
517 #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:410
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:23
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:323
bool hasCSIRLevelProfile() const override
A remapper that applies remappings based on a symbol remapping file.
Error error(instrprof_error Err)
Set the current error and return same.
A forward iterator which reads text lines from a buffer.
Definition: LineIterator.h:31
#define error(X)
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:24
block Block Frequency true
InstrProfIterator(InstrProfReader *Reader)
ProfileSummary & getSummary(bool UseCS)
Return the profile summary.
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:937
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
const HashT HashType
Definition: InstrProf.h:906
static StringRef getName(Value *V)
Error populateSymtab(InstrProfSymtab &Symtab) override
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
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:32
static std::pair< offset_type, offset_type > ReadKeyDataLength(const unsigned char *&D)
Reader for the simple text based instrprof format.
bool hasCSIRLevelProfile() const override
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:908
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:326
Trait for lookups into the on-disk hash table for the binary instrprof format.
uint64_t getMaximumFunctionCount(bool UseCS)
Return the maximum of all known function counts.
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:41
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:940
bool hasCSIRLevelProfile() const override
unsigned char getSwappedBytes(unsigned char C)
Definition: SwapByteOrder.h:72
TextInstrProfReader(std::unique_ptr< MemoryBuffer > DataBuffer_)
bool hasCSIRLevelProfile() const override
Profiling information for a single function.
Definition: InstrProf.h:621
instrprof_error
Definition: InstrProf.h:279
#define N
InstrProfIterator begin()
Iterator over profile data.
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
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:157
support::endianness getHostEndianness()
Definition: InstrProf.h:846
value_type & operator*()
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
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:904
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.