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  /// Compute the sum of counts and return in Sum.
95  void accumuateCounts(CountSumOrPercent &Sum, bool IsCS);
96 
97 protected:
98  std::unique_ptr<InstrProfSymtab> Symtab;
99 
100  /// Set the current error and return same.
102  LastError = Err;
103  if (Err == instrprof_error::success)
104  return Error::success();
105  return make_error<InstrProfError>(Err);
106  }
107 
108  Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
109 
110  /// Clear the current error and return a successful one.
112 
113 public:
114  /// Return true if the reader has finished reading the profile data.
115  bool isEOF() { return LastError == instrprof_error::eof; }
116 
117  /// Return true if the reader encountered an error reading profiling data.
118  bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
119 
120  /// Get the current error.
122  if (hasError())
123  return make_error<InstrProfError>(LastError);
124  return Error::success();
125  }
126 
127  /// Factory method to create an appropriately typed reader for the given
128  /// instrprof file.
129  static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
130 
132  create(std::unique_ptr<MemoryBuffer> Buffer);
133 };
134 
135 /// Reader for the simple text based instrprof format.
136 ///
137 /// This format is a simple text format that's suitable for test data. Records
138 /// are separated by one or more blank lines, and record fields are separated by
139 /// new lines.
140 ///
141 /// Each record consists of a function name, a function hash, a number of
142 /// counters, and then each counter value, in that order.
144 private:
145  /// The profile data file contents.
146  std::unique_ptr<MemoryBuffer> DataBuffer;
147  /// Iterator over the profile data.
148  line_iterator Line;
149  bool IsIRLevelProfile = false;
150  bool HasCSIRLevelProfile = false;
151 
152  Error readValueProfileData(InstrProfRecord &Record);
153 
154 public:
155  TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
156  : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
157  TextInstrProfReader(const TextInstrProfReader &) = delete;
158  TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
159 
160  /// Return true if the given buffer is in text instrprof format.
161  static bool hasFormat(const MemoryBuffer &Buffer);
162 
163  bool isIRLevelProfile() const override { return IsIRLevelProfile; }
164 
165  bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; }
166 
167  /// Read the header.
168  Error readHeader() override;
169 
170  /// Read a single record.
171  Error readNextRecord(NamedInstrProfRecord &Record) override;
172 
174  assert(Symtab.get());
175  return *Symtab.get();
176  }
177 };
178 
179 /// Reader for the raw instrprof binary format from runtime.
180 ///
181 /// This format is a raw memory dump of the instrumentation-baed profiling data
182 /// from the runtime. It has no index.
183 ///
184 /// Templated on the unsigned type whose size matches pointers on the platform
185 /// that wrote the profile.
186 template <class IntPtrT>
188 private:
189  /// The profile data file contents.
190  std::unique_ptr<MemoryBuffer> DataBuffer;
191  bool ShouldSwapBytes;
192  // The value of the version field of the raw profile data header. The lower 56
193  // bits specifies the format version and the most significant 8 bits specify
194  // the variant types of the profile.
195  uint64_t Version;
196  uint64_t CountersDelta;
197  uint64_t NamesDelta;
199  const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
200  const uint64_t *CountersStart;
201  const char *NamesStart;
202  uint64_t NamesSize;
203  // After value profile is all read, this pointer points to
204  // the header of next profile data (if exists)
205  const uint8_t *ValueDataStart;
206  uint32_t ValueKindLast;
207  uint32_t CurValueDataSize;
208 
209 public:
210  RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
211  : DataBuffer(std::move(DataBuffer)) {}
212  RawInstrProfReader(const RawInstrProfReader &) = delete;
213  RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
214 
215  static bool hasFormat(const MemoryBuffer &DataBuffer);
216  Error readHeader() override;
217  Error readNextRecord(NamedInstrProfRecord &Record) override;
218 
219  bool isIRLevelProfile() const override {
220  return (Version & VARIANT_MASK_IR_PROF) != 0;
221  }
222 
223  bool hasCSIRLevelProfile() const override {
224  return (Version & VARIANT_MASK_CSIR_PROF) != 0;
225  }
226 
228  assert(Symtab.get());
229  return *Symtab.get();
230  }
231 
232 private:
233  Error createSymtab(InstrProfSymtab &Symtab);
234  Error readNextHeader(const char *CurrentPos);
235  Error readHeader(const RawInstrProf::Header &Header);
236 
237  template <class IntT> IntT swap(IntT Int) const {
238  return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
239  }
240 
241  support::endianness getDataEndianness() const {
242  support::endianness HostEndian = getHostEndianness();
243  if (!ShouldSwapBytes)
244  return HostEndian;
245  if (HostEndian == support::little)
246  return support::big;
247  else
248  return support::little;
249  }
250 
251  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
252  return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
253  }
254 
255  Error readName(NamedInstrProfRecord &Record);
256  Error readFuncHash(NamedInstrProfRecord &Record);
257  Error readRawCounts(InstrProfRecord &Record);
258  Error readValueProfilingData(InstrProfRecord &Record);
259  bool atEnd() const { return Data == DataEnd; }
260 
261  void advanceData() {
262  Data++;
263  ValueDataStart += CurValueDataSize;
264  }
265 
266  const char *getNextHeaderPos() const {
267  assert(atEnd());
268  return (const char *)ValueDataStart;
269  }
270 
271  const uint64_t *getCounter(IntPtrT CounterPtr) const {
272  ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
273  return CountersStart + Offset;
274  }
275 
276  StringRef getName(uint64_t NameRef) const {
277  return Symtab->getFuncName(swap(NameRef));
278  }
279 };
280 
283 
284 namespace IndexedInstrProf {
285 
286 enum class HashT : uint32_t;
287 
288 } // end namespace IndexedInstrProf
289 
290 /// Trait for lookups into the on-disk hash table for the binary instrprof
291 /// format.
293  std::vector<NamedInstrProfRecord> DataBuffer;
295  unsigned FormatVersion;
296  // Endianness of the input value profile data.
297  // It should be LE by default, but can be changed
298  // for testing purpose.
299  support::endianness ValueProfDataEndianness = support::little;
300 
301 public:
302  InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
303  : HashType(HashType), FormatVersion(FormatVersion) {}
304 
306 
309  using hash_value_type = uint64_t;
310  using offset_type = uint64_t;
311 
312  static bool EqualKey(StringRef A, StringRef B) { return A == B; }
313  static StringRef GetInternalKey(StringRef K) { return K; }
314  static StringRef GetExternalKey(StringRef K) { return K; }
315 
317 
318  static std::pair<offset_type, offset_type>
319  ReadKeyDataLength(const unsigned char *&D) {
320  using namespace support;
321 
322  offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
323  offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
324  return std::make_pair(KeyLen, DataLen);
325  }
326 
327  StringRef ReadKey(const unsigned char *D, offset_type N) {
328  return StringRef((const char *)D, N);
329  }
330 
331  bool readValueProfilingData(const unsigned char *&D,
332  const unsigned char *const End);
333  data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
334 
335  // Used for testing purpose only.
337  ValueProfDataEndianness = Endianness;
338  }
339 };
340 
342  virtual ~InstrProfReaderIndexBase() = default;
343 
344  // Read all the profile records with the same key pointed to the current
345  // iterator.
346  virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0;
347 
348  // Read all the profile records with the key equal to FuncName
349  virtual Error getRecords(StringRef FuncName,
351  virtual void advanceToNextKey() = 0;
352  virtual bool atEnd() const = 0;
353  virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
354  virtual uint64_t getVersion() const = 0;
355  virtual bool isIRLevelProfile() const = 0;
356  virtual bool hasCSIRLevelProfile() const = 0;
357  virtual Error populateSymtab(InstrProfSymtab &) = 0;
358 };
359 
360 using OnDiskHashTableImplV3 =
362 
363 template <typename HashTableImpl>
365 
366 template <typename HashTableImpl>
368 private:
369  std::unique_ptr<HashTableImpl> HashTable;
370  typename HashTableImpl::data_iterator RecordIterator;
371  uint64_t FormatVersion;
372 
373  friend class InstrProfReaderItaniumRemapper<HashTableImpl>;
374 
375 public:
376  InstrProfReaderIndex(const unsigned char *Buckets,
377  const unsigned char *const Payload,
378  const unsigned char *const Base,
380  ~InstrProfReaderIndex() override = default;
381 
382  Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
383  Error getRecords(StringRef FuncName,
385  void advanceToNextKey() override { RecordIterator++; }
386 
387  bool atEnd() const override {
388  return RecordIterator == HashTable->data_end();
389  }
390 
392  HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
393  }
394 
395  uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
396 
397  bool isIRLevelProfile() const override {
398  return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
399  }
400 
401  bool hasCSIRLevelProfile() const override {
402  return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
403  }
404 
406  return Symtab.create(HashTable->keys());
407  }
408 };
409 
410 /// Name matcher supporting fuzzy matching of symbol names to names in profiles.
412 public:
414  virtual Error populateRemappings() { return Error::success(); }
415  virtual Error getRecords(StringRef FuncName,
417 };
418 
419 /// Reader for the indexed binary instrprof format.
421 private:
422  /// The profile data file contents.
423  std::unique_ptr<MemoryBuffer> DataBuffer;
424  /// The profile remapping file contents.
425  std::unique_ptr<MemoryBuffer> RemappingBuffer;
426  /// The index into the profile data.
427  std::unique_ptr<InstrProfReaderIndexBase> Index;
428  /// The profile remapping file contents.
429  std::unique_ptr<InstrProfReaderRemapper> Remapper;
430  /// Profile summary data.
431  std::unique_ptr<ProfileSummary> Summary;
432  /// Context sensitive profile summary data.
433  std::unique_ptr<ProfileSummary> CS_Summary;
434  // Index to the current record in the record array.
435  unsigned RecordIndex;
436 
437  // Read the profile summary. Return a pointer pointing to one byte past the
438  // end of the summary data if it exists or the input \c Cur.
439  // \c UseCS indicates whether to use the context-sensitive profile summary.
440  const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
441  const unsigned char *Cur, bool UseCS);
442 
443 public:
445  std::unique_ptr<MemoryBuffer> DataBuffer,
446  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
447  : DataBuffer(std::move(DataBuffer)),
448  RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
450  IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
451 
452  /// Return the profile version.
453  uint64_t getVersion() const { return Index->getVersion(); }
454  bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
455  bool hasCSIRLevelProfile() const override {
456  return Index->hasCSIRLevelProfile();
457  }
458 
459  /// Return true if the given buffer is in an indexed instrprof format.
460  static bool hasFormat(const MemoryBuffer &DataBuffer);
461 
462  /// Read the file header.
463  Error readHeader() override;
464  /// Read a single record.
465  Error readNextRecord(NamedInstrProfRecord &Record) override;
466 
467  /// Return the NamedInstrProfRecord associated with FuncName and FuncHash
468  Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
469  uint64_t FuncHash);
470 
471  /// Fill Counts with the profile data for the given function name.
472  Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
473  std::vector<uint64_t> &Counts);
474 
475  /// Return the maximum of all known function counts.
476  /// \c UseCS indicates whether to use the context-sensitive count.
477  uint64_t getMaximumFunctionCount(bool UseCS) {
478  if (UseCS) {
479  assert(CS_Summary && "No context sensitive profile summary");
480  return CS_Summary->getMaxFunctionCount();
481  } else {
482  assert(Summary && "No profile summary");
483  return Summary->getMaxFunctionCount();
484  }
485  }
486 
487  /// Factory method to create an indexed reader.
489  create(const Twine &Path, const Twine &RemappingPath = "");
490 
492  create(std::unique_ptr<MemoryBuffer> Buffer,
493  std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
494 
495  // Used for testing purpose only.
497  Index->setValueProfDataEndianness(Endianness);
498  }
499 
500  // See description in the base class. This interface is designed
501  // to be used by llvm-profdata (for dumping). Avoid using this when
502  // the client is the compiler.
503  InstrProfSymtab &getSymtab() override;
504 
505  /// Return the profile summary.
506  /// \c UseCS indicates whether to use the context-sensitive summary.
507  ProfileSummary &getSummary(bool UseCS) {
508  if (UseCS) {
509  assert(CS_Summary && "No context sensitive summary");
510  return *(CS_Summary.get());
511  } else {
512  assert(Summary && "No profile summary");
513  return *(Summary.get());
514  }
515  }
516 };
517 
518 } // end namespace llvm
519 
520 #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:986
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:988
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:689
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:926
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:984
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.