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/ProfileData/InstrProfCorrelator.h" 22 #include "llvm/Support/Endian.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/LineIterator.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/OnDiskHashTable.h" 27 #include "llvm/Support/SwapByteOrder.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 { 43 public: 44 using iterator_category = std::input_iterator_tag; 45 using value_type = NamedInstrProfRecord; 46 using difference_type = std::ptrdiff_t; 47 using pointer = value_type *; 48 using reference = value_type &; 49 50 private: 51 InstrProfReader *Reader = nullptr; 52 value_type Record; 53 54 void Increment(); 55 56 public: 57 InstrProfIterator() = default; 58 InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } 59 60 InstrProfIterator &operator++() { Increment(); return *this; } 61 bool operator==(const InstrProfIterator &RHS) const { 62 return Reader == RHS.Reader; 63 } 64 bool operator!=(const InstrProfIterator &RHS) const { 65 return Reader != RHS.Reader; 66 } 67 value_type &operator*() { return Record; } 68 value_type *operator->() { return &Record; } 69 }; 70 71 /// Base class and interface for reading profiling data of any known instrprof 72 /// format. Provides an iterator over NamedInstrProfRecords. 73 class InstrProfReader { 74 instrprof_error LastError = instrprof_error::success; 75 std::string LastErrorMsg; 76 77 public: 78 InstrProfReader() = default; 79 virtual ~InstrProfReader() = default; 80 81 /// Read the header. Required before reading first record. 82 virtual Error readHeader() = 0; 83 84 /// Read a single record. 85 virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0; 86 87 /// Print binary ids on stream OS. 88 virtual Error printBinaryIds(raw_ostream &OS) { return success(); }; 89 90 /// Iterator over profile data. 91 InstrProfIterator begin() { return InstrProfIterator(this); } 92 InstrProfIterator end() { return InstrProfIterator(); } 93 94 virtual bool isIRLevelProfile() const = 0; 95 96 virtual bool hasCSIRLevelProfile() const = 0; 97 98 virtual bool instrEntryBBEnabled() const = 0; 99 100 /// Return true if we must provide debug info to create PGO profiles. 101 virtual bool useDebugInfoCorrelate() const { return false; } 102 103 /// Return true if the profile has single byte counters representing coverage. 104 virtual bool hasSingleByteCoverage() const = 0; 105 106 /// Return true if the profile only instruments function entries. 107 virtual bool functionEntryOnly() const = 0; 108 109 /// Returns a BitsetEnum describing the attributes of the profile. To check 110 /// individual attributes prefer using the helpers above. 111 virtual InstrProfKind getProfileKind() const = 0; 112 113 /// Return the PGO symtab. There are three different readers: 114 /// Raw, Text, and Indexed profile readers. The first two types 115 /// of readers are used only by llvm-profdata tool, while the indexed 116 /// profile reader is also used by llvm-cov tool and the compiler ( 117 /// backend or frontend). Since creating PGO symtab can create 118 /// significant runtime and memory overhead (as it touches data 119 /// for the whole program), InstrProfSymtab for the indexed profile 120 /// reader should be created on demand and it is recommended to be 121 /// only used for dumping purpose with llvm-proftool, not with the 122 /// compiler. 123 virtual InstrProfSymtab &getSymtab() = 0; 124 125 /// Compute the sum of counts and return in Sum. 126 void accumulateCounts(CountSumOrPercent &Sum, bool IsCS); 127 128 protected: 129 std::unique_ptr<InstrProfSymtab> Symtab; 130 131 /// Set the current error and return same. 132 Error error(instrprof_error Err, const std::string &ErrMsg = "") { 133 LastError = Err; 134 LastErrorMsg = ErrMsg; 135 if (Err == instrprof_error::success) 136 return Error::success(); 137 return make_error<InstrProfError>(Err, ErrMsg); 138 } 139 140 Error error(Error &&E) { 141 handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { 142 LastError = IPE.get(); 143 LastErrorMsg = IPE.getMessage(); 144 }); 145 return make_error<InstrProfError>(LastError, LastErrorMsg); 146 } 147 148 /// Clear the current error and return a successful one. 149 Error success() { return error(instrprof_error::success); } 150 151 public: 152 /// Return true if the reader has finished reading the profile data. 153 bool isEOF() { return LastError == instrprof_error::eof; } 154 155 /// Return true if the reader encountered an error reading profiling data. 156 bool hasError() { return LastError != instrprof_error::success && !isEOF(); } 157 158 /// Get the current error. 159 Error getError() { 160 if (hasError()) 161 return make_error<InstrProfError>(LastError, LastErrorMsg); 162 return Error::success(); 163 } 164 165 /// Factory method to create an appropriately typed reader for the given 166 /// instrprof file. 167 static Expected<std::unique_ptr<InstrProfReader>> 168 create(const Twine &Path, const InstrProfCorrelator *Correlator = nullptr); 169 170 static Expected<std::unique_ptr<InstrProfReader>> 171 create(std::unique_ptr<MemoryBuffer> Buffer, 172 const InstrProfCorrelator *Correlator = nullptr); 173 }; 174 175 /// Reader for the simple text based instrprof format. 176 /// 177 /// This format is a simple text format that's suitable for test data. Records 178 /// are separated by one or more blank lines, and record fields are separated by 179 /// new lines. 180 /// 181 /// Each record consists of a function name, a function hash, a number of 182 /// counters, and then each counter value, in that order. 183 class TextInstrProfReader : public InstrProfReader { 184 private: 185 /// The profile data file contents. 186 std::unique_ptr<MemoryBuffer> DataBuffer; 187 /// Iterator over the profile data. 188 line_iterator Line; 189 /// The attributes of the current profile. 190 InstrProfKind ProfileKind = InstrProfKind::Unknown; 191 192 Error readValueProfileData(InstrProfRecord &Record); 193 194 public: 195 TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) 196 : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} 197 TextInstrProfReader(const TextInstrProfReader &) = delete; 198 TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; 199 200 /// Return true if the given buffer is in text instrprof format. 201 static bool hasFormat(const MemoryBuffer &Buffer); 202 203 bool isIRLevelProfile() const override { 204 return static_cast<bool>(ProfileKind & InstrProfKind::IR); 205 } 206 207 bool hasCSIRLevelProfile() const override { 208 return static_cast<bool>(ProfileKind & InstrProfKind::CS); 209 } 210 211 bool instrEntryBBEnabled() const override { 212 return static_cast<bool>(ProfileKind & InstrProfKind::BB); 213 } 214 215 bool hasSingleByteCoverage() const override { 216 return static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage); 217 } 218 219 bool functionEntryOnly() const override { 220 return static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly); 221 } 222 223 InstrProfKind getProfileKind() const override { return ProfileKind; } 224 225 /// Read the header. 226 Error readHeader() override; 227 228 /// Read a single record. 229 Error readNextRecord(NamedInstrProfRecord &Record) override; 230 231 InstrProfSymtab &getSymtab() override { 232 assert(Symtab.get()); 233 return *Symtab.get(); 234 } 235 }; 236 237 /// Reader for the raw instrprof binary format from runtime. 238 /// 239 /// This format is a raw memory dump of the instrumentation-based profiling data 240 /// from the runtime. It has no index. 241 /// 242 /// Templated on the unsigned type whose size matches pointers on the platform 243 /// that wrote the profile. 244 template <class IntPtrT> 245 class RawInstrProfReader : public InstrProfReader { 246 private: 247 /// The profile data file contents. 248 std::unique_ptr<MemoryBuffer> DataBuffer; 249 /// If available, this hold the ProfileData array used to correlate raw 250 /// instrumentation data to their functions. 251 const InstrProfCorrelatorImpl<IntPtrT> *Correlator; 252 bool ShouldSwapBytes; 253 // The value of the version field of the raw profile data header. The lower 56 254 // bits specifies the format version and the most significant 8 bits specify 255 // the variant types of the profile. 256 uint64_t Version; 257 uint64_t CountersDelta; 258 uint64_t NamesDelta; 259 const RawInstrProf::ProfileData<IntPtrT> *Data; 260 const RawInstrProf::ProfileData<IntPtrT> *DataEnd; 261 const char *CountersStart; 262 const char *CountersEnd; 263 const char *NamesStart; 264 const char *NamesEnd; 265 // After value profile is all read, this pointer points to 266 // the header of next profile data (if exists) 267 const uint8_t *ValueDataStart; 268 uint32_t ValueKindLast; 269 uint32_t CurValueDataSize; 270 271 uint64_t BinaryIdsSize; 272 const uint8_t *BinaryIdsStart; 273 274 public: 275 RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer, 276 const InstrProfCorrelator *Correlator) 277 : DataBuffer(std::move(DataBuffer)), 278 Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>( 279 Correlator)) {} 280 RawInstrProfReader(const RawInstrProfReader &) = delete; 281 RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; 282 283 static bool hasFormat(const MemoryBuffer &DataBuffer); 284 Error readHeader() override; 285 Error readNextRecord(NamedInstrProfRecord &Record) override; 286 Error printBinaryIds(raw_ostream &OS) override; 287 288 bool isIRLevelProfile() const override { 289 return (Version & VARIANT_MASK_IR_PROF) != 0; 290 } 291 292 bool hasCSIRLevelProfile() const override { 293 return (Version & VARIANT_MASK_CSIR_PROF) != 0; 294 } 295 296 bool instrEntryBBEnabled() const override { 297 return (Version & VARIANT_MASK_INSTR_ENTRY) != 0; 298 } 299 300 bool useDebugInfoCorrelate() const override { 301 return (Version & VARIANT_MASK_DBG_CORRELATE) != 0; 302 } 303 304 bool hasSingleByteCoverage() const override { 305 return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0; 306 } 307 308 bool functionEntryOnly() const override { 309 return (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0; 310 } 311 312 /// Returns a BitsetEnum describing the attributes of the raw instr profile. 313 InstrProfKind getProfileKind() const override; 314 315 InstrProfSymtab &getSymtab() override { 316 assert(Symtab.get()); 317 return *Symtab.get(); 318 } 319 320 private: 321 Error createSymtab(InstrProfSymtab &Symtab); 322 Error readNextHeader(const char *CurrentPos); 323 Error readHeader(const RawInstrProf::Header &Header); 324 325 template <class IntT> IntT swap(IntT Int) const { 326 return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; 327 } 328 329 support::endianness getDataEndianness() const { 330 support::endianness HostEndian = getHostEndianness(); 331 if (!ShouldSwapBytes) 332 return HostEndian; 333 if (HostEndian == support::little) 334 return support::big; 335 else 336 return support::little; 337 } 338 339 inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { 340 return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); 341 } 342 343 Error readName(NamedInstrProfRecord &Record); 344 Error readFuncHash(NamedInstrProfRecord &Record); 345 Error readRawCounts(InstrProfRecord &Record); 346 Error readValueProfilingData(InstrProfRecord &Record); 347 bool atEnd() const { return Data == DataEnd; } 348 349 void advanceData() { 350 // `CountersDelta` is a constant zero when using debug info correlation. 351 if (!Correlator) { 352 // The initial CountersDelta is the in-memory address difference between 353 // the data and counts sections: 354 // start(__llvm_prf_cnts) - start(__llvm_prf_data) 355 // As we advance to the next record, we maintain the correct CountersDelta 356 // with respect to the next record. 357 CountersDelta -= sizeof(*Data); 358 } 359 Data++; 360 ValueDataStart += CurValueDataSize; 361 } 362 363 const char *getNextHeaderPos() const { 364 assert(atEnd()); 365 return (const char *)ValueDataStart; 366 } 367 368 StringRef getName(uint64_t NameRef) const { 369 return Symtab->getFuncName(swap(NameRef)); 370 } 371 372 int getCounterTypeSize() const { 373 return hasSingleByteCoverage() ? sizeof(uint8_t) : sizeof(uint64_t); 374 } 375 }; 376 377 using RawInstrProfReader32 = RawInstrProfReader<uint32_t>; 378 using RawInstrProfReader64 = RawInstrProfReader<uint64_t>; 379 380 namespace IndexedInstrProf { 381 382 enum class HashT : uint32_t; 383 384 } // end namespace IndexedInstrProf 385 386 /// Trait for lookups into the on-disk hash table for the binary instrprof 387 /// format. 388 class InstrProfLookupTrait { 389 std::vector<NamedInstrProfRecord> DataBuffer; 390 IndexedInstrProf::HashT HashType; 391 unsigned FormatVersion; 392 // Endianness of the input value profile data. 393 // It should be LE by default, but can be changed 394 // for testing purpose. 395 support::endianness ValueProfDataEndianness = support::little; 396 397 public: 398 InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) 399 : HashType(HashType), FormatVersion(FormatVersion) {} 400 401 using data_type = ArrayRef<NamedInstrProfRecord>; 402 403 using internal_key_type = StringRef; 404 using external_key_type = StringRef; 405 using hash_value_type = uint64_t; 406 using offset_type = uint64_t; 407 408 static bool EqualKey(StringRef A, StringRef B) { return A == B; } 409 static StringRef GetInternalKey(StringRef K) { return K; } 410 static StringRef GetExternalKey(StringRef K) { return K; } 411 412 hash_value_type ComputeHash(StringRef K); 413 414 static std::pair<offset_type, offset_type> 415 ReadKeyDataLength(const unsigned char *&D) { 416 using namespace support; 417 418 offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D); 419 offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D); 420 return std::make_pair(KeyLen, DataLen); 421 } 422 423 StringRef ReadKey(const unsigned char *D, offset_type N) { 424 return StringRef((const char *)D, N); 425 } 426 427 bool readValueProfilingData(const unsigned char *&D, 428 const unsigned char *const End); 429 data_type ReadData(StringRef K, const unsigned char *D, offset_type N); 430 431 // Used for testing purpose only. 432 void setValueProfDataEndianness(support::endianness Endianness) { 433 ValueProfDataEndianness = Endianness; 434 } 435 }; 436 437 struct InstrProfReaderIndexBase { 438 virtual ~InstrProfReaderIndexBase() = default; 439 440 // Read all the profile records with the same key pointed to the current 441 // iterator. 442 virtual Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) = 0; 443 444 // Read all the profile records with the key equal to FuncName 445 virtual Error getRecords(StringRef FuncName, 446 ArrayRef<NamedInstrProfRecord> &Data) = 0; 447 virtual void advanceToNextKey() = 0; 448 virtual bool atEnd() const = 0; 449 virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; 450 virtual uint64_t getVersion() const = 0; 451 virtual bool isIRLevelProfile() const = 0; 452 virtual bool hasCSIRLevelProfile() const = 0; 453 virtual bool instrEntryBBEnabled() const = 0; 454 virtual bool hasSingleByteCoverage() const = 0; 455 virtual bool functionEntryOnly() const = 0; 456 virtual InstrProfKind getProfileKind() const = 0; 457 virtual Error populateSymtab(InstrProfSymtab &) = 0; 458 }; 459 460 using OnDiskHashTableImplV3 = 461 OnDiskIterableChainedHashTable<InstrProfLookupTrait>; 462 463 template <typename HashTableImpl> 464 class InstrProfReaderItaniumRemapper; 465 466 template <typename HashTableImpl> 467 class InstrProfReaderIndex : public InstrProfReaderIndexBase { 468 private: 469 std::unique_ptr<HashTableImpl> HashTable; 470 typename HashTableImpl::data_iterator RecordIterator; 471 uint64_t FormatVersion; 472 473 friend class InstrProfReaderItaniumRemapper<HashTableImpl>; 474 475 public: 476 InstrProfReaderIndex(const unsigned char *Buckets, 477 const unsigned char *const Payload, 478 const unsigned char *const Base, 479 IndexedInstrProf::HashT HashType, uint64_t Version); 480 ~InstrProfReaderIndex() override = default; 481 482 Error getRecords(ArrayRef<NamedInstrProfRecord> &Data) override; 483 Error getRecords(StringRef FuncName, 484 ArrayRef<NamedInstrProfRecord> &Data) override; 485 void advanceToNextKey() override { RecordIterator++; } 486 487 bool atEnd() const override { 488 return RecordIterator == HashTable->data_end(); 489 } 490 491 void setValueProfDataEndianness(support::endianness Endianness) override { 492 HashTable->getInfoObj().setValueProfDataEndianness(Endianness); 493 } 494 495 uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } 496 497 bool isIRLevelProfile() const override { 498 return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; 499 } 500 501 bool hasCSIRLevelProfile() const override { 502 return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0; 503 } 504 505 bool instrEntryBBEnabled() const override { 506 return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0; 507 } 508 509 bool hasSingleByteCoverage() const override { 510 return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0; 511 } 512 513 bool functionEntryOnly() const override { 514 return (FormatVersion & VARIANT_MASK_FUNCTION_ENTRY_ONLY) != 0; 515 } 516 517 InstrProfKind getProfileKind() const override; 518 519 Error populateSymtab(InstrProfSymtab &Symtab) override { 520 return Symtab.create(HashTable->keys()); 521 } 522 }; 523 524 /// Name matcher supporting fuzzy matching of symbol names to names in profiles. 525 class InstrProfReaderRemapper { 526 public: 527 virtual ~InstrProfReaderRemapper() = default; 528 virtual Error populateRemappings() { return Error::success(); } 529 virtual Error getRecords(StringRef FuncName, 530 ArrayRef<NamedInstrProfRecord> &Data) = 0; 531 }; 532 533 /// Reader for the indexed binary instrprof format. 534 class IndexedInstrProfReader : public InstrProfReader { 535 private: 536 /// The profile data file contents. 537 std::unique_ptr<MemoryBuffer> DataBuffer; 538 /// The profile remapping file contents. 539 std::unique_ptr<MemoryBuffer> RemappingBuffer; 540 /// The index into the profile data. 541 std::unique_ptr<InstrProfReaderIndexBase> Index; 542 /// The profile remapping file contents. 543 std::unique_ptr<InstrProfReaderRemapper> Remapper; 544 /// Profile summary data. 545 std::unique_ptr<ProfileSummary> Summary; 546 /// Context sensitive profile summary data. 547 std::unique_ptr<ProfileSummary> CS_Summary; 548 // Index to the current record in the record array. 549 unsigned RecordIndex; 550 551 // Read the profile summary. Return a pointer pointing to one byte past the 552 // end of the summary data if it exists or the input \c Cur. 553 // \c UseCS indicates whether to use the context-sensitive profile summary. 554 const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, 555 const unsigned char *Cur, bool UseCS); 556 557 public: 558 IndexedInstrProfReader( 559 std::unique_ptr<MemoryBuffer> DataBuffer, 560 std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr) 561 : DataBuffer(std::move(DataBuffer)), 562 RemappingBuffer(std::move(RemappingBuffer)), RecordIndex(0) {} 563 IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; 564 IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; 565 566 /// Return the profile version. 567 uint64_t getVersion() const { return Index->getVersion(); } 568 bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } 569 bool hasCSIRLevelProfile() const override { 570 return Index->hasCSIRLevelProfile(); 571 } 572 573 bool instrEntryBBEnabled() const override { 574 return Index->instrEntryBBEnabled(); 575 } 576 577 bool hasSingleByteCoverage() const override { 578 return Index->hasSingleByteCoverage(); 579 } 580 581 bool functionEntryOnly() const override { return Index->functionEntryOnly(); } 582 583 /// Returns a BitsetEnum describing the attributes of the indexed instr 584 /// profile. 585 InstrProfKind getProfileKind() const override { 586 return Index->getProfileKind(); 587 } 588 589 /// Return true if the given buffer is in an indexed instrprof format. 590 static bool hasFormat(const MemoryBuffer &DataBuffer); 591 592 /// Read the file header. 593 Error readHeader() override; 594 /// Read a single record. 595 Error readNextRecord(NamedInstrProfRecord &Record) override; 596 597 /// Return the NamedInstrProfRecord associated with FuncName and FuncHash 598 Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName, 599 uint64_t FuncHash); 600 601 /// Fill Counts with the profile data for the given function name. 602 Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, 603 std::vector<uint64_t> &Counts); 604 605 /// Return the maximum of all known function counts. 606 /// \c UseCS indicates whether to use the context-sensitive count. 607 uint64_t getMaximumFunctionCount(bool UseCS) { 608 if (UseCS) { 609 assert(CS_Summary && "No context sensitive profile summary"); 610 return CS_Summary->getMaxFunctionCount(); 611 } else { 612 assert(Summary && "No profile summary"); 613 return Summary->getMaxFunctionCount(); 614 } 615 } 616 617 /// Factory method to create an indexed reader. 618 static Expected<std::unique_ptr<IndexedInstrProfReader>> 619 create(const Twine &Path, const Twine &RemappingPath = ""); 620 621 static Expected<std::unique_ptr<IndexedInstrProfReader>> 622 create(std::unique_ptr<MemoryBuffer> Buffer, 623 std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr); 624 625 // Used for testing purpose only. 626 void setValueProfDataEndianness(support::endianness Endianness) { 627 Index->setValueProfDataEndianness(Endianness); 628 } 629 630 // See description in the base class. This interface is designed 631 // to be used by llvm-profdata (for dumping). Avoid using this when 632 // the client is the compiler. 633 InstrProfSymtab &getSymtab() override; 634 635 /// Return the profile summary. 636 /// \c UseCS indicates whether to use the context-sensitive summary. 637 ProfileSummary &getSummary(bool UseCS) { 638 if (UseCS) { 639 assert(CS_Summary && "No context sensitive summary"); 640 return *(CS_Summary.get()); 641 } else { 642 assert(Summary && "No profile summary"); 643 return *(Summary.get()); 644 } 645 } 646 }; 647 648 } // end namespace llvm 649 650 #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H 651