Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/ProfileData/InstrProfReader.h
Line
Count
Source (jump to first uncovered line)
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"
20
#include "llvm/ProfileData/InstrProf.h"
21
#include "llvm/Support/Endian.h"
22
#include "llvm/Support/Error.h"
23
#include "llvm/Support/LineIterator.h"
24
#include "llvm/Support/MemoryBuffer.h"
25
#include "llvm/Support/OnDiskHashTable.h"
26
#include "llvm/Support/SwapByteOrder.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
603
  InstrProfIterator() = default;
50
301
  InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
51
52
724
  InstrProfIterator &operator++() { Increment(); return *this; }
53
  bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
54
1.02k
  bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
55
722
  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.
61
class InstrProfReader {
62
  instrprof_error LastError = instrprof_error::success;
63
64
public:
65
745
  InstrProfReader() = default;
66
737
  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.
75
301
  InstrProfIterator begin() { return InstrProfIterator(this); }
76
302
  InstrProfIterator end() { return InstrProfIterator(); }
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.
101
2.98k
  Error error(instrprof_error Err) {
102
2.98k
    LastError = Err;
103
2.98k
    if (Err == instrprof_error::success)
104
2.58k
      return Error::success();
105
399
    return make_error<InstrProfError>(Err);
106
399
  }
107
108
173
  Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
109
110
  /// Clear the current error and return a successful one.
111
2.58k
  Error success() { return error(instrprof_error::success); }
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.
121
  Error getError() {
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
131
  static Expected<std::unique_ptr<InstrProfReader>>
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.
143
class TextInstrProfReader : public InstrProfReader {
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
209
      : 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
292
  bool isIRLevelProfile() const override { return IsIRLevelProfile; }
164
165
169
  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
173
14
  InstrProfSymtab &getSymtab() override {
174
14
    assert(Symtab.get());
175
14
    return *Symtab.get();
176
14
  }
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>
187
class RawInstrProfReader : public InstrProfReader {
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;
198
  const RawInstrProf::ProfileData<IntPtrT> *Data;
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
10
      : DataBuffer(std::move(DataBuffer)) {}
llvm::RawInstrProfReader<unsigned int>::RawInstrProfReader(std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >)
Line
Count
Source
211
2
      : DataBuffer(std::move(DataBuffer)) {}
llvm::RawInstrProfReader<unsigned long long>::RawInstrProfReader(std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_delete<llvm::MemoryBuffer> >)
Line
Count
Source
211
8
      : 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
62
  bool isIRLevelProfile() const override {
220
62
    return (Version & VARIANT_MASK_IR_PROF) != 0;
221
62
  }
llvm::RawInstrProfReader<unsigned int>::isIRLevelProfile() const
Line
Count
Source
219
8
  bool isIRLevelProfile() const override {
220
8
    return (Version & VARIANT_MASK_IR_PROF) != 0;
221
8
  }
llvm::RawInstrProfReader<unsigned long long>::isIRLevelProfile() const
Line
Count
Source
219
54
  bool isIRLevelProfile() const override {
220
54
    return (Version & VARIANT_MASK_IR_PROF) != 0;
221
54
  }
222
223
0
  bool hasCSIRLevelProfile() const override {
224
0
    return (Version & VARIANT_MASK_CSIR_PROF) != 0;
225
0
  }
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned int>::hasCSIRLevelProfile() const
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned long long>::hasCSIRLevelProfile() const
226
227
0
  InstrProfSymtab &getSymtab() override {
228
0
    assert(Symtab.get());
229
0
    return *Symtab.get();
230
0
  }
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned int>::getSymtab()
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned long long>::getSymtab()
231
232
private:
233
  Error createSymtab(InstrProfSymtab &Symtab);
234
  Error readNextHeader(const char *CurrentPos);
235
  Error readHeader(const RawInstrProf::Header &Header);
236
237
300
  template <class IntT> IntT swap(IntT Int) const {
238
300
    return ShouldSwapBytes ? 
sys::getSwappedBytes(Int)40
:
Int260
;
239
300
  }
unsigned int llvm::RawInstrProfReader<unsigned int>::swap<unsigned int>(unsigned int) const
Line
Count
Source
237
12
  template <class IntT> IntT swap(IntT Int) const {
238
12
    return ShouldSwapBytes ? 
sys::getSwappedBytes(Int)6
:
Int6
;
239
12
  }
unsigned long long llvm::RawInstrProfReader<unsigned int>::swap<unsigned long long>(unsigned long long) const
Line
Count
Source
237
25
  template <class IntT> IntT swap(IntT Int) const {
238
25
    return ShouldSwapBytes ? 
sys::getSwappedBytes(Int)14
:
Int11
;
239
25
  }
unsigned long long llvm::RawInstrProfReader<unsigned long long>::swap<unsigned long long>(unsigned long long) const
Line
Count
Source
237
221
  template <class IntT> IntT swap(IntT Int) const {
238
221
    return ShouldSwapBytes ? 
sys::getSwappedBytes(Int)18
:
Int203
;
239
221
  }
unsigned int llvm::RawInstrProfReader<unsigned long long>::swap<unsigned int>(unsigned int) const
Line
Count
Source
237
42
  template <class IntT> IntT swap(IntT Int) const {
238
42
    return ShouldSwapBytes ? 
sys::getSwappedBytes(Int)2
:
Int40
;
239
42
  }
240
241
0
  support::endianness getDataEndianness() const {
242
0
    support::endianness HostEndian = getHostEndianness();
243
0
    if (!ShouldSwapBytes)
244
0
      return HostEndian;
245
0
    if (HostEndian == support::little)
246
0
      return support::big;
247
0
    else
248
0
      return support::little;
249
0
  }
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned int>::getDataEndianness() const
Unexecuted instantiation: llvm::RawInstrProfReader<unsigned long long>::getDataEndianness() const
250
251
9
  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
252
9
    return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
253
9
  }
llvm::RawInstrProfReader<unsigned int>::getNumPaddingBytes(unsigned long long)
Line
Count
Source
251
2
  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
252
2
    return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
253
2
  }
llvm::RawInstrProfReader<unsigned long long>::getNumPaddingBytes(unsigned long long)
Line
Count
Source
251
7
  inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
252
7
    return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
253
7
  }
254
255
  Error readName(NamedInstrProfRecord &Record);
256
  Error readFuncHash(NamedInstrProfRecord &Record);
257
  Error readRawCounts(InstrProfRecord &Record);
258
  Error readValueProfilingData(InstrProfRecord &Record);
259
54
  bool atEnd() const { return Data == DataEnd; }
llvm::RawInstrProfReader<unsigned int>::atEnd() const
Line
Count
Source
259
6
  bool atEnd() const { return Data == DataEnd; }
llvm::RawInstrProfReader<unsigned long long>::atEnd() const
Line
Count
Source
259
48
  bool atEnd() const { return Data == DataEnd; }
260
261
46
  void advanceData() {
262
46
    Data++;
263
46
    ValueDataStart += CurValueDataSize;
264
46
  }
llvm::RawInstrProfReader<unsigned int>::advanceData()
Line
Count
Source
261
4
  void advanceData() {
262
4
    Data++;
263
4
    ValueDataStart += CurValueDataSize;
264
4
  }
llvm::RawInstrProfReader<unsigned long long>::advanceData()
Line
Count
Source
261
42
  void advanceData() {
262
42
    Data++;
263
42
    ValueDataStart += CurValueDataSize;
264
42
  }
265
266
9
  const char *getNextHeaderPos() const {
267
9
      assert(atEnd());
268
9
      return (const char *)ValueDataStart;
269
9
  }
llvm::RawInstrProfReader<unsigned int>::getNextHeaderPos() const
Line
Count
Source
266
2
  const char *getNextHeaderPos() const {
267
2
      assert(atEnd());
268
2
      return (const char *)ValueDataStart;
269
2
  }
llvm::RawInstrProfReader<unsigned long long>::getNextHeaderPos() const
Line
Count
Source
266
7
  const char *getNextHeaderPos() const {
267
7
      assert(atEnd());
268
7
      return (const char *)ValueDataStart;
269
7
  }
270
271
46
  const uint64_t *getCounter(IntPtrT CounterPtr) const {
272
46
    ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
273
46
    return CountersStart + Offset;
274
46
  }
llvm::RawInstrProfReader<unsigned int>::getCounter(unsigned int) const
Line
Count
Source
271
4
  const uint64_t *getCounter(IntPtrT CounterPtr) const {
272
4
    ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
273
4
    return CountersStart + Offset;
274
4
  }
llvm::RawInstrProfReader<unsigned long long>::getCounter(unsigned long long) const
Line
Count
Source
271
42
  const uint64_t *getCounter(IntPtrT CounterPtr) const {
272
42
    ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
273
42
    return CountersStart + Offset;
274
42
  }
275
276
46
  StringRef getName(uint64_t NameRef) const {
277
46
    return Symtab->getFuncName(swap(NameRef));
278
46
  }
llvm::RawInstrProfReader<unsigned int>::getName(unsigned long long) const
Line
Count
Source
276
4
  StringRef getName(uint64_t NameRef) const {
277
4
    return Symtab->getFuncName(swap(NameRef));
278
4
  }
llvm::RawInstrProfReader<unsigned long long>::getName(unsigned long long) const
Line
Count
Source
276
42
  StringRef getName(uint64_t NameRef) const {
277
42
    return Symtab->getFuncName(swap(NameRef));
278
42
  }
279
};
280
281
using RawInstrProfReader32 = RawInstrProfReader<uint32_t>;
282
using RawInstrProfReader64 = RawInstrProfReader<uint64_t>;
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.
292
class InstrProfLookupTrait {
293
  std::vector<NamedInstrProfRecord> DataBuffer;
294
  IndexedInstrProf::HashT HashType;
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
525
      : HashType(HashType), FormatVersion(FormatVersion) {}
304
305
  using data_type = ArrayRef<NamedInstrProfRecord>;
306
307
  using internal_key_type = StringRef;
308
  using external_key_type = StringRef;
309
  using hash_value_type = uint64_t;
310
  using offset_type = uint64_t;
311
312
766
  static bool EqualKey(StringRef A, StringRef B) { return A == B; }
313
865
  static StringRef GetInternalKey(StringRef K) { return K; }
314
15
  static StringRef GetExternalKey(StringRef K) { return K; }
315
316
  hash_value_type ComputeHash(StringRef K);
317
318
  static std::pair<offset_type, offset_type>
319
1.52k
  ReadKeyDataLength(const unsigned char *&D) {
320
1.52k
    using namespace support;
321
1.52k
322
1.52k
    offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
323
1.52k
    offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
324
1.52k
    return std::make_pair(KeyLen, DataLen);
325
1.52k
  }
326
327
1.03k
  StringRef ReadKey(const unsigned char *D, offset_type N) {
328
1.03k
    return StringRef((const char *)D, N);
329
1.03k
  }
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.
336
2
  void setValueProfDataEndianness(support::endianness Endianness) {
337
2
    ValueProfDataEndianness = Endianness;
338
2
  }
339
};
340
341
struct InstrProfReaderIndexBase {
342
523
  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,
350
                                     ArrayRef<NamedInstrProfRecord> &Data) = 0;
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 =
361
    OnDiskIterableChainedHashTable<InstrProfLookupTrait>;
362
363
template <typename HashTableImpl>
364
class InstrProfReaderItaniumRemapper;
365
366
template <typename HashTableImpl>
367
class InstrProfReaderIndex : public InstrProfReaderIndexBase {
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,
379
                       IndexedInstrProf::HashT HashType, uint64_t Version);
380
523
  ~InstrProfReaderIndex() override = default;
381
382
  Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override;
383
  Error getRecords(StringRef FuncName,
384
                   ArrayRef<NamedInstrProfRecord> &Data) override;
385
232
  void advanceToNextKey() override { RecordIterator++; }
386
387
334
  bool atEnd() const override {
388
334
    return RecordIterator == HashTable->data_end();
389
334
  }
390
391
2
  void setValueProfDataEndianness(support::endianness Endianness) override {
392
2
    HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
393
2
  }
394
395
338
  uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
396
397
435
  bool isIRLevelProfile() const override {
398
435
    return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
399
435
  }
400
401
146
  bool hasCSIRLevelProfile() const override {
402
146
    return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
403
146
  }
404
405
4
  Error populateSymtab(InstrProfSymtab &Symtab) override {
406
4
    return Symtab.create(HashTable->keys());
407
4
  }
408
};
409
410
/// Name matcher supporting fuzzy matching of symbol names to names in profiles.
411
class InstrProfReaderRemapper {
412
public:
413
523
  virtual ~InstrProfReaderRemapper() {}
414
0
  virtual Error populateRemappings() { return Error::success(); }
415
  virtual Error getRecords(StringRef FuncName,
416
                           ArrayRef<NamedInstrProfRecord> &Data) = 0;
417
};
418
419
/// Reader for the indexed binary instrprof format.
420
class IndexedInstrProfReader : public InstrProfReader {
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:
444
  IndexedInstrProfReader(
445
      std::unique_ptr<MemoryBuffer> DataBuffer,
446
      std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr)
447
      : DataBuffer(std::move(DataBuffer)),
448
525
        RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {}
449
  IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
450
  IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
451
452
  /// Return the profile version.
453
338
  uint64_t getVersion() const { return Index->getVersion(); }
454
435
  bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
455
146
  bool hasCSIRLevelProfile() const override {
456
146
    return Index->hasCSIRLevelProfile();
457
146
  }
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
81
  uint64_t getMaximumFunctionCount(bool UseCS) {
478
81
    if (UseCS) {
479
7
      assert(CS_Summary && "No context sensitive profile summary");
480
7
      return CS_Summary->getMaxFunctionCount();
481
74
    } else {
482
74
      assert(Summary && "No profile summary");
483
74
      return Summary->getMaxFunctionCount();
484
74
    }
485
81
  }
486
487
  /// Factory method to create an indexed reader.
488
  static Expected<std::unique_ptr<IndexedInstrProfReader>>
489
  create(const Twine &Path, const Twine &RemappingPath = "");
490
491
  static Expected<std::unique_ptr<IndexedInstrProfReader>>
492
  create(std::unique_ptr<MemoryBuffer> Buffer,
493
         std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
494
495
  // Used for testing purpose only.
496
  void setValueProfDataEndianness(support::endianness Endianness) {
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
137
  ProfileSummary &getSummary(bool UseCS) {
508
137
    if (UseCS) {
509
12
      assert(CS_Summary && "No context sensitive summary");
510
12
      return *(CS_Summary.get());
511
125
    } else {
512
125
      assert(Summary && "No profile summary");
513
125
      return *(Summary.get());
514
125
    }
515
137
  }
516
};
517
518
} // end namespace llvm
519
520
#endif // LLVM_PROFILEDATA_INSTRPROFREADER_H