35#include <system_error>
45 if (Version & VARIANT_MASK_IR_PROF) {
46 ProfileKind |= InstrProfKind::IRInstrumentation;
48 if (Version & VARIANT_MASK_CSIR_PROF) {
49 ProfileKind |= InstrProfKind::ContextSensitive;
51 if (Version & VARIANT_MASK_INSTR_ENTRY) {
52 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
54 if (Version & VARIANT_MASK_BYTE_COVERAGE) {
55 ProfileKind |= InstrProfKind::SingleByteCoverage;
57 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
58 ProfileKind |= InstrProfKind::FunctionEntryOnly;
60 if (Version & VARIANT_MASK_MEMPROF) {
61 ProfileKind |= InstrProfKind::MemProf;
63 if (Version & VARIANT_MASK_TEMPORAL_PROF) {
64 ProfileKind |= InstrProfKind::TemporalProfile;
72 : FS.getBufferForFile(Filename);
73 if (std::error_code EC = BufferOrErr.getError())
75 return std::move(BufferOrErr.get());
93 const uint8_t *BinaryIdsStart,
94 std::vector<llvm::object::BuildID> &BinaryIds,
96 using namespace support;
98 if (BinaryIdsSize == 0)
101 const uint8_t *BI = BinaryIdsStart;
102 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
104 reinterpret_cast<const uint8_t *
>(DataBuffer.
getBufferEnd());
107 size_t Remaining = BIEnd - BI;
110 return make_error<InstrProfError>(
111 instrprof_error::malformed,
112 "not enough data to read binary id length");
117 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(BI);
119 BILen = endian::readNext<uint64_t, llvm::endianness::big, unaligned>(BI);
122 return make_error<InstrProfError>(instrprof_error::malformed,
123 "binary id length is 0");
125 Remaining = BIEnd - BI;
128 return make_error<InstrProfError>(
129 instrprof_error::malformed,
"not enough data to read binary id data");
137 return make_error<InstrProfError>(
138 instrprof_error::malformed,
139 "binary id section is greater than buffer size");
147 std::vector<llvm::object::BuildID> &BinaryIds) {
148 OS <<
"Binary IDs: \n";
149 for (
auto BI : BinaryIds) {
159 std::function<
void(
Error)> Warn) {
162 if (
Error E = BufferOrError.takeError())
171 std::function<
void(
Error)> Warn) {
172 if (Buffer->getBufferSize() == 0)
175 std::unique_ptr<InstrProfReader> Result;
192 return std::move(Result);
197 const Twine &RemappingPath) {
200 if (
Error E = BufferOrError.takeError())
204 std::unique_ptr<MemoryBuffer> RemappingBuffer;
205 std::string RemappingPathStr = RemappingPath.
str();
206 if (!RemappingPathStr.empty()) {
208 if (
Error E = RemappingBufferOrError.takeError())
210 RemappingBuffer = std::move(RemappingBufferOrError.get());
214 std::move(RemappingBuffer));
219 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
223 auto Result = std::make_unique<IndexedInstrProfReader>(
224 std::move(Buffer), std::move(RemappingBuffer));
230 return std::move(Result);
240 [](
char c) { return isPrint(c) || isSpace(c); });
251 if (Str.equals_insensitive(
"ir"))
253 else if (Str.equals_insensitive(
"fe"))
255 else if (Str.equals_insensitive(
"csir")) {
258 }
else if (Str.equals_insensitive(
"entry_first"))
260 else if (Str.equals_insensitive(
"not_entry_first"))
262 else if (Str.equals_insensitive(
"single_byte_coverage"))
264 else if (Str.equals_insensitive(
"temporal_prof_traces")) {
266 if (
auto Err = readTemporalProfTraceData())
267 return error(std::move(Err));
280Error TextInstrProfReader::readTemporalProfTraceData() {
281 if ((++Line).is_at_end())
288 if ((++Line).is_at_end())
294 for (
uint32_t i = 0; i < NumTraces; i++) {
295 if ((++Line).is_at_end())
302 if ((++Line).is_at_end())
306 Line->
split(FuncNames,
",", -1,
false);
307 for (
auto &FuncName : FuncNames)
308 Trace.FunctionNameRefs.push_back(
318#define CHECK_LINE_END(Line) \
319 if (Line.is_at_end()) \
320 return error(instrprof_error::truncated);
321#define READ_NUM(Str, Dst) \
322 if ((Str).getAsInteger(10, (Dst))) \
323 return error(instrprof_error::malformed);
324#define VP_READ_ADVANCE(Val) \
325 CHECK_LINE_END(Line); \
327 READ_NUM((*Line), (Val)); \
338 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
340 "number of value kinds is invalid");
343 for (
uint32_t VK = 0; VK < NumValueKinds; VK++) {
345 if (ValueKind > IPVK_Last)
352 Record.reserveSites(VK, NumValueSites);
353 for (
uint32_t S = 0; S < NumValueSites; S++) {
356 std::vector<InstrProfValueData> CurrentValues;
359 std::pair<StringRef, StringRef> VD = Line->
rsplit(
':');
361 if (ValueKind == IPVK_IndirectCallTarget) {
373 CurrentValues.push_back({
Value, TakenCount});
376 Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
384#undef VP_READ_ADVANCE
399 return error(std::move(
E));
404 if ((Line++)->getAsInteger(0,
Record.Hash))
406 "function hash is not a valid integer");
412 if ((Line++)->getAsInteger(10, NumCounters))
414 "number of counters is not a valid integer");
415 if (NumCounters == 0)
420 Record.Counts.reserve(NumCounters);
425 if ((Line++)->getAsInteger(10, Count))
427 Record.Counts.push_back(Count);
432 Record.BitmapBytes.clear();
435 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
437 "number of bitmap bytes is not a valid integer");
438 if (NumBitmapBytes != 0) {
440 Record.BitmapBytes.reserve(NumBitmapBytes);
441 for (uint8_t
I = 0;
I < NumBitmapBytes; ++
I) {
445 if ((Line++)->getAsInteger(0, BitmapByte))
447 "bitmap byte is not a valid integer");
448 Record.BitmapBytes.push_back(BitmapByte);
455 return error(std::move(
E));
460template <
class IntPtrT>
465template <
class IntPtrT>
468 std::optional<uint64_t> Weight) {
469 if (TemporalProfTimestamps.empty()) {
470 assert(TemporalProfTraces.empty());
471 return TemporalProfTraces;
474 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
477 Trace.Weight = *Weight;
478 for (
auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
479 Trace.FunctionNameRefs.push_back(NameRef);
480 TemporalProfTraces = {std::move(
Trace)};
481 return TemporalProfTraces;
484template <
class IntPtrT>
490 return RawInstrProf::getMagic<IntPtrT>() == Magic ||
494template <
class IntPtrT>
496 if (!hasFormat(*DataBuffer))
501 DataBuffer->getBufferStart());
502 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
503 return readHeader(*Header);
506template <
class IntPtrT>
508 const char *
End = DataBuffer->getBufferEnd();
510 while (CurrentPos !=
End && *CurrentPos == 0)
513 if (CurrentPos ==
End)
519 "not enough space for another header");
521 if (
reinterpret_cast<size_t>(CurrentPos) %
alignof(
uint64_t))
523 "insufficient padding");
526 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
531 return readHeader(*Header);
534template <
class IntPtrT>
537 return error(std::move(
E));
539 const IntPtrT FPtr = swap(
I->FunctionPointer);
547template <
class IntPtrT>
553 (
"Profile uses raw profile format version = " +
554 Twine(GET_VERSION(Version)) +
556 "\nPLEASE update this tool to version in the raw profile, or "
557 "regenerate raw profile with expected version.")
559 if (useCorrelate() && !Correlator)
561 if (!useCorrelate() && Correlator)
566 const uint8_t *BinaryIdStart =
568 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
569 const uint8_t *BufferEnd = (
const uint8_t *)DataBuffer->getBufferEnd();
570 if (BinaryIdSize %
sizeof(
uint64_t) || BinaryIdEnd > BufferEnd)
572 if (BinaryIdSize != 0) {
575 BinaryIds, getDataEndianness()))
579 CountersDelta =
swap(Header.CountersDelta);
580 BitmapDelta =
swap(Header.BitmapDelta);
581 NamesDelta =
swap(Header.NamesDelta);
582 auto NumData =
swap(Header.NumData);
583 auto PaddingBytesBeforeCounters =
swap(Header.PaddingBytesBeforeCounters);
584 auto CountersSize =
swap(Header.NumCounters) * getCounterTypeSize();
585 auto PaddingBytesAfterCounters =
swap(Header.PaddingBytesAfterCounters);
586 auto NumBitmapBytes =
swap(Header.NumBitmapBytes);
587 auto PaddingBytesAfterBitmapBytes =
swap(Header.PaddingBytesAfterBitmapBytes);
588 auto NamesSize =
swap(Header.NamesSize);
589 ValueKindLast =
swap(Header.ValueKindLast);
592 auto PaddingSize = getNumPaddingBytes(NamesSize);
596 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
598 CountersOffset + CountersSize + PaddingBytesAfterCounters;
600 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
601 ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
603 auto *Start =
reinterpret_cast<const char *
>(&Header);
604 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
610 assert(DataSize == 0 && NamesSize == 0);
611 assert(CountersDelta == 0 && NamesDelta == 0);
612 Data = Correlator->getDataPointer();
619 DataEnd =
Data + NumData;
620 NamesStart = Start + NamesOffset;
621 NamesEnd = NamesStart + NamesSize;
624 CountersStart = Start + CountersOffset;
625 CountersEnd = CountersStart + CountersSize;
626 BitmapStart = Start + BitmapOffset;
627 BitmapEnd = BitmapStart + NumBitmapBytes;
628 ValueDataStart =
reinterpret_cast<const uint8_t *
>(Start + ValueDataOffset);
630 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
631 if (
Error E = createSymtab(*NewSymtab))
634 Symtab = std::move(NewSymtab);
638template <
class IntPtrT>
644template <
class IntPtrT>
650template <
class IntPtrT>
654 if (NumCounters == 0)
658 if (CounterBaseOffset < 0)
661 (
"counter offset " +
Twine(CounterBaseOffset) +
" is negative").str());
663 if (CounterBaseOffset >= CountersEnd - CountersStart)
665 (
"counter offset " +
Twine(CounterBaseOffset) +
666 " is greater than the maximum counter offset " +
667 Twine(CountersEnd - CountersStart - 1))
671 (CountersEnd - (CountersStart + CounterBaseOffset)) /
672 getCounterTypeSize();
673 if (NumCounters > MaxNumCounters)
675 (
"number of counters " +
Twine(NumCounters) +
676 " is greater than the maximum number of counters " +
677 Twine(MaxNumCounters))
681 Record.Counts.reserve(NumCounters);
684 CountersStart + CounterBaseOffset +
I * getCounterTypeSize();
685 if (
I == 0 && hasTemporalProfile()) {
687 if (TimestampValue != 0 &&
688 TimestampValue != std::numeric_limits<uint64_t>::max()) {
689 TemporalProfTimestamps.emplace_back(TimestampValue,
691 TemporalProfTraceStreamSize = 1;
693 if (hasSingleByteCoverage()) {
702 if (hasSingleByteCoverage()) {
704 Record.Counts.push_back(*
Ptr == 0 ? 1 : 0);
707 if (CounterValue > MaxCounterValue && Warn)
708 Warn(make_error<InstrProfError>(
711 Record.Counts.push_back(CounterValue);
718template <
class IntPtrT>
722 Record.BitmapBytes.clear();
723 Record.BitmapBytes.reserve(NumBitmapBytes);
727 if (NumBitmapBytes == 0)
732 if (BitmapOffset < 0)
735 (
"bitmap offset " +
Twine(BitmapOffset) +
" is negative").str());
737 if (BitmapOffset >= BitmapEnd - BitmapStart)
739 (
"bitmap offset " +
Twine(BitmapOffset) +
740 " is greater than the maximum bitmap offset " +
741 Twine(BitmapEnd - BitmapStart - 1))
745 (BitmapEnd - (BitmapStart + BitmapOffset)) /
sizeof(uint8_t);
746 if (NumBitmapBytes > MaxNumBitmapBytes)
748 (
"number of bitmap bytes " +
Twine(NumBitmapBytes) +
749 " is greater than the maximum number of bitmap bytes " +
750 Twine(MaxNumBitmapBytes))
754 const char *
Ptr = BitmapStart + BitmapOffset +
I;
761template <
class IntPtrT>
765 CurValueDataSize = 0;
769 NumValueKinds += (
Data->NumValueSites[
I] != 0);
775 ValueProfData::getValueProfData(
776 ValueDataStart, (
const unsigned char *)DataBuffer->getBufferEnd(),
777 getDataEndianness());
785 VDataPtrOrErr.
get()->deserializeTo(
Record, Symtab.get());
786 CurValueDataSize = VDataPtrOrErr.
get()->getSize();
790template <
class IntPtrT>
796 if (
Error E = readNextHeader(getNextHeaderPos()))
797 return error(std::move(
E));
801 return error(std::move(
E));
805 return error(std::move(
E));
809 return error(std::move(
E));
813 return error(std::move(
E));
817 return error(std::move(
E));
824template <
class IntPtrT>
826 std::vector<llvm::object::BuildID> &BinaryIds) {
827 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
828 this->BinaryIds.end());
832template <
class IntPtrT>
834 if (!BinaryIds.empty())
855 const unsigned char *&
D,
const unsigned char *
const End) {
857 ValueProfData::getValueProfData(
D,
End, ValueProfDataEndianness);
862 VDataPtrOrErr.
get()->deserializeTo(DataBuffer.back(),
nullptr);
863 D += VDataPtrOrErr.
get()->TotalSize;
870 using namespace support;
877 std::vector<uint64_t> CounterBuffer;
878 std::vector<uint8_t> BitmapByteBuffer;
880 const unsigned char *
End =
D +
N;
886 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
D);
895 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
D);
901 CounterBuffer.clear();
902 CounterBuffer.reserve(CountsSize);
903 for (
uint64_t J = 0; J < CountsSize; ++J)
904 CounterBuffer.push_back(
905 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
D));
913 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
D);
915 if (
D + BitmapBytes *
sizeof(uint8_t) >
End)
917 BitmapByteBuffer.clear();
918 BitmapByteBuffer.reserve(BitmapBytes);
919 for (
uint64_t J = 0; J < BitmapBytes; ++J)
920 BitmapByteBuffer.push_back(
static_cast<uint8_t
>(
921 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(
925 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
926 std::move(BitmapByteBuffer));
938template <
typename HashTableImpl>
941 auto Iter = HashTable->find(FuncName);
942 if (Iter == HashTable->end())
948 "profile data is empty");
953template <
typename HashTableImpl>
959 Data = *RecordIterator;
963 "profile data is empty");
968template <
typename HashTableImpl>
970 const unsigned char *Buckets,
const unsigned char *
const Payload,
973 FormatVersion = Version;
974 HashTable.reset(HashTableImpl::Create(
975 Buckets, Payload,
Base,
976 typename HashTableImpl::InfoType(HashType, Version)));
977 RecordIterator = HashTable->data_begin();
980template <
typename HashTableImpl>
992 : Underlying(Underlying) {}
996 return Underlying.getRecords(FuncName, Data);
1002template <
typename HashTableImpl>
1007 std::unique_ptr<MemoryBuffer> RemapBuffer,
1009 : RemapBuffer(
std::
move(RemapBuffer)), Underlying(Underlying) {
1017 std::pair<StringRef, StringRef> Parts = {
StringRef(),
Name};
1019 Parts = Parts.second.split(
':');
1020 if (Parts.first.startswith(
"_Z"))
1022 if (Parts.second.empty())
1043 if (
auto Key = Remappings.
insert(RealName)) {
1047 MappedNames.insert({Key, RealName});
1056 if (
auto Key = Remappings.
lookup(RealName)) {
1057 StringRef Remapped = MappedNames.lookup(Key);
1058 if (!Remapped.
empty()) {
1060 RealName.
end() == FuncName.
end())
1061 FuncName = Remapped;
1066 Error E = Underlying.getRecords(Reconstituted,
Data);
1073 std::move(
E), [](std::unique_ptr<InstrProfError> Err) {
1076 :
Error(std::move(Err));
1082 return Underlying.getRecords(FuncName,
Data);
1088 std::unique_ptr<MemoryBuffer> RemapBuffer;
1104 using namespace support;
1108 uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
1114const unsigned char *
1116 const unsigned char *Cur,
bool UseCS) {
1117 using namespace IndexedInstrProf;
1118 using namespace support;
1123 uint64_t NFields = endian::byte_swap<uint64_t, llvm::endianness::little>(
1125 uint64_t NEntries = endian::byte_swap<uint64_t, llvm::endianness::little>(
1129 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1134 for (
unsigned I = 0;
I < SummarySize /
sizeof(
uint64_t);
I++)
1135 Dst[
I] = endian::byte_swap<uint64_t, llvm::endianness::little>(Src[
I]);
1138 for (
unsigned I = 0;
I < SummaryData->NumCutoffEntries;
I++) {
1143 std::unique_ptr<llvm::ProfileSummary> &Summary =
1144 UseCS ? this->CS_Summary : this->Summary;
1147 Summary = std::make_unique<ProfileSummary>(
1149 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1150 SummaryData->get(Summary::MaxBlockCount),
1151 SummaryData->get(Summary::MaxInternalBlockCount),
1152 SummaryData->get(Summary::MaxFunctionCount),
1153 SummaryData->get(Summary::TotalNumBlocks),
1154 SummaryData->get(Summary::TotalNumFunctions));
1155 return Cur + SummarySize;
1163 Summary = Builder.getSummary();
1169 using namespace support;
1171 const unsigned char *Start =
1172 (
const unsigned char *)DataBuffer->getBufferStart();
1173 const unsigned char *Cur = Start;
1174 if ((
const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1179 return HeaderOr.takeError();
1182 Cur += Header->size();
1186 if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
1192 endian::byte_swap<uint64_t, llvm::endianness::little>(Header->HashType));
1197 endian::byte_swap<uint64_t, llvm::endianness::little>(Header->HashOffset);
1200 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1201 Start + HashOffset, Cur, Start, HashType, Header->formatVersion());
1205 if (GET_VERSION(Header->formatVersion()) >= 8 &&
1206 Header->formatVersion() & VARIANT_MASK_MEMPROF) {
1208 endian::byte_swap<uint64_t, llvm::endianness::little>(
1209 Header->MemProfOffset);
1211 const unsigned char *
Ptr = Start + MemProfOffset;
1218 const uint64_t FramePayloadOffset =
1229 return SchemaOr.takeError();
1230 Schema = SchemaOr.get();
1234 Start + RecordTableOffset,
1240 Start + FrameTableOffset,
1241 Start + FramePayloadOffset,
1247 if (GET_VERSION(Header->formatVersion()) >= 9) {
1249 endian::byte_swap<uint64_t, llvm::endianness::little>(
1250 Header->BinaryIdOffset);
1251 const unsigned char *
Ptr = Start + BinaryIdOffset;
1256 if (BinaryIdsSize %
sizeof(
uint64_t))
1259 BinaryIdsStart =
Ptr;
1260 if (BinaryIdsStart > (
const unsigned char *)DataBuffer->getBufferEnd())
1262 "corrupted binary ids");
1265 if (GET_VERSION(Header->formatVersion()) >= 10 &&
1266 Header->formatVersion() & VARIANT_MASK_TEMPORAL_PROF) {
1267 uint64_t TemporalProfTracesOffset =
1268 endian::byte_swap<uint64_t, llvm::endianness::little>(
1269 Header->TemporalProfTracesOffset);
1270 const unsigned char *
Ptr = Start + TemporalProfTracesOffset;
1271 const auto *PtrEnd = (
const unsigned char *)DataBuffer->getBufferEnd();
1281 for (
unsigned i = 0; i < NumTraces; i++) {
1293 if (
Ptr + NumFunctions *
sizeof(
uint64_t) > PtrEnd)
1295 for (
unsigned j = 0; j < NumFunctions; j++) {
1299 Trace.FunctionNameRefs.push_back(NameRef);
1306 if (RemappingBuffer) {
1308 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1309 std::move(RemappingBuffer), *IndexPtr);
1310 if (
Error E = Remapper->populateRemappings())
1313 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1315 Index = std::move(IndexPtr);
1324 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
1325 if (
Error E =
Index->populateSymtab(*NewSymtab)) {
1330 Symtab = std::move(NewSymtab);
1339 auto Err = Remapper->getRecords(FuncName,
Data);
1346 return make_error<InstrProfError>(IE);
1347 if (
auto Err = Remapper->getRecords(DeprecatedFuncName,
Data))
1352 return std::move(Err2);
1358 bool CSBitMatch =
false;
1359 auto getFuncSum = [](
const std::vector<uint64_t> &Counts) {
1361 for (
uint64_t CountValue : Counts) {
1365 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1366 return std::numeric_limits<uint64_t>::max();
1367 ValueSum += CountValue;
1374 if (
I.Hash == FuncHash)
1375 return std::move(
I);
1379 if (MismatchedFuncSum ==
nullptr)
1381 FuncSum = std::max(FuncSum, getFuncSum(
I.Counts));
1385 if (MismatchedFuncSum !=
nullptr)
1386 *MismatchedFuncSum = FuncSum;
1395 if (MemProfRecordTable ==
nullptr)
1397 "no memprof data available in profile");
1398 auto Iter = MemProfRecordTable->find(FuncNameHash);
1399 if (Iter == MemProfRecordTable->end())
1400 return make_error<InstrProfError>(
1402 "memprof record not found for function hash " +
Twine(FuncNameHash));
1407 bool HasFrameMappingError =
false;
1409 auto FrIter = MemProfFrameTable->find(Id);
1410 if (FrIter == MemProfFrameTable->end()) {
1411 LastUnmappedFrameId = Id;
1412 HasFrameMappingError =
true;
1421 if (HasFrameMappingError) {
1423 "memprof frame not found for frame id " +
1424 Twine(LastUnmappedFrameId));
1431 std::vector<uint64_t> &Counts) {
1434 return error(std::move(
E));
1436 Counts =
Record.get().Counts;
1444 return error(std::move(
E));
1446 BitmapBytes =
Record.get().BitmapBytes;
1455 return error(std::move(
E));
1458 if (RecordIndex >=
Data.size()) {
1459 Index->advanceToNextKey();
1466 std::vector<llvm::object::BuildID> &BinaryIds) {
1472 std::vector<llvm::object::BuildID> BinaryIds;
1481 for (
const auto &Func : *
this) {
1484 if (FuncIsCS != IsCS)
1487 Func.accumulateCounts(Sum);
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.
Provides ErrorOr<T> smart pointer.
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
static Error initializeReader(InstrProfReader &Reader)
static void printBinaryIdsInternal(raw_ostream &OS, std::vector< llvm::object::BuildID > &BinaryIds)
static Error readBinaryIdsInternal(const MemoryBuffer &DataBuffer, const uint64_t BinaryIdsSize, const uint8_t *BinaryIdsStart, std::vector< llvm::object::BuildID > &BinaryIds, const llvm::endianness Endian)
Read a list of binary ids from a profile that consist of a.
#define READ_NUM(Str, Dst)
#define CHECK_LINE_END(Line)
#define VP_READ_ADVANCE(Val)
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
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.
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.
Expected< InstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Error getFunctionBitmapBytes(StringRef FuncName, uint64_t FuncHash, std::vector< uint8_t > &BitmapBytes)
Fill Bitmap Bytes 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.
const char * getNamesPointer() const
Return a pointer to the names string that this class constructs.
std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
size_t getNamesSize() const
Return the number of bytes in the names string.
static std::pair< instrprof_error, std::string > take(Error E)
Consume an Error and return the raw enum value contained within it, and the optional error message.
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)
Error populateRemappings() override
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.
std::unique_ptr< InstrProfSymtab > Symtab
Error success()
Clear the current error and return a successful one.
SmallVector< TemporalProfTraceTy > TemporalProfTraces
A list of temporal profile traces.
uint64_t TemporalProfTraceStreamSize
The total number of temporal profile traces seen.
static Expected< std::unique_ptr< InstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const InstrProfCorrelator *Correlator=nullptr, std::function< void(Error)> Warn=nullptr)
Factory method to create an appropriately typed reader for the given instrprof file.
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...
static bool isExternalSymbol(const StringRef &Symbol)
True if Symbol is the value used to represent external symbols.
void mapAddress(uint64_t Addr, uint64_t MD5Val)
Map a function address to its name's MD5 hash.
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...
size_t getBufferSize() const
const char * getBufferEnd() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
const char * getBufferStart() const
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.
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.
SmallVector< TemporalProfTraceTy > & getTemporalProfTraces(std::optional< uint64_t > Weight={}) override
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator insert(iterator I, T &&Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
bool startswith(StringRef Prefix) const
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
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...
std::string str() const
Return the twine contents as a std::string.
LLVM Value Representation.
bool is_at_end() const
Return true if we're an "end" iterator or have reached EOF.
This class implements an extremely fast bulk output stream that can only output to a stream.
The virtual file system interface.
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
uint64_t ComputeHash(StringRef K)
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
This is an optimization pass for GlobalISel generic memory operations.
RawInstrProfReader< uint32_t > RawInstrProfReader32
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
std::vector< ProfileSummaryEntry > SummaryEntryVector
@ raw_profile_version_mismatch
@ missing_debug_info_for_correlation
@ counter_value_too_large
@ unexpected_debug_info_for_correlation
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...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
RawInstrProfReader< uint64_t > RawInstrProfReader64
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
InstrProfKind
An enum describing the attributes of an instrumented profile.
@ FunctionEntryInstrumentation
@ FrontendInstrumentation
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
uint64_t Cutoff
The required percentile of total execution count.
uint64_t NumBlocks
Number of blocks >= the minumum execution count.
uint64_t MinBlockCount
The minimum execution count for this percentile.
static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries)
uint64_t NumSummaryFields
uint64_t NumCutoffEntries
Profiling information for a single function.
static bool hasCSFlagInHash(uint64_t FuncHash)
An ordered list of functions identified by their NameRef found in INSTR_PROF_DATA.