LLVM 17.0.0git
InstrProfReader.cpp
Go to the documentation of this file.
1//===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
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 clang's
10// instrumentation based PGO and coverage.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/DenseMap.h"
18#include "llvm/ADT/StringRef.h"
23#include "llvm/Support/Endian.h"
24#include "llvm/Support/Error.h"
30#include <algorithm>
31#include <cstddef>
32#include <cstdint>
33#include <limits>
34#include <memory>
35#include <system_error>
36#include <utility>
37#include <vector>
38
39using namespace llvm;
40
41// Extracts the variant information from the top 8 bits in the version and
42// returns an enum specifying the variants present.
44 InstrProfKind ProfileKind = InstrProfKind::Unknown;
45 if (Version & VARIANT_MASK_IR_PROF) {
46 ProfileKind |= InstrProfKind::IRInstrumentation;
47 }
48 if (Version & VARIANT_MASK_CSIR_PROF) {
49 ProfileKind |= InstrProfKind::ContextSensitive;
50 }
51 if (Version & VARIANT_MASK_INSTR_ENTRY) {
52 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
53 }
54 if (Version & VARIANT_MASK_BYTE_COVERAGE) {
55 ProfileKind |= InstrProfKind::SingleByteCoverage;
56 }
57 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
58 ProfileKind |= InstrProfKind::FunctionEntryOnly;
59 }
60 if (Version & VARIANT_MASK_MEMPROF) {
61 ProfileKind |= InstrProfKind::MemProf;
62 }
63 return ProfileKind;
64}
65
68 auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
69 : FS.getBufferForFile(Filename);
70 if (std::error_code EC = BufferOrErr.getError())
71 return errorCodeToError(EC);
72 return std::move(BufferOrErr.get());
73}
74
76 return Reader.readHeader();
77}
78
79/// Read a list of binary ids from a profile that consist of
80/// a. uint64_t binary id length
81/// b. uint8_t binary id data
82/// c. uint8_t padding (if necessary)
83/// This function is shared between raw and indexed profiles.
84/// Raw profiles are in host-endian format, and indexed profiles are in
85/// little-endian format. So, this function takes an argument indicating the
86/// associated endian format to read the binary ids correctly.
87static Error
89 const uint64_t BinaryIdsSize,
90 const uint8_t *BinaryIdsStart,
91 std::vector<llvm::object::BuildID> &BinaryIds,
92 const llvm::support::endianness Endian) {
93 using namespace support;
94
95 if (BinaryIdsSize == 0)
96 return Error::success();
97
98 const uint8_t *BI = BinaryIdsStart;
99 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
100 const uint8_t *End =
101 reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
102
103 while (BI < BIEnd) {
104 size_t Remaining = BIEnd - BI;
105 // There should be enough left to read the binary id length.
106 if (Remaining < sizeof(uint64_t))
107 return make_error<InstrProfError>(
108 instrprof_error::malformed,
109 "not enough data to read binary id length");
110
111 uint64_t BILen = 0;
112 if (Endian == little)
113 BILen = endian::readNext<uint64_t, little, unaligned>(BI);
114 else
115 BILen = endian::readNext<uint64_t, big, unaligned>(BI);
116
117 if (BILen == 0)
118 return make_error<InstrProfError>(instrprof_error::malformed,
119 "binary id length is 0");
120
121 Remaining = BIEnd - BI;
122 // There should be enough left to read the binary id data.
123 if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
124 return make_error<InstrProfError>(
125 instrprof_error::malformed, "not enough data to read binary id data");
126
127 // Add binary id to the binary ids list.
128 BinaryIds.push_back(object::BuildID(BI, BI + BILen));
129
130 // Increment by binary id data length, which aligned to the size of uint64.
131 BI += alignToPowerOf2(BILen, sizeof(uint64_t));
132 if (BI > End)
133 return make_error<InstrProfError>(
134 instrprof_error::malformed,
135 "binary id section is greater than buffer size");
136 }
137
138 return Error::success();
139}
140
142 const MemoryBuffer &DataBuffer,
143 uint64_t BinaryIdsSize,
144 const uint8_t *BinaryIdsStart,
146 if (BinaryIdsSize == 0)
147 return Error::success();
148
149 std::vector<llvm::object::BuildID> BinaryIds;
150 if (Error E = readBinaryIdsInternal(DataBuffer, BinaryIdsSize, BinaryIdsStart,
151 BinaryIds, Endian))
152 return E;
153
154 OS << "Binary IDs: \n";
155 for (auto BI : BinaryIds) {
156 for (uint64_t I = 0; I < BI.size(); I++)
157 OS << format("%02x", BI[I]);
158 OS << "\n";
159 }
160
161 return Error::success();
162}
163
166 const InstrProfCorrelator *Correlator) {
167 // Set up the buffer to read.
168 auto BufferOrError = setupMemoryBuffer(Path, FS);
169 if (Error E = BufferOrError.takeError())
170 return std::move(E);
171 return InstrProfReader::create(std::move(BufferOrError.get()), Correlator);
172}
173
175InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
176 const InstrProfCorrelator *Correlator) {
177 if (Buffer->getBufferSize() == 0)
178 return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
179
180 std::unique_ptr<InstrProfReader> Result;
181 // Create the reader.
183 Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
184 else if (RawInstrProfReader64::hasFormat(*Buffer))
185 Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator));
186 else if (RawInstrProfReader32::hasFormat(*Buffer))
187 Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator));
188 else if (TextInstrProfReader::hasFormat(*Buffer))
189 Result.reset(new TextInstrProfReader(std::move(Buffer)));
190 else
191 return make_error<InstrProfError>(instrprof_error::unrecognized_format);
192
193 // Initialize the reader and return the result.
194 if (Error E = initializeReader(*Result))
195 return std::move(E);
196
197 return std::move(Result);
198}
199
202 const Twine &RemappingPath) {
203 // Set up the buffer to read.
204 auto BufferOrError = setupMemoryBuffer(Path, FS);
205 if (Error E = BufferOrError.takeError())
206 return std::move(E);
207
208 // Set up the remapping buffer if requested.
209 std::unique_ptr<MemoryBuffer> RemappingBuffer;
210 std::string RemappingPathStr = RemappingPath.str();
211 if (!RemappingPathStr.empty()) {
212 auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
213 if (Error E = RemappingBufferOrError.takeError())
214 return std::move(E);
215 RemappingBuffer = std::move(RemappingBufferOrError.get());
216 }
217
218 return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
219 std::move(RemappingBuffer));
220}
221
223IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
224 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
225 // Create the reader.
227 return make_error<InstrProfError>(instrprof_error::bad_magic);
228 auto Result = std::make_unique<IndexedInstrProfReader>(
229 std::move(Buffer), std::move(RemappingBuffer));
230
231 // Initialize the reader and return the result.
232 if (Error E = initializeReader(*Result))
233 return std::move(E);
234
235 return std::move(Result);
236}
237
239 // Verify that this really looks like plain ASCII text by checking a
240 // 'reasonable' number of characters (up to profile magic size).
241 size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
242 StringRef buffer = Buffer.getBufferStart();
243 return count == 0 ||
244 std::all_of(buffer.begin(), buffer.begin() + count,
245 [](char c) { return isPrint(c) || isSpace(c); });
246}
247
248// Read the profile variant flag from the header: ":FE" means this is a FE
249// generated profile. ":IR" means this is an IR level profile. Other strings
250// with a leading ':' will be reported an error format.
252 Symtab.reset(new InstrProfSymtab());
253
254 while (Line->startswith(":")) {
255 StringRef Str = Line->substr(1);
256 if (Str.equals_insensitive("ir"))
258 else if (Str.equals_insensitive("fe"))
260 else if (Str.equals_insensitive("csir")) {
262 ProfileKind |= InstrProfKind::ContextSensitive;
263 } else if (Str.equals_insensitive("entry_first"))
265 else if (Str.equals_insensitive("not_entry_first"))
267 else
269 ++Line;
270 }
271 return success();
272}
273
274Error
275TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
276
277#define CHECK_LINE_END(Line) \
278 if (Line.is_at_end()) \
279 return error(instrprof_error::truncated);
280#define READ_NUM(Str, Dst) \
281 if ((Str).getAsInteger(10, (Dst))) \
282 return error(instrprof_error::malformed);
283#define VP_READ_ADVANCE(Val) \
284 CHECK_LINE_END(Line); \
285 uint32_t Val; \
286 READ_NUM((*Line), (Val)); \
287 Line++;
288
289 if (Line.is_at_end())
290 return success();
291
292 uint32_t NumValueKinds;
293 if (Line->getAsInteger(10, NumValueKinds)) {
294 // No value profile data
295 return success();
296 }
297 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
299 "number of value kinds is invalid");
300 Line++;
301
302 for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
303 VP_READ_ADVANCE(ValueKind);
304 if (ValueKind > IPVK_Last)
305 return error(instrprof_error::malformed, "value kind is invalid");
306 ;
307 VP_READ_ADVANCE(NumValueSites);
308 if (!NumValueSites)
309 continue;
310
311 Record.reserveSites(VK, NumValueSites);
312 for (uint32_t S = 0; S < NumValueSites; S++) {
313 VP_READ_ADVANCE(NumValueData);
314
315 std::vector<InstrProfValueData> CurrentValues;
316 for (uint32_t V = 0; V < NumValueData; V++) {
317 CHECK_LINE_END(Line);
318 std::pair<StringRef, StringRef> VD = Line->rsplit(':');
319 uint64_t TakenCount, Value;
320 if (ValueKind == IPVK_IndirectCallTarget) {
321 if (InstrProfSymtab::isExternalSymbol(VD.first)) {
322 Value = 0;
323 } else {
324 if (Error E = Symtab->addFuncName(VD.first))
325 return E;
327 }
328 } else {
329 READ_NUM(VD.first, Value);
330 }
331 READ_NUM(VD.second, TakenCount);
332 CurrentValues.push_back({Value, TakenCount});
333 Line++;
334 }
335 Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
336 nullptr);
337 }
338 }
339 return success();
340
341#undef CHECK_LINE_END
342#undef READ_NUM
343#undef VP_READ_ADVANCE
344}
345
347 // Skip empty lines and comments.
348 while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
349 ++Line;
350 // If we hit EOF while looking for a name, we're done.
351 if (Line.is_at_end()) {
353 }
354
355 // Read the function name.
356 Record.Name = *Line++;
357 if (Error E = Symtab->addFuncName(Record.Name))
358 return error(std::move(E));
359
360 // Read the function hash.
361 if (Line.is_at_end())
363 if ((Line++)->getAsInteger(0, Record.Hash))
365 "function hash is not a valid integer");
366
367 // Read the number of counters.
368 uint64_t NumCounters;
369 if (Line.is_at_end())
371 if ((Line++)->getAsInteger(10, NumCounters))
373 "number of counters is not a valid integer");
374 if (NumCounters == 0)
375 return error(instrprof_error::malformed, "number of counters is zero");
376
377 // Read each counter and fill our internal storage with the values.
378 Record.Clear();
379 Record.Counts.reserve(NumCounters);
380 for (uint64_t I = 0; I < NumCounters; ++I) {
381 if (Line.is_at_end())
383 uint64_t Count;
384 if ((Line++)->getAsInteger(10, Count))
385 return error(instrprof_error::malformed, "count is invalid");
386 Record.Counts.push_back(Count);
387 }
388
389 // Check if value profile data exists and read it if so.
390 if (Error E = readValueProfileData(Record))
391 return error(std::move(E));
392
393 return success();
394}
395
396template <class IntPtrT>
398 return getProfileKindFromVersion(Version);
399}
400
401template <class IntPtrT>
403 if (DataBuffer.getBufferSize() < sizeof(uint64_t))
404 return false;
405 uint64_t Magic =
406 *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
407 return RawInstrProf::getMagic<IntPtrT>() == Magic ||
408 sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
409}
410
411template <class IntPtrT>
413 if (!hasFormat(*DataBuffer))
415 if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
417 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
418 DataBuffer->getBufferStart());
419 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
420 return readHeader(*Header);
421}
422
423template <class IntPtrT>
425 const char *End = DataBuffer->getBufferEnd();
426 // Skip zero padding between profiles.
427 while (CurrentPos != End && *CurrentPos == 0)
428 ++CurrentPos;
429 // If there's nothing left, we're done.
430 if (CurrentPos == End)
431 return make_error<InstrProfError>(instrprof_error::eof);
432 // If there isn't enough space for another header, this is probably just
433 // garbage at the end of the file.
434 if (CurrentPos + sizeof(RawInstrProf::Header) > End)
435 return make_error<InstrProfError>(instrprof_error::malformed,
436 "not enough space for another header");
437 // The writer ensures each profile is padded to start at an aligned address.
438 if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
439 return make_error<InstrProfError>(instrprof_error::malformed,
440 "insufficient padding");
441 // The magic should have the same byte order as in the previous header.
442 uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
443 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
444 return make_error<InstrProfError>(instrprof_error::bad_magic);
445
446 // There's another profile to read, so we need to process the header.
447 auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
448 return readHeader(*Header);
449}
450
451template <class IntPtrT>
453 if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart)))
454 return error(std::move(E));
455 for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
456 const IntPtrT FPtr = swap(I->FunctionPointer);
457 if (!FPtr)
458 continue;
459 Symtab.mapAddress(FPtr, I->NameRef);
460 }
461 return success();
462}
463
464template <class IntPtrT>
466 const RawInstrProf::Header &Header) {
467 Version = swap(Header.Version);
468 if (GET_VERSION(Version) != RawInstrProf::Version)
470 if (useDebugInfoCorrelate() && !Correlator)
472 if (!useDebugInfoCorrelate() && Correlator)
474
475 BinaryIdsSize = swap(Header.BinaryIdsSize);
476 if (BinaryIdsSize % sizeof(uint64_t))
478
479 CountersDelta = swap(Header.CountersDelta);
480 NamesDelta = swap(Header.NamesDelta);
481 auto NumData = swap(Header.DataSize);
482 auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
483 auto CountersSize = swap(Header.CountersSize) * getCounterTypeSize();
484 auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
485 auto NamesSize = swap(Header.NamesSize);
486 ValueKindLast = swap(Header.ValueKindLast);
487
488 auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
489 auto PaddingSize = getNumPaddingBytes(NamesSize);
490
491 // Profile data starts after profile header and binary ids if exist.
492 ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize;
493 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
494 ptrdiff_t NamesOffset =
495 CountersOffset + CountersSize + PaddingBytesAfterCounters;
496 ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
497
498 auto *Start = reinterpret_cast<const char *>(&Header);
499 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
501
502 if (Correlator) {
503 // These sizes in the raw file are zero because we constructed them in the
504 // Correlator.
505 assert(DataSize == 0 && NamesSize == 0);
506 assert(CountersDelta == 0 && NamesDelta == 0);
507 Data = Correlator->getDataPointer();
508 DataEnd = Data + Correlator->getDataSize();
509 NamesStart = Correlator->getNamesPointer();
510 NamesEnd = NamesStart + Correlator->getNamesSize();
511 } else {
512 Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
513 Start + DataOffset);
514 DataEnd = Data + NumData;
515 NamesStart = Start + NamesOffset;
516 NamesEnd = NamesStart + NamesSize;
517 }
518
519 // Binary ids start just after the header.
520 BinaryIdsStart =
521 reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
522 CountersStart = Start + CountersOffset;
523 CountersEnd = CountersStart + CountersSize;
524 ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
525
526 const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
527 if (BinaryIdsStart + BinaryIdsSize > BufferEnd)
529
530 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
531 if (Error E = createSymtab(*NewSymtab))
532 return E;
533
534 Symtab = std::move(NewSymtab);
535 return success();
536}
537
538template <class IntPtrT>
540 Record.Name = getName(Data->NameRef);
541 return success();
542}
543
544template <class IntPtrT>
546 Record.Hash = swap(Data->FuncHash);
547 return success();
548}
549
550template <class IntPtrT>
553 uint32_t NumCounters = swap(Data->NumCounters);
554 if (NumCounters == 0)
555 return error(instrprof_error::malformed, "number of counters is zero");
556
557 ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
558 if (CounterBaseOffset < 0)
559 return error(
561 ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
562
563 if (CounterBaseOffset >= CountersEnd - CountersStart)
565 ("counter offset " + Twine(CounterBaseOffset) +
566 " is greater than the maximum counter offset " +
567 Twine(CountersEnd - CountersStart - 1))
568 .str());
569
570 uint64_t MaxNumCounters =
571 (CountersEnd - (CountersStart + CounterBaseOffset)) /
572 getCounterTypeSize();
573 if (NumCounters > MaxNumCounters)
575 ("number of counters " + Twine(NumCounters) +
576 " is greater than the maximum number of counters " +
577 Twine(MaxNumCounters))
578 .str());
579
580 Record.Counts.clear();
581 Record.Counts.reserve(NumCounters);
582 for (uint32_t I = 0; I < NumCounters; I++) {
583 const char *Ptr =
584 CountersStart + CounterBaseOffset + I * getCounterTypeSize();
585 if (hasSingleByteCoverage()) {
586 // A value of zero signifies the block is covered.
587 Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
588 } else {
589 const auto *CounterValue = reinterpret_cast<const uint64_t *>(Ptr);
590 Record.Counts.push_back(swap(*CounterValue));
591 }
592 }
593
594 return success();
595}
596
597template <class IntPtrT>
600 Record.clearValueData();
601 CurValueDataSize = 0;
602 // Need to match the logic in value profile dumper code in compiler-rt:
603 uint32_t NumValueKinds = 0;
604 for (uint32_t I = 0; I < IPVK_Last + 1; I++)
605 NumValueKinds += (Data->NumValueSites[I] != 0);
606
607 if (!NumValueKinds)
608 return success();
609
611 ValueProfData::getValueProfData(
612 ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
613 getDataEndianness());
614
615 if (Error E = VDataPtrOrErr.takeError())
616 return E;
617
618 // Note that besides deserialization, this also performs the conversion for
619 // indirect call targets. The function pointers from the raw profile are
620 // remapped into function name hashes.
621 VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
622 CurValueDataSize = VDataPtrOrErr.get()->getSize();
623 return success();
624}
625
626template <class IntPtrT>
628 // Keep reading profiles that consist of only headers and no profile data and
629 // counters.
630 while (atEnd())
631 // At this point, ValueDataStart field points to the next header.
632 if (Error E = readNextHeader(getNextHeaderPos()))
633 return error(std::move(E));
634
635 // Read name ad set it in Record.
636 if (Error E = readName(Record))
637 return error(std::move(E));
638
639 // Read FuncHash and set it in Record.
640 if (Error E = readFuncHash(Record))
641 return error(std::move(E));
642
643 // Read raw counts and set Record.
644 if (Error E = readRawCounts(Record))
645 return error(std::move(E));
646
647 // Read value data and set Record.
648 if (Error E = readValueProfilingData(Record))
649 return error(std::move(E));
650
651 // Iterate.
652 advanceData();
653 return success();
654}
655
656template <class IntPtrT>
658 std::vector<llvm::object::BuildID> &BinaryIds) {
659 return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
660 BinaryIds, getDataEndianness());
661}
662
663template <class IntPtrT>
665 return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
666 getDataEndianness());
667}
668
669namespace llvm {
670
671template class RawInstrProfReader<uint32_t>;
672template class RawInstrProfReader<uint64_t>;
673
674} // end namespace llvm
675
678 return IndexedInstrProf::ComputeHash(HashType, K);
679}
680
683
685 const unsigned char *&D, const unsigned char *const End) {
687 ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
688
689 if (VDataPtrOrErr.takeError())
690 return false;
691
692 VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
693 D += VDataPtrOrErr.get()->TotalSize;
694
695 return true;
696}
697
699 offset_type N) {
700 using namespace support;
701
702 // Check if the data is corrupt. If so, don't try to read it.
703 if (N % sizeof(uint64_t))
704 return data_type();
705
706 DataBuffer.clear();
707 std::vector<uint64_t> CounterBuffer;
708
709 const unsigned char *End = D + N;
710 while (D < End) {
711 // Read hash.
712 if (D + sizeof(uint64_t) >= End)
713 return data_type();
714 uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
715
716 // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
717 uint64_t CountsSize = N / sizeof(uint64_t) - 1;
718 // If format version is different then read the number of counters.
719 if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
720 if (D + sizeof(uint64_t) > End)
721 return data_type();
722 CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
723 }
724 // Read counter values.
725 if (D + CountsSize * sizeof(uint64_t) > End)
726 return data_type();
727
728 CounterBuffer.clear();
729 CounterBuffer.reserve(CountsSize);
730 for (uint64_t J = 0; J < CountsSize; ++J)
731 CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
732
733 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
734
735 // Read value profiling data.
736 if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
737 !readValueProfilingData(D, End)) {
738 DataBuffer.clear();
739 return data_type();
740 }
741 }
742 return DataBuffer;
743}
744
745template <typename HashTableImpl>
748 auto Iter = HashTable->find(FuncName);
749 if (Iter == HashTable->end())
750 return make_error<InstrProfError>(instrprof_error::unknown_function);
751
752 Data = (*Iter);
753 if (Data.empty())
754 return make_error<InstrProfError>(instrprof_error::malformed,
755 "profile data is empty");
756
757 return Error::success();
758}
759
760template <typename HashTableImpl>
763 if (atEnd())
764 return make_error<InstrProfError>(instrprof_error::eof);
765
766 Data = *RecordIterator;
767
768 if (Data.empty())
769 return make_error<InstrProfError>(instrprof_error::malformed,
770 "profile data is empty");
771
772 return Error::success();
773}
774
775template <typename HashTableImpl>
777 const unsigned char *Buckets, const unsigned char *const Payload,
778 const unsigned char *const Base, IndexedInstrProf::HashT HashType,
779 uint64_t Version) {
780 FormatVersion = Version;
781 HashTable.reset(HashTableImpl::Create(
782 Buckets, Payload, Base,
783 typename HashTableImpl::InfoType(HashType, Version)));
784 RecordIterator = HashTable->data_begin();
785}
786
787template <typename HashTableImpl>
789 return getProfileKindFromVersion(FormatVersion);
790}
791
792namespace {
793/// A remapper that does not apply any remappings.
794class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
795 InstrProfReaderIndexBase &Underlying;
796
797public:
798 InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
799 : Underlying(Underlying) {}
800
801 Error getRecords(StringRef FuncName,
803 return Underlying.getRecords(FuncName, Data);
804 }
805};
806} // namespace
807
808/// A remapper that applies remappings based on a symbol remapping file.
809template <typename HashTableImpl>
811 : public InstrProfReaderRemapper {
812public:
814 std::unique_ptr<MemoryBuffer> RemapBuffer,
816 : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
817 }
818
819 /// Extract the original function name from a PGO function name.
821 // We can have multiple :-separated pieces; there can be pieces both
822 // before and after the mangled name. Find the first part that starts
823 // with '_Z'; we'll assume that's the mangled name we want.
824 std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
825 while (true) {
826 Parts = Parts.second.split(':');
827 if (Parts.first.startswith("_Z"))
828 return Parts.first;
829 if (Parts.second.empty())
830 return Name;
831 }
832 }
833
834 /// Given a mangled name extracted from a PGO function name, and a new
835 /// form for that mangled name, reconstitute the name.
836 static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
837 StringRef Replacement,
839 Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
840 Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
841 Out.insert(Out.end(), Replacement.begin(), Replacement.end());
842 Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
843 }
844
846 if (Error E = Remappings.read(*RemapBuffer))
847 return E;
848 for (StringRef Name : Underlying.HashTable->keys()) {
849 StringRef RealName = extractName(Name);
850 if (auto Key = Remappings.insert(RealName)) {
851 // FIXME: We could theoretically map the same equivalence class to
852 // multiple names in the profile data. If that happens, we should
853 // return NamedInstrProfRecords from all of them.
854 MappedNames.insert({Key, RealName});
855 }
856 }
857 return Error::success();
858 }
859
862 StringRef RealName = extractName(FuncName);
863 if (auto Key = Remappings.lookup(RealName)) {
864 StringRef Remapped = MappedNames.lookup(Key);
865 if (!Remapped.empty()) {
866 if (RealName.begin() == FuncName.begin() &&
867 RealName.end() == FuncName.end())
868 FuncName = Remapped;
869 else {
870 // Try rebuilding the name from the given remapping.
871 SmallString<256> Reconstituted;
872 reconstituteName(FuncName, RealName, Remapped, Reconstituted);
873 Error E = Underlying.getRecords(Reconstituted, Data);
874 if (!E)
875 return E;
876
877 // If we failed because the name doesn't exist, fall back to asking
878 // about the original name.
879 if (Error Unhandled = handleErrors(
880 std::move(E), [](std::unique_ptr<InstrProfError> Err) {
881 return Err->get() == instrprof_error::unknown_function
883 : Error(std::move(Err));
884 }))
885 return Unhandled;
886 }
887 }
888 }
889 return Underlying.getRecords(FuncName, Data);
890 }
891
892private:
893 /// The memory buffer containing the remapping configuration. Remappings
894 /// holds pointers into this buffer.
895 std::unique_ptr<MemoryBuffer> RemapBuffer;
896
897 /// The mangling remapper.
898 SymbolRemappingReader Remappings;
899
900 /// Mapping from mangled name keys to the name used for the key in the
901 /// profile data.
902 /// FIXME: Can we store a location within the on-disk hash table instead of
903 /// redoing lookup?
905
906 /// The real profile data reader.
908};
909
911 using namespace support;
912
913 if (DataBuffer.getBufferSize() < 8)
914 return false;
915 uint64_t Magic =
916 endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
917 // Verify that it's magical.
918 return Magic == IndexedInstrProf::Magic;
919}
920
921const unsigned char *
922IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
923 const unsigned char *Cur, bool UseCS) {
924 using namespace IndexedInstrProf;
925 using namespace support;
926
927 if (Version >= IndexedInstrProf::Version4) {
928 const IndexedInstrProf::Summary *SummaryInLE =
929 reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
930 uint64_t NFields =
931 endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
932 uint64_t NEntries =
933 endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
934 uint32_t SummarySize =
935 IndexedInstrProf::Summary::getSize(NFields, NEntries);
936 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
938
939 const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
940 uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
941 for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
942 Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
943
944 SummaryEntryVector DetailedSummary;
945 for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
946 const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
947 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
948 Ent.NumBlocks);
949 }
950 std::unique_ptr<llvm::ProfileSummary> &Summary =
951 UseCS ? this->CS_Summary : this->Summary;
952
953 // initialize InstrProfSummary using the SummaryData from disk.
954 Summary = std::make_unique<ProfileSummary>(
956 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
957 SummaryData->get(Summary::MaxBlockCount),
958 SummaryData->get(Summary::MaxInternalBlockCount),
959 SummaryData->get(Summary::MaxFunctionCount),
960 SummaryData->get(Summary::TotalNumBlocks),
961 SummaryData->get(Summary::TotalNumFunctions));
962 return Cur + SummarySize;
963 } else {
964 // The older versions do not support a profile summary. This just computes
965 // an empty summary, which will not result in accurate hot/cold detection.
966 // We would need to call addRecord for all NamedInstrProfRecords to get the
967 // correct summary. However, this version is old (prior to early 2016) and
968 // has not been supporting an accurate summary for several years.
970 Summary = Builder.getSummary();
971 return Cur;
972 }
973}
974
976 using namespace support;
977
978 const unsigned char *Start =
979 (const unsigned char *)DataBuffer->getBufferStart();
980 const unsigned char *Cur = Start;
981 if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
983
984 auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
985 if (!HeaderOr)
986 return HeaderOr.takeError();
987
988 const IndexedInstrProf::Header *Header = &HeaderOr.get();
989 Cur += Header->size();
990
991 Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
992 /* UseCS */ false);
993 if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
994 Cur =
995 readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
996 /* UseCS */ true);
997 // Read the hash type and start offset.
998 IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
999 endian::byte_swap<uint64_t, little>(Header->HashType));
1000 if (HashType > IndexedInstrProf::HashT::Last)
1002
1003 uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
1004
1005 // The hash table with profile counts comes next.
1006 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1007 Start + HashOffset, Cur, Start, HashType, Header->formatVersion());
1008
1009 // The MemProfOffset field in the header is only valid when the format
1010 // version is higher than 8 (when it was introduced).
1011 if (GET_VERSION(Header->formatVersion()) >= 8 &&
1012 Header->formatVersion() & VARIANT_MASK_MEMPROF) {
1013 uint64_t MemProfOffset =
1014 endian::byte_swap<uint64_t, little>(Header->MemProfOffset);
1015
1016 const unsigned char *Ptr = Start + MemProfOffset;
1017 // The value returned from RecordTableGenerator.Emit.
1018 const uint64_t RecordTableOffset =
1019 support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1020 // The offset in the stream right before invoking
1021 // FrameTableGenerator.Emit.
1022 const uint64_t FramePayloadOffset =
1023 support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1024 // The value returned from FrameTableGenerator.Emit.
1025 const uint64_t FrameTableOffset =
1026 support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1027
1028 // Read the schema.
1029 auto SchemaOr = memprof::readMemProfSchema(Ptr);
1030 if (!SchemaOr)
1031 return SchemaOr.takeError();
1032 Schema = SchemaOr.get();
1033
1034 // Now initialize the table reader with a pointer into data buffer.
1035 MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1036 /*Buckets=*/Start + RecordTableOffset,
1037 /*Payload=*/Ptr,
1038 /*Base=*/Start, memprof::RecordLookupTrait(Schema)));
1039
1040 // Initialize the frame table reader with the payload and bucket offsets.
1041 MemProfFrameTable.reset(MemProfFrameHashTable::Create(
1042 /*Buckets=*/Start + FrameTableOffset,
1043 /*Payload=*/Start + FramePayloadOffset,
1044 /*Base=*/Start, memprof::FrameLookupTrait()));
1045 }
1046
1047 // BinaryIdOffset field in the header is only valid when the format version
1048 // is higher than 9 (when it was introduced).
1049 if (GET_VERSION(Header->formatVersion()) >= 9) {
1050 uint64_t BinaryIdOffset =
1051 endian::byte_swap<uint64_t, little>(Header->BinaryIdOffset);
1052 const unsigned char *Ptr = Start + BinaryIdOffset;
1053 // Read binary ids size.
1054 BinaryIdsSize = support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1055 if (BinaryIdsSize % sizeof(uint64_t))
1057 // Set the binary ids start.
1058 BinaryIdsStart = Ptr;
1059 if (BinaryIdsStart > (const unsigned char *)DataBuffer->getBufferEnd())
1060 return make_error<InstrProfError>(instrprof_error::malformed,
1061 "corrupted binary ids");
1062 }
1063
1064 // Load the remapping table now if requested.
1065 if (RemappingBuffer) {
1066 Remapper =
1067 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1068 std::move(RemappingBuffer), *IndexPtr);
1069 if (Error E = Remapper->populateRemappings())
1070 return E;
1071 } else {
1072 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1073 }
1074 Index = std::move(IndexPtr);
1075
1076 return success();
1077}
1078
1080 if (Symtab)
1081 return *Symtab;
1082
1083 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
1084 if (Error E = Index->populateSymtab(*NewSymtab)) {
1086 }
1087
1088 Symtab = std::move(NewSymtab);
1089 return *Symtab;
1090}
1091
1093 StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum) {
1095 uint64_t FuncSum = 0;
1096 Error Err = Remapper->getRecords(FuncName, Data);
1097 if (Err)
1098 return std::move(Err);
1099 // Found it. Look for counters with the right hash.
1100
1101 // A flag to indicate if the records are from the same type
1102 // of profile (i.e cs vs nocs).
1103 bool CSBitMatch = false;
1104 auto getFuncSum = [](const std::vector<uint64_t> &Counts) {
1105 uint64_t ValueSum = 0;
1106 for (uint64_t CountValue : Counts) {
1107 if (CountValue == (uint64_t)-1)
1108 continue;
1109 // Handle overflow -- if that happens, return max.
1110 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1111 return std::numeric_limits<uint64_t>::max();
1112 ValueSum += CountValue;
1113 }
1114 return ValueSum;
1115 };
1116
1117 for (const NamedInstrProfRecord &I : Data) {
1118 // Check for a match and fill the vector if there is one.
1119 if (I.Hash == FuncHash)
1120 return std::move(I);
1123 CSBitMatch = true;
1124 if (MismatchedFuncSum == nullptr)
1125 continue;
1126 FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1127 }
1128 }
1129 if (CSBitMatch) {
1130 if (MismatchedFuncSum != nullptr)
1131 *MismatchedFuncSum = FuncSum;
1133 }
1135}
1136
1139 // TODO: Add memprof specific errors.
1140 if (MemProfRecordTable == nullptr)
1141 return make_error<InstrProfError>(instrprof_error::invalid_prof,
1142 "no memprof data available in profile");
1143 auto Iter = MemProfRecordTable->find(FuncNameHash);
1144 if (Iter == MemProfRecordTable->end())
1145 return make_error<InstrProfError>(
1147 "memprof record not found for function hash " + Twine(FuncNameHash));
1148
1149 // Setup a callback to convert from frame ids to frame using the on-disk
1150 // FrameData hash table.
1151 memprof::FrameId LastUnmappedFrameId = 0;
1152 bool HasFrameMappingError = false;
1153 auto IdToFrameCallback = [&](const memprof::FrameId Id) {
1154 auto FrIter = MemProfFrameTable->find(Id);
1155 if (FrIter == MemProfFrameTable->end()) {
1156 LastUnmappedFrameId = Id;
1157 HasFrameMappingError = true;
1158 return memprof::Frame(0, 0, 0, false);
1159 }
1160 return *FrIter;
1161 };
1162
1163 memprof::MemProfRecord Record(*Iter, IdToFrameCallback);
1164
1165 // Check that all frame ids were successfully converted to frames.
1166 if (HasFrameMappingError) {
1167 return make_error<InstrProfError>(instrprof_error::hash_mismatch,
1168 "memprof frame not found for frame id " +
1169 Twine(LastUnmappedFrameId));
1170 }
1171 return Record;
1172}
1173
1175 uint64_t FuncHash,
1176 std::vector<uint64_t> &Counts) {
1178 if (Error E = Record.takeError())
1179 return error(std::move(E));
1180
1181 Counts = Record.get().Counts;
1182 return success();
1183}
1184
1187
1188 Error E = Index->getRecords(Data);
1189 if (E)
1190 return error(std::move(E));
1191
1192 Record = Data[RecordIndex++];
1193 if (RecordIndex >= Data.size()) {
1194 Index->advanceToNextKey();
1195 RecordIndex = 0;
1196 }
1197 return success();
1198}
1199
1201 std::vector<llvm::object::BuildID> &BinaryIds) {
1202 return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
1203 BinaryIds, llvm::support::little);
1204}
1205
1207 return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
1209}
1210
1212 uint64_t NumFuncs = 0;
1213 for (const auto &Func : *this) {
1214 if (isIRLevelProfile()) {
1215 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1216 if (FuncIsCS != IsCS)
1217 continue;
1218 }
1219 Func.accumulateCounts(Sum);
1220 ++NumFuncs;
1221 }
1222 Sum.NumEntries = NumFuncs;
1223}
assume Assume Builder
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
std::string Name
Provides ErrorOr<T> smart pointer.
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
static Error printBinaryIdsInternal(raw_ostream &OS, const MemoryBuffer &DataBuffer, uint64_t BinaryIdsSize, const uint8_t *BinaryIdsStart, llvm::support::endianness Endian)
static Error initializeReader(InstrProfReader &Reader)
#define READ_NUM(Str, Dst)
#define CHECK_LINE_END(Line)
#define VP_READ_ADVANCE(Val)
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static Error readBinaryIdsInternal(const MemoryBuffer &DataBuffer, const uint64_t BinaryIdsSize, const uint8_t *BinaryIdsStart, std::vector< llvm::object::BuildID > &BinaryIds, const llvm::support::endianness Endian)
Read a list of binary ids from a profile that consist of a.
#define I(x, y, z)
Definition: MD5.cpp:58
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some functions that are useful when dealing with strings.
#define error(X)
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
Reader for the indexed binary instrprof format.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
Expected< memprof::MemProfRecord > getMemProfRecord(uint64_t FuncNameHash)
Return the memprof record for the function identified by llvm::md5(Name).
Error readHeader() override
Read the file header.
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
Expected< InstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
static bool hasFormat(const MemoryBuffer &DataBuffer)
Return true if the given buffer is in an indexed instrprof format.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
InstrProfCorrelator - A base class used to create raw instrumentation data to their functions.
static instrprof_error take(Error E)
Consume an Error and return the raw enum value contained within it.
Definition: InstrProf.h:358
data_type ReadData(StringRef K, const unsigned char *D, offset_type N)
bool readValueProfilingData(const unsigned char *&D, const unsigned char *const End)
hash_value_type ComputeHash(StringRef K)
ArrayRef< NamedInstrProfRecord > data_type
InstrProfKind getProfileKind() const override
Error getRecords(ArrayRef< NamedInstrProfRecord > &Data) override
InstrProfReaderIndex(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, IndexedInstrProf::HashT HashType, uint64_t Version)
A remapper that applies remappings based on a symbol remapping file.
static StringRef extractName(StringRef Name)
Extract the original function name from a PGO function name.
InstrProfReaderItaniumRemapper(std::unique_ptr< MemoryBuffer > RemapBuffer, InstrProfReaderIndex< HashTableImpl > &Underlying)
static void reconstituteName(StringRef OrigName, StringRef ExtractedName, StringRef Replacement, SmallVectorImpl< char > &Out)
Given a mangled name extracted from a PGO function name, and a new form for that mangled name,...
Error getRecords(StringRef FuncName, ArrayRef< NamedInstrProfRecord > &Data) override
Name matcher supporting fuzzy matching of symbol names to names in profiles.
Base class and interface for reading profiling data of any known instrprof format.
static Expected< std::unique_ptr< InstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const InstrProfCorrelator *Correlator=nullptr)
Factory method to create an appropriately typed reader for the given instrprof file.
std::unique_ptr< InstrProfSymtab > Symtab
Error success()
Clear the current error and return a successful one.
virtual bool isIRLevelProfile() const =0
virtual Error readHeader()=0
Read the header. Required before reading first record.
void accumulateCounts(CountSumOrPercent &Sum, bool IsCS)
Compute the sum of counts and return in Sum.
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
Definition: InstrProf.h:446
static bool isExternalSymbol(const StringRef &Symbol)
True if Symbol is the value used to represent external symbols.
Definition: InstrProf.h:544
void mapAddress(uint64_t Addr, uint64_t MD5Val)
Map a function address to its name's MD5 hash.
Definition: InstrProf.h:522
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
size_t getBufferSize() const
Definition: MemoryBuffer.h:68
const char * getBufferEnd() const
Definition: MemoryBuffer.h:67
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
Definition: MemoryBuffer.h:66
static OnDiskIterableChainedHashTable * Create(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, const Info &InfoObj=Info())
Create the hash table.
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Definition: ProfileCommon.h:65
Reader for the raw instrprof binary format from runtime.
Error readHeader() override
Read the header. Required before reading first record.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
static bool hasFormat(const MemoryBuffer &DataBuffer)
InstrProfKind getProfileKind() const override
Returns a BitsetEnum describing the attributes of the raw instr profile.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void reserve(size_type N)
Definition: SmallVector.h:667
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:809
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:469
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:559
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
iterator end() const
Definition: StringRef.h:113
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
Definition: StringRef.h:721
Reader for symbol remapping files.
Key insert(StringRef FunctionName)
Construct a key for the given symbol, or return an existing one if an equivalent name has already bee...
Key lookup(StringRef FunctionName)
Map the given symbol name into the key for the corresponding equivalence class.
Error read(MemoryBuffer &B)
Read remappings from the given buffer, which must live as long as the remapper.
Reader for the simple text based instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if the given buffer is in text instrprof format.
Error readNextRecord(NamedInstrProfRecord &Record) override
Read a single record.
Error readHeader() override
Read the header.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
LLVM Value Representation.
Definition: Value.h:74
bool is_at_end() const
Return true if we're an "end" iterator or have reached EOF.
Definition: LineIterator.h:63
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
The virtual file system interface.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
Definition: InstrProf.h:1171
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:1062
const uint64_t Version
Definition: InstrProf.h:1058
const uint64_t Magic
Definition: InstrProf.h:1025
const uint64_t Version
Definition: InstrProf.h:1192
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
Definition: MemProf.cpp:84
unsigned char getSwappedBytes(unsigned char C)
Definition: SwapByteOrder.h:69
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
RawInstrProfReader< uint32_t > RawInstrProfReader32
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
Definition: MathExtras.h:476
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:943
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
std::vector< ProfileSummaryEntry > SummaryEntryVector
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1896
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1862
RawInstrProfReader< uint64_t > RawInstrProfReader64
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
InstrProfKind
An enum describing the attributes of an instrumented profile.
Definition: InstrProf.h:287
Definition: BitVector.h:851
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
#define N
static Expected< Header > readFromBuffer(const unsigned char *Buffer)
Definition: InstrProf.cpp:1356
uint64_t Cutoff
The required percentile of total execution count.
Definition: InstrProf.h:1095
uint64_t NumBlocks
Number of blocks >= the minumum execution count.
Definition: InstrProf.h:1098
uint64_t MinBlockCount
The minimum execution count for this percentile.
Definition: InstrProf.h:1097
static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries)
Definition: InstrProf.h:1131
Profiling information for a single function.
Definition: InstrProf.h:730
static bool hasCSFlagInHash(uint64_t FuncHash)
Definition: InstrProf.h:923