37#include <system_error>
78 if (std::error_code EC = BufferOrErr.getError())
80 return std::move(BufferOrErr.get());
98 std::vector<llvm::object::BuildID> &BinaryIds,
103 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.
data();
105 if (BinaryIdsSize == 0)
108 const uint8_t *BI = BinaryIdsStart;
109 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
114 size_t Remaining = BIEnd - BI;
119 "not enough data to read binary id length");
124 "binary id length is 0");
126 Remaining = BIEnd - BI;
140 "binary id section is greater than buffer size");
148 OS <<
"Binary IDs: \n";
149 for (
const auto &BI : BinaryIds) {
161 std::function<
void(
Error)> Warn) {
164 if (
Error E = BufferOrError.takeError())
167 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
174 std::function<
void(
Error)> Warn) {
175 if (Buffer->getBufferSize() == 0)
178 std::unique_ptr<InstrProfReader> Result;
184 BIDFetcher, BIDFetcherCorrelatorKind,
188 BIDFetcher, BIDFetcherCorrelatorKind,
199 return std::move(Result);
204 const Twine &RemappingPath) {
207 if (
Error E = BufferOrError.takeError())
211 std::unique_ptr<MemoryBuffer> RemappingBuffer;
212 std::string RemappingPathStr = RemappingPath.
str();
213 if (!RemappingPathStr.empty()) {
215 if (
Error E = RemappingBufferOrError.takeError())
217 RemappingBuffer = std::move(RemappingBufferOrError.get());
221 std::move(RemappingBuffer));
226 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
230 auto Result = std::make_unique<IndexedInstrProfReader>(
231 std::move(Buffer), std::move(RemappingBuffer));
237 return std::move(Result);
247 [](
char c) { return isPrint(c) || isSpace(c); });
256 while (Line->starts_with(
":")) {
258 if (Str.equals_insensitive(
"ir"))
260 else if (Str.equals_insensitive(
"fe"))
262 else if (Str.equals_insensitive(
"csir")) {
265 }
else if (Str.equals_insensitive(
"entry_first"))
267 else if (Str.equals_insensitive(
"not_entry_first"))
269 else if (Str.equals_insensitive(
"instrument_loop_entries"))
271 else if (Str.equals_insensitive(
"single_byte_coverage"))
273 else if (Str.equals_insensitive(
"temporal_prof_traces")) {
275 if (
auto Err = readTemporalProfTraceData())
276 return error(std::move(Err));
289Error TextInstrProfReader::readTemporalProfTraceData() {
290 if ((++Line).is_at_end())
294 if (Line->getAsInteger(0, NumTraces))
297 if ((++Line).is_at_end())
303 for (
uint32_t i = 0; i < NumTraces; i++) {
304 if ((++Line).is_at_end())
308 if (Line->getAsInteger(0,
Trace.Weight))
311 if ((++Line).is_at_end())
315 Line->split(FuncNames,
",", -1,
false);
316 for (
auto &FuncName : FuncNames)
317 Trace.FunctionNameRefs.push_back(
327#define CHECK_LINE_END(Line) \
328 if (Line.is_at_end()) \
329 return error(instrprof_error::truncated);
330#define READ_NUM(Str, Dst) \
331 if ((Str).getAsInteger(10, (Dst))) \
332 return error(instrprof_error::malformed);
333#define VP_READ_ADVANCE(Val) \
334 CHECK_LINE_END(Line); \
336 READ_NUM((*Line), (Val)); \
339 if (Line.is_at_end())
342 uint32_t NumValueKinds;
343 if (Line->getAsInteger(10, NumValueKinds)) {
347 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
349 "number of value kinds is invalid");
352 for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
354 if (ValueKind > IPVK_Last)
365 std::vector<InstrProfValueData> CurrentValues;
366 for (uint32_t V = 0;
V < NumValueData;
V++) {
368 std::pair<StringRef, StringRef> VD = Line->rsplit(
':');
370 if (ValueKind == IPVK_IndirectCallTarget) {
378 }
else if (ValueKind == IPVK_VTableTarget) {
390 CurrentValues.push_back({
Value, TakenCount});
393 assert(CurrentValues.size() == NumValueData);
394 Record.addValueData(ValueKind, S, CurrentValues,
nullptr);
401#undef VP_READ_ADVANCE
406 while (!Line.is_at_end() && (Line->empty() || Line->starts_with(
"#")))
409 if (Line.is_at_end()) {
416 return error(std::move(E));
419 if (Line.is_at_end())
421 if ((Line++)->getAsInteger(0,
Record.Hash))
423 "function hash is not a valid integer");
426 uint64_t NumCounters;
427 if (Line.is_at_end())
429 if ((Line++)->getAsInteger(10, NumCounters))
431 "number of counters is not a valid integer");
432 if (NumCounters == 0)
437 Record.Counts.reserve(NumCounters);
438 for (uint64_t
I = 0;
I < NumCounters; ++
I) {
439 if (Line.is_at_end())
442 if ((Line++)->getAsInteger(10,
Count))
453 Record.BitmapBytes.clear();
456 if ((Line++)->drop_front(1).trim().getAsInteger(0,
NumBitmapBytes))
458 "number of bitmap bytes is not a valid integer");
463 if (Line.is_at_end())
466 if ((Line++)->getAsInteger(0, BitmapByte))
468 "bitmap byte is not a valid integer");
469 Record.BitmapBytes.push_back(BitmapByte);
476 return error(std::move(E));
481template <
class IntPtrT>
486template <
class IntPtrT>
489 std::optional<uint64_t> Weight) {
490 if (TemporalProfTimestamps.empty()) {
495 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
498 Trace.Weight = *Weight;
499 for (
auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
500 Trace.FunctionNameRefs.push_back(NameRef);
505template <
class IntPtrT>
507 if (DataBuffer.getBufferSize() <
sizeof(uint64_t))
510 *
reinterpret_cast<const uint64_t *
>(DataBuffer.getBufferStart());
515template <
class IntPtrT>
521 std::string(
"profile file header is truncated"));
523 DataBuffer->getBufferStart());
528template <
class IntPtrT>
529Error RawInstrProfReader<IntPtrT>::readNextHeader(
const char *CurrentPos) {
530 const char *End = DataBuffer->getBufferEnd();
532 while (CurrentPos != End && *CurrentPos == 0)
535 if (CurrentPos == End)
541 "not enough space for another header");
543 if (
reinterpret_cast<size_t>(CurrentPos) %
alignof(uint64_t))
545 "insufficient padding");
547 uint64_t Magic = *
reinterpret_cast<const uint64_t *
>(CurrentPos);
553 return readHeader(*Header);
556template <
class IntPtrT>
559 StringRef(VNamesStart, VNamesEnd - VNamesStart)))
560 return error(std::move(
E));
562 const IntPtrT FPtr = swap(
I->FunctionPointer);
568 if (VTableBegin !=
nullptr && VTableEnd !=
nullptr) {
570 I != VTableEnd; ++
I) {
571 const IntPtrT VPtr =
swap(
I->VTablePointer);
579 swap(
I->VTableNameHash));
585template <
class IntPtrT>
591 (
"Profile uses raw profile format version = " +
594 "\nPLEASE update this tool to version in the raw profile, or "
595 "regenerate raw profile with expected version.")
599 const uint8_t *BinaryIdStart =
601 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
602 const uint8_t *BufferEnd = (
const uint8_t *)DataBuffer->getBufferEnd();
603 if (BinaryIdSize %
sizeof(
uint64_t))
606 (
"BinaryIdSize (" +
Twine(BinaryIdSize) +
") is not a multiple of 8")
608 if (BinaryIdEnd > BufferEnd)
610 (
"Header.BinaryIdSize = " +
Twine(BinaryIdSize) +
" bytes; " +
611 Twine(BufferEnd - BinaryIdStart) +
" bytes available")
615 if (!BinaryIdsBuffer.empty()) {
617 BinaryIds, getDataEndianness()))
621 CountersDelta =
swap(Header.CountersDelta);
622 BitmapDelta =
swap(Header.BitmapDelta);
624 NamesDelta =
swap(Header.NamesDelta);
625 auto NumData =
swap(Header.NumData);
626 auto PaddingBytesBeforeCounters =
swap(Header.PaddingBytesBeforeCounters);
627 auto CountersSize =
swap(Header.NumCounters) * getCounterTypeSize();
628 auto PaddingBytesAfterCounters =
swap(Header.PaddingBytesAfterCounters);
630 auto PaddingBytesAfterBitmapBytes =
swap(Header.PaddingBytesAfterBitmapBytes);
631 auto NumUniformCounters =
swap(Header.NumUniformCounters);
632 auto PaddingBytesAfterUniformCounters =
633 swap(Header.PaddingBytesAfterUniformCounters);
634 auto NamesSize =
swap(Header.NamesSize);
635 auto VTableNameSize =
swap(Header.VNamesSize);
636 auto NumVTables =
swap(Header.NumVTables);
637 ValueKindLast =
swap(Header.ValueKindLast);
640 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
641 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
643 auto VTableSectionSize =
645 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
646 auto UniformCountersSectionSize = NumUniformCounters *
sizeof(
uint64_t);
650 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
651 ptrdiff_t BitmapOffset =
652 CountersOffset + CountersSize + PaddingBytesAfterCounters;
653 ptrdiff_t UniformCountersOffset =
655 ptrdiff_t NamesOffset = UniformCountersOffset + UniformCountersSectionSize +
656 PaddingBytesAfterUniformCounters;
657 ptrdiff_t VTableProfDataOffset =
658 NamesOffset + NamesSize + PaddingBytesAfterNames;
659 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
660 PaddingBytesAfterVTableProfData;
661 ptrdiff_t ValueDataOffset =
662 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
664 auto *
Start =
reinterpret_cast<const char *
>(&Header);
665 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
669 (
"profile file size (" +
Twine(DataBuffer->getBufferSize()) +
670 " bytes) smaller than expected (at least " +
Twine(ValueDataOffset) +
673 Twine(BinaryIdSize) +
"(BinaryIdSize) + " +
674 Twine(DataSize) +
"(DataSize) + " +
675 Twine(CountersSize) +
"(CountersSize) + " +
677 Twine(UniformCountersSectionSize) +
"(UniformCountersSectionSize) + " +
678 Twine(NamesSize) +
"(NamesSize) + " +
679 Twine(VTableSectionSize) +
"(VTableSectionSize) + " +
680 Twine(VTableNameSize) +
"(VTableNameSize) + " +
681 Twine(PaddingBytesBeforeCounters + PaddingBytesAfterCounters +
682 PaddingBytesAfterBitmapBytes + PaddingBytesAfterUniformCounters +
683 PaddingBytesAfterNames + PaddingBytesAfterVTableProfData +
684 PaddingBytesAfterVTableNames) +
690 std::vector<object::BuildID> BinaryIDs;
691 if (
Error E = readBinaryIds(BinaryIDs))
694 BIDFetcher, BinaryIDs)
695 .moveInto(BIDFetcherCorrelator)) {
698 if (
auto Err = BIDFetcherCorrelator->correlateProfileData(0))
705 if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
706 BitmapDelta == 0 && NamesDelta == 0))
708 Data = Correlator->getDataPointer();
712 }
else if (BIDFetcherCorrelator) {
715 BIDFetcherCorrelator.get());
723 DataEnd =
Data + NumData;
726 Start + VTableProfDataOffset);
727 VTableEnd = VTableBegin + NumVTables;
730 VNamesStart =
Start + VTableNameOffset;
731 VNamesEnd = VNamesStart + VTableNameSize;
736 BitmapStart =
Start + BitmapOffset;
740 ValueDataStart =
reinterpret_cast<const uint8_t *
>(
Start + ValueDataOffset);
742 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
743 if (
Error E = createSymtab(*NewSymtab))
746 Symtab = std::move(NewSymtab);
750template <
class IntPtrT>
756template <
class IntPtrT>
762template <
class IntPtrT>
763Error RawInstrProfReader<IntPtrT>::readRawCounts(
765 uint32_t NumCounters =
swap(
Data->NumCounters);
766 if (NumCounters == 0)
769 ptrdiff_t CounterBaseOffset =
swap(
Data->CounterPtr) - CountersDelta;
770 if (CounterBaseOffset < 0)
773 (
"counter offset " +
Twine(CounterBaseOffset) +
" is negative").str());
777 (
"counter offset " +
Twine(CounterBaseOffset) +
778 " is greater than the maximum counter offset " +
784 getCounterTypeSize();
785 if (NumCounters > MaxNumCounters)
787 (
"number of counters " +
Twine(NumCounters) +
788 " is greater than the maximum number of counters " +
789 Twine(MaxNumCounters))
793 Record.Counts.reserve(NumCounters);
794 for (uint32_t
I = 0;
I < NumCounters;
I++) {
797 if (
I == 0 && hasTemporalProfile()) {
799 if (TimestampValue != 0 &&
800 TimestampValue != std::numeric_limits<uint64_t>::max()) {
801 TemporalProfTimestamps.emplace_back(TimestampValue,
803 TemporalProfTraceStreamSize = 1;
805 if (hasSingleByteCoverage()) {
814 if (hasSingleByteCoverage()) {
816 Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
819 if (CounterValue > MaxCounterValue && Warn)
823 Record.Counts.push_back(CounterValue);
830template <
class IntPtrT>
834 Record.BitmapBytes.clear();
843 ptrdiff_t BitmapOffset =
swap(
Data->BitmapPtr) - BitmapDelta;
844 if (BitmapOffset < 0)
847 (
"bitmap offset " +
Twine(BitmapOffset) +
" is negative").str());
849 if (BitmapOffset >= BitmapEnd - BitmapStart)
851 (
"bitmap offset " +
Twine(BitmapOffset) +
852 " is greater than the maximum bitmap offset " +
853 Twine(BitmapEnd - BitmapStart - 1))
857 (BitmapEnd - (BitmapStart + BitmapOffset)) /
sizeof(uint8_t);
861 " is greater than the maximum number of bitmap bytes " +
862 Twine(MaxNumBitmapBytes))
866 const char *Ptr = BitmapStart + BitmapOffset +
I;
873template <
class IntPtrT>
874Error RawInstrProfReader<IntPtrT>::readRawUniformCounters(
876 Record.UniformCounts.clear();
881 uint32_t NumCounters =
swap(
Data->NumCounters);
883 ptrdiff_t UniformCounterOffset =
885 if (UniformCounterOffset < 0)
887 (
"uniform counter offset " +
Twine(UniformCounterOffset) +
893 (
"uniform counter offset " +
Twine(UniformCounterOffset) +
894 " is greater than the maximum uniform counter offset " +
901 if (NumCounters > MaxNumCounters)
903 (
"number of uniform counters " +
Twine(NumCounters) +
904 " is greater than the maximum number of uniform counters " +
905 Twine(MaxNumCounters))
908 Record.UniformCounts.reserve(NumCounters);
909 for (uint32_t
I = 0;
I < NumCounters;
I++) {
913 Record.UniformCounts.push_back(CounterValue);
919template <
class IntPtrT>
920Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
923 CurValueDataSize = 0;
925 uint32_t NumValueKinds = 0;
926 for (uint32_t
I = 0;
I < IPVK_Last + 1;
I++)
927 NumValueKinds += (
Data->NumValueSites[
I] != 0);
933 ValueProfData::getValueProfData(
934 ValueDataStart, (
const unsigned char *)DataBuffer->getBufferEnd(),
935 getDataEndianness());
943 VDataPtrOrErr.
get()->deserializeTo(
Record, Symtab.get());
944 CurValueDataSize = VDataPtrOrErr.
get()->getSize();
948template <
class IntPtrT>
954 if (
Error E = readNextHeader(getNextHeaderPos()))
955 return error(std::move(E));
959 return error(std::move(E));
963 return error(std::move(E));
965 Record.OffloadDeviceWaveSize = swap(Data->OffloadDeviceWaveSize);
969 return error(std::move(E));
973 return error(std::move(E));
977 return error(std::move(E));
981 return error(std::move(E));
988template <
class IntPtrT>
990 std::vector<llvm::object::BuildID> &BinaryIds) {
991 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
992 this->BinaryIds.end());
996template <
class IntPtrT>
998 if (!BinaryIds.empty())
1019 const unsigned char *&
D,
const unsigned char *
const End) {
1021 ValueProfData::getValueProfData(
D, End, ValueProfDataEndianness);
1026 VDataPtrOrErr.
get()->deserializeTo(DataBuffer.back(),
nullptr);
1027 D += VDataPtrOrErr.
get()->TotalSize;
1037 if (
N %
sizeof(uint64_t))
1041 std::vector<uint64_t> CounterBuffer;
1042 std::vector<uint8_t> BitmapByteBuffer;
1043 std::vector<uint8_t> UniformityBitsBuffer;
1045 const unsigned char *End =
D +
N;
1048 if (
D +
sizeof(uint64_t) > End)
1053 uint64_t CountsSize =
N /
sizeof(uint64_t) - 1;
1056 if (
D +
sizeof(uint64_t) > End)
1061 if (
D + CountsSize *
sizeof(uint64_t) > End)
1064 CounterBuffer.clear();
1065 CounterBuffer.reserve(CountsSize);
1066 for (uint64_t J = 0; J < CountsSize; ++J)
1067 CounterBuffer.push_back(
1072 uint64_t BitmapBytes = 0;
1073 if (
D +
sizeof(uint64_t) > End)
1076 BitmapByteBuffer.clear();
1077 BitmapByteBuffer.reserve(BitmapBytes);
1082 uint64_t PaddedSize =
alignTo(BitmapBytes,
sizeof(uint64_t));
1083 if (
D + PaddedSize > End)
1085 for (uint64_t J = 0; J < BitmapBytes; ++J)
1086 BitmapByteBuffer.push_back(
1088 for (uint64_t J = BitmapBytes; J < PaddedSize; ++J)
1092 uint64_t UniformityBitsSize = 0;
1093 if (
D +
sizeof(uint64_t) > End)
1095 UniformityBitsSize =
1097 uint64_t PaddedUniformitySize =
1098 alignTo(UniformityBitsSize,
sizeof(uint64_t));
1099 if (
D + PaddedUniformitySize > End)
1101 UniformityBitsBuffer.clear();
1102 UniformityBitsBuffer.reserve(UniformityBitsSize);
1103 for (uint64_t J = 0; J < UniformityBitsSize; ++J)
1104 UniformityBitsBuffer.push_back(
1106 for (uint64_t J = UniformityBitsSize; J < PaddedUniformitySize; ++J)
1110 if (
D + BitmapBytes *
sizeof(uint64_t) > End)
1112 for (uint64_t J = 0; J < BitmapBytes; ++J)
1113 BitmapByteBuffer.push_back(
static_cast<uint8_t>(
1118 DataBuffer.emplace_back(
K, Hash, std::move(CounterBuffer),
1119 std::move(BitmapByteBuffer),
1120 std::move(UniformityBitsBuffer));
1132template <
typename HashTableImpl>
1135 auto Iter = HashTable->find(FuncName);
1136 if (Iter == HashTable->end())
1142 "profile data is empty");
1147template <
typename HashTableImpl>
1153 Data = *RecordIterator;
1157 "profile data is empty");
1162template <
typename HashTableImpl>
1164 const unsigned char *Buckets,
const unsigned char *
const Payload,
1168 HashTable.reset(HashTableImpl::Create(
1169 Buckets, Payload,
Base,
1170 typename HashTableImpl::InfoType(HashType,
Version)));
1171 RecordIterator = HashTable->data_begin();
1174template <
typename HashTableImpl>
1186 : Underlying(Underlying) {}
1190 return Underlying.getRecords(FuncName,
Data);
1196template <
typename HashTableImpl>
1201 std::unique_ptr<MemoryBuffer> RemapBuffer,
1203 : RemapBuffer(
std::
move(RemapBuffer)), Underlying(Underlying) {
1212 std::pair<StringRef, StringRef> Parts = {
StringRef(), Name};
1215 if (Parts.first.starts_with(
"_Z"))
1217 if (Parts.second.empty())
1227 Out.reserve(OrigName.
size() + Replacement.
size() - ExtractedName.
size());
1228 Out.insert(Out.end(), OrigName.
begin(), ExtractedName.
begin());
1230 Out.insert(Out.end(), ExtractedName.
end(), OrigName.
end());
1234 if (
Error E = Remappings.read(*RemapBuffer))
1236 for (
StringRef Name : Underlying.HashTable->keys()) {
1238 if (
auto Key = Remappings.insert(RealName)) {
1242 MappedNames.insert({
Key, RealName});
1251 if (
auto Key = Remappings.lookup(RealName)) {
1253 if (!Remapped.
empty()) {
1255 RealName.
end() == FuncName.
end())
1256 FuncName = Remapped;
1261 Error E = Underlying.getRecords(Reconstituted,
Data);
1268 std::move(E), [](std::unique_ptr<InstrProfError> Err) {
1271 :
Error(std::move(Err));
1277 return Underlying.getRecords(FuncName,
Data);
1283 std::unique_ptr<MemoryBuffer> RemapBuffer;
1301 if (DataBuffer.getBufferSize() < 8)
1309const unsigned char *
1311 const unsigned char *Cur,
bool UseCS) {
1324 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1327 const uint64_t *Src =
reinterpret_cast<const uint64_t *
>(SummaryInLE);
1328 uint64_t *Dst =
reinterpret_cast<uint64_t *
>(SummaryData.get());
1329 for (
unsigned I = 0;
I < SummarySize /
sizeof(uint64_t);
I++)
1333 for (
unsigned I = 0;
I < SummaryData->NumCutoffEntries;
I++) {
1338 std::unique_ptr<llvm::ProfileSummary> &Summary =
1339 UseCS ? this->CS_Summary : this->Summary;
1342 Summary = std::make_unique<ProfileSummary>(
1344 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1345 SummaryData->get(Summary::MaxBlockCount),
1346 SummaryData->get(Summary::MaxInternalBlockCount),
1347 SummaryData->get(Summary::MaxFunctionCount),
1348 SummaryData->get(Summary::TotalNumBlocks),
1349 SummaryData->get(Summary::TotalNumFunctions));
1350 return Cur + SummarySize;
1358 Summary = Builder.getSummary();
1366 const unsigned char *Start =
1367 (
const unsigned char *)DataBuffer->getBufferStart();
1368 const unsigned char *Cur = Start;
1369 if ((
const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1374 return HeaderOr.takeError();
1377 Cur += Header->
size();
1391 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1392 Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1396 if (Header->getIndexedProfileVersion() >= 8 &&
1398 if (
Error E = MemProfReader.deserialize(Start, Header->MemProfOffset))
1404 if (Header->getIndexedProfileVersion() >= 9) {
1405 const unsigned char *Ptr = Start + Header->BinaryIdOffset;
1407 uint64_t BinaryIdsSize =
1409 if (BinaryIdsSize %
sizeof(uint64_t))
1412 (
"BinaryIdSize (" +
Twine(BinaryIdsSize) +
") is not a multiple of 8")
1416 if (Ptr > (
const unsigned char *)DataBuffer->getBufferEnd())
1418 "corrupted binary ids");
1421 if (Header->getIndexedProfileVersion() >= 12) {
1422 const unsigned char *Ptr = Start + Header->VTableNamesOffset;
1424 uint64_t CompressedVTableNamesLen =
1429 const char *VTableNamePtr = (
const char *)Ptr;
1430 if (VTableNamePtr > DataBuffer->getBufferEnd())
1433 VTableName =
StringRef(VTableNamePtr, CompressedVTableNamesLen);
1436 if (Header->getIndexedProfileVersion() >= 10 &&
1438 const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset;
1439 const auto *PtrEnd = (
const unsigned char *)DataBuffer->getBufferEnd();
1441 if (Ptr + 2 *
sizeof(uint64_t) > PtrEnd)
1443 const uint64_t NumTraces =
1447 for (
unsigned i = 0; i < NumTraces; i++) {
1449 if (Ptr + 2 *
sizeof(uint64_t) > PtrEnd)
1454 const uint64_t NumFunctions =
1457 if (Ptr + NumFunctions *
sizeof(uint64_t) > PtrEnd)
1459 for (
unsigned j = 0; j < NumFunctions; j++) {
1460 const uint64_t NameRef =
1462 Trace.FunctionNameRefs.push_back(NameRef);
1469 if (RemappingBuffer) {
1471 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1472 std::move(RemappingBuffer), *IndexPtr);
1473 if (
Error E = Remapper->populateRemappings())
1476 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1478 Index = std::move(IndexPtr);
1487 auto NewSymtab = std::make_unique<InstrProfSymtab>();
1489 if (
Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1495 if (
Error E = Index->populateSymtab(*NewSymtab)) {
1500 Symtab = std::move(NewSymtab);
1506 uint64_t *MismatchedFuncSum) {
1508 uint64_t FuncSum = 0;
1509 auto Err = Remapper->getRecords(FuncName,
Data);
1517 if (
auto Err = Remapper->getRecords(DeprecatedFuncName,
Data))
1522 return std::move(Err2);
1528 bool CSBitMatch =
false;
1530 uint64_t ValueSum = 0;
1531 for (uint64_t CountValue : Counts) {
1532 if (CountValue == (uint64_t)-1)
1535 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1536 return std::numeric_limits<uint64_t>::max();
1537 ValueSum += CountValue;
1545 return std::move(
I);
1549 if (MismatchedFuncSum ==
nullptr)
1551 FuncSum = std::max(FuncSum, getFuncSum(
I.Counts));
1555 if (MismatchedFuncSum !=
nullptr)
1556 *MismatchedFuncSum = FuncSum;
1570 MemProfCallStackTable, FrameIdConv);
1578 "memprof call stack not found for call stack id " +
1585 "memprof frame not found for frame id " +
1595 if (MemProfRecordTable ==
nullptr)
1597 "no memprof data available in profile");
1598 auto Iter = MemProfRecordTable->find(FuncNameHash);
1599 if (Iter == MemProfRecordTable->end())
1602 "memprof record not found for function hash " +
Twine(FuncNameHash));
1607 assert(MemProfFrameTable &&
"MemProfFrameTable must be available");
1608 assert(MemProfCallStackTable &&
"MemProfCallStackTable must be available");
1610 *MemProfCallStackTable);
1614 assert(!MemProfFrameTable &&
"MemProfFrameTable must not be available");
1615 assert(!MemProfCallStackTable &&
1616 "MemProfCallStackTable must not be available");
1617 assert(FrameBase &&
"FrameBase must be available");
1618 assert(CallStackBase &&
"CallStackBase must be available");
1629 formatv(
"MemProf version {} not supported; "
1630 "requires version between {} and {}, inclusive",
1637 assert(MemProfRecordTable);
1652 MemProfRecordTable->data()) {
1654 IndexedRecord.AllocSites)
1659 for (
unsigned CS : Worklist.
set_bits())
1663 std::move(Extractor.CallerCalleePairs);
1666 for (
auto &[CallerGUID, CallList] : Pairs) {
1668 CallList.erase(
llvm::unique(CallList), CallList.end());
1677 MemProfRecordTable->getNumEntries());
1678 for (uint64_t
Key : MemProfRecordTable->keys()) {
1688 if (DataAccessProfileData !=
nullptr) {
1690 DataAccessProfileData->getRecords().size());
1692 DataAccessProfileData->getKnownColdSymbols().size());
1694 DataAccessProfileData->getKnownColdHashes().size());
1695 for (
const auto &[SymHandleRef, RecordRef] :
1696 DataAccessProfileData->getRecords())
1699 RecordRef.Locations));
1700 for (
StringRef ColdSymbol : DataAccessProfileData->getKnownColdSymbols())
1703 for (uint64_t Hash : DataAccessProfileData->getKnownColdHashes())
1709 return lhs.AccessCount > rhs.AccessCount;
1713 [](
const std::string &lhs,
const std::string &rhs) {
1718 [](
const uint64_t &lhs,
const uint64_t &rhs) { return lhs < rhs; });
1720 return AllMemProfData;
1725 std::vector<uint64_t> &Counts) {
1728 return error(std::move(E));
1730 Counts =
Record.get().Counts;
1739 return error(std::move(E));
1741 const auto &BitmapBytes =
Record.get().BitmapBytes;
1742 size_t I = 0, E = BitmapBytes.size();
1743 Bitmap.
resize(E * CHAR_BIT);
1746 using XTy =
decltype(
X);
1748 size_t N = std::min(E -
I,
sizeof(W));
1749 std::memset(W, 0,
sizeof(W));
1750 std::memcpy(W, &BitmapBytes[
I],
N);
1766 return error(std::move(E));
1769 if (RecordIndex >=
Data.size()) {
1770 Index->advanceToNextKey();
1777 std::vector<llvm::object::BuildID> &BinaryIds) {
1783 std::vector<llvm::object::BuildID> BinaryIds;
1791 uint64_t NumFuncs = 0;
1792 for (
const auto &Func : *
this) {
1795 if (FuncIsCS != IsCS)
1798 Func.accumulateCounts(Sum);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
InstrProfLookupTrait::offset_type offset_type
static Error initializeReader(InstrProfReader &Reader)
#define READ_NUM(Str, Dst)
#define CHECK_LINE_END(Line)
static Error readBinaryIdsInternal(const MemoryBuffer &DataBuffer, ArrayRef< uint8_t > BinaryIdsBuffer, std::vector< llvm::object::BuildID > &BinaryIds, const llvm::endianness Endian)
Read a list of binary ids from a profile that consist of a.
#define VP_READ_ADVANCE(Val)
InstrProfLookupTrait::data_type data_type
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static Expected< memprof::MemProfRecord > getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, MemProfFrameHashTable &MemProfFrameTable, MemProfCallStackHashTable &MemProfCallStackTable)
static void printBinaryIdsInternal(raw_ostream &OS, ArrayRef< llvm::object::BuildID > BinaryIds)
#define VARIANT_MASK_CSIR_PROF
#define VARIANT_MASK_MEMPROF
#define VARIANT_MASK_TEMPORAL_PROF
#define VARIANT_MASK_IR_PROF
#define VARIANT_MASK_BYTE_COVERAGE
#define VARIANT_MASK_INSTR_ENTRY
#define VARIANT_MASK_FUNCTION_ENTRY_ONLY
#define VARIANT_MASK_INSTR_LOOP_ENTRIES
static constexpr StringLiteral Filename
static StringRef getName(Value *V)
Defines the virtual file system interface vfs::FileSystem.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
BitVector & set()
Set all bits in the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
static BitVector & apply(F &&f, BitVector &Out, BitVector const &Arg, ArgTys const &...Args)
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.
Error readHeader() override
Read the file header.
Error printBinaryIds(raw_ostream &OS) override
Print binary ids.
Error getFunctionBitmap(StringRef FuncName, uint64_t FuncHash, BitVector &Bitmap)
Fill Bitmap with the profile data for the given function name.
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.
Expected< NamedInstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
LLVM_ABI memprof::AllMemProfData getAllMemProfData() const
LLVM_ABI Expected< memprof::MemProfRecord > getMemProfRecord(const uint64_t FuncNameHash) const
LLVM_ABI DenseMap< uint64_t, SmallVector< memprof::CallEdgeTy, 0 > > getMemProfCallerCalleePairs() const
InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template pointer type so that the Pro...
const RawInstrProf::ProfileData< IntPtrT > * getDataPointer() const
Return a pointer to the underlying ProfileData vector that this class constructs.
size_t getDataSize() const
Return the number of ProfileData elements.
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.
ProfCorrelatorKind
Indicate if we should use the debug info or profile metadata sections to correlate.
LLVM_ABI std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static LLVM_ABI llvm::Expected< std::unique_ptr< InstrProfCorrelator > > get(StringRef Filename, ProfCorrelatorKind FileKind, const object::BuildIDFetcher *BIDFetcher=nullptr, const ArrayRef< llvm::object::BuildID > BIs={})
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.
LLVM_ABI data_type ReadData(StringRef K, const unsigned char *D, offset_type N)
LLVM_ABI bool readValueProfilingData(const unsigned char *&D, const unsigned char *const End)
LLVM_ABI 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)
bool atEnd() const override
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.
virtual bool isIRLevelProfile() const =0
virtual Error readHeader()=0
Read the header. Required before reading first record.
LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS)
Compute the sum of counts and return in Sum.
static LLVM_ABI Expected< std::unique_ptr< InstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const InstrProfCorrelator *Correlator=nullptr, const object::BuildIDFetcher *BIDFetcher=nullptr, const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind=InstrProfCorrelator::ProfCorrelatorKind::NONE, std::function< void(Error)> Warn=nullptr)
Factory method to create an appropriately typed reader for the given instrprof file.
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
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.
LLVM_ABI Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
void mapVTableAddress(uint64_t StartAddr, uint64_t EndAddr, uint64_t MD5Val)
Map the address range (i.e., [start_address, end_address)) of a variable to its names' MD5 hash.
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 LLVM_ABI 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...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
char front() const
Get the first character in the string.
Reader for symbol remapping files.
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...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
BuildIDFetcher searches local cache directories for debug info.
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)
constexpr uint64_t MaximumSupportedVersion
constexpr uint64_t MinimumSupportedVersion
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
value_type byte_swap(value_type value, endianness endian)
Swap the bytes of value to match the given endianness.
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
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.
void stable_sort(R &&Range)
RawInstrProfReader< uint64_t > RawInstrProfReader64
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
RelativeUniformCounterPtr ValuesPtrExpr NumBitmapBytes
RelativeUniformCounterPtr ValuesPtrExpr NumValueSites[IPVK_Last+1]
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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersDelta
auto unique(Range &&R, Predicate P)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersStart
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
OnDiskIterableChainedHashTable< memprof::CallStackLookupTrait > MemProfCallStackHashTable
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OnDiskIterableChainedHashTable< memprof::FrameLookupTrait > MemProfFrameHashTable
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr CountersStart
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
@ raw_profile_version_mismatch
@ counter_value_too_large
@ unexpected_correlation_info
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr NamesStart
constexpr char GlobalIdentifierDelimiter
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::vector< ProfileSummaryEntry > SummaryEntryVector
void consumeError(Error Err)
Consume a Error without doing anything.
InstrProfKind
An enum describing the attributes of an instrumented profile.
@ LoopEntriesInstrumentation
@ FunctionEntryInstrumentation
@ FrontendInstrumentation
RawInstrProfReader< uint32_t > RawInstrProfReader32
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.
YamlDataAccessProfData YamlifiedDataAccessProfiles
std::vector< GUIDMemProfRecordPair > HeapProfileRecords
std::optional< CallStackId > LastUnmappedId
The data access profiles for a symbol.
std::optional< FrameId > LastUnmappedId
LLVM_ABI MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const
std::vector< memprof::DataAccessProfRecord > Records
std::vector< uint64_t > KnownColdStrHashes
std::vector< std::string > KnownColdSymbols