36#include <system_error>
46 if (Version & VARIANT_MASK_IR_PROF) {
47 ProfileKind |= InstrProfKind::IRInstrumentation;
49 if (Version & VARIANT_MASK_CSIR_PROF) {
50 ProfileKind |= InstrProfKind::ContextSensitive;
52 if (Version & VARIANT_MASK_INSTR_ENTRY) {
53 ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
55 if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) {
56 ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
58 if (Version & VARIANT_MASK_BYTE_COVERAGE) {
59 ProfileKind |= InstrProfKind::SingleByteCoverage;
61 if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
62 ProfileKind |= InstrProfKind::FunctionEntryOnly;
64 if (Version & VARIANT_MASK_MEMPROF) {
65 ProfileKind |= InstrProfKind::MemProf;
67 if (Version & VARIANT_MASK_TEMPORAL_PROF) {
68 ProfileKind |= InstrProfKind::TemporalProfile;
76 : FS.getBufferForFile(Filename);
77 if (std::error_code EC = BufferOrErr.getError())
79 return std::move(BufferOrErr.get());
97 std::vector<llvm::object::BuildID> &BinaryIds,
99 using namespace support;
102 const uint8_t *BinaryIdsStart = BinaryIdsBuffer.
data();
104 if (BinaryIdsSize == 0)
107 const uint8_t *BI = BinaryIdsStart;
108 const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
113 size_t Remaining = BIEnd - BI;
116 return make_error<InstrProfError>(
117 instrprof_error::malformed,
118 "not enough data to read binary id length");
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 OS <<
"Binary IDs: \n";
148 for (
const auto &BI : BinaryIds) {
160 std::function<
void(
Error)> Warn) {
163 if (
Error E = BufferOrError.takeError())
166 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
173 std::function<
void(
Error)> Warn) {
174 if (Buffer->getBufferSize() == 0)
177 std::unique_ptr<InstrProfReader> Result;
183 BIDFetcher, BIDFetcherCorrelatorKind,
187 BIDFetcher, BIDFetcherCorrelatorKind,
198 return std::move(Result);
203 const Twine &RemappingPath) {
206 if (
Error E = BufferOrError.takeError())
210 std::unique_ptr<MemoryBuffer> RemappingBuffer;
211 std::string RemappingPathStr = RemappingPath.
str();
212 if (!RemappingPathStr.empty()) {
214 if (
Error E = RemappingBufferOrError.takeError())
216 RemappingBuffer = std::move(RemappingBufferOrError.get());
220 std::move(RemappingBuffer));
225 std::unique_ptr<MemoryBuffer> RemappingBuffer) {
229 auto Result = std::make_unique<IndexedInstrProfReader>(
230 std::move(Buffer), std::move(RemappingBuffer));
236 return std::move(Result);
246 [](
char c) { return isPrint(c) || isSpace(c); });
257 if (Str.equals_insensitive(
"ir"))
259 else if (Str.equals_insensitive(
"fe"))
261 else if (Str.equals_insensitive(
"csir")) {
264 }
else if (Str.equals_insensitive(
"entry_first"))
266 else if (Str.equals_insensitive(
"not_entry_first"))
268 else if (Str.equals_insensitive(
"instrument_loop_entries"))
270 else if (Str.equals_insensitive(
"single_byte_coverage"))
272 else if (Str.equals_insensitive(
"temporal_prof_traces")) {
274 if (
auto Err = readTemporalProfTraceData())
275 return error(std::move(Err));
288Error TextInstrProfReader::readTemporalProfTraceData() {
289 if ((++Line).is_at_end())
296 if ((++Line).is_at_end())
302 for (
uint32_t i = 0; i < NumTraces; i++) {
303 if ((++Line).is_at_end())
310 if ((++Line).is_at_end())
314 Line->
split(FuncNames,
",", -1,
false);
315 for (
auto &FuncName : FuncNames)
316 Trace.FunctionNameRefs.push_back(
326#define CHECK_LINE_END(Line) \
327 if (Line.is_at_end()) \
328 return error(instrprof_error::truncated);
329#define READ_NUM(Str, Dst) \
330 if ((Str).getAsInteger(10, (Dst))) \
331 return error(instrprof_error::malformed);
332#define VP_READ_ADVANCE(Val) \
333 CHECK_LINE_END(Line); \
335 READ_NUM((*Line), (Val)); \
346 if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
348 "number of value kinds is invalid");
351 for (
uint32_t VK = 0; VK < NumValueKinds; VK++) {
353 if (ValueKind > IPVK_Last)
360 Record.reserveSites(VK, NumValueSites);
361 for (
uint32_t S = 0; S < NumValueSites; S++) {
364 std::vector<InstrProfValueData> CurrentValues;
367 std::pair<StringRef, StringRef> VD = Line->
rsplit(
':');
369 if (ValueKind == IPVK_IndirectCallTarget) {
377 }
else if (ValueKind == IPVK_VTableTarget) {
389 CurrentValues.push_back({
Value, TakenCount});
392 assert(CurrentValues.size() == NumValueData);
393 Record.addValueData(ValueKind, S, CurrentValues,
nullptr);
400#undef VP_READ_ADVANCE
415 return error(std::move(E));
420 if ((Line++)->getAsInteger(0,
Record.Hash))
422 "function hash is not a valid integer");
428 if ((Line++)->getAsInteger(10, NumCounters))
430 "number of counters is not a valid integer");
431 if (NumCounters == 0)
436 Record.Counts.reserve(NumCounters);
441 if ((Line++)->getAsInteger(10, Count))
443 Record.Counts.push_back(Count);
448 Record.BitmapBytes.clear();
451 if ((Line++)->drop_front(1).trim().getAsInteger(0, NumBitmapBytes))
453 "number of bitmap bytes is not a valid integer");
454 if (NumBitmapBytes != 0) {
456 Record.BitmapBytes.reserve(NumBitmapBytes);
457 for (
uint8_t I = 0;
I < NumBitmapBytes; ++
I) {
461 if ((Line++)->getAsInteger(0, BitmapByte))
463 "bitmap byte is not a valid integer");
464 Record.BitmapBytes.push_back(BitmapByte);
471 return error(std::move(E));
476template <
class IntPtrT>
481template <
class IntPtrT>
484 std::optional<uint64_t> Weight) {
485 if (TemporalProfTimestamps.empty()) {
486 assert(TemporalProfTraces.empty());
487 return TemporalProfTraces;
490 std::sort(TemporalProfTimestamps.begin(), TemporalProfTimestamps.end());
493 Trace.Weight = *Weight;
494 for (
auto &[TimestampValue, NameRef] : TemporalProfTimestamps)
495 Trace.FunctionNameRefs.push_back(NameRef);
496 TemporalProfTraces = {std::move(
Trace)};
497 return TemporalProfTraces;
500template <
class IntPtrT>
506 return RawInstrProf::getMagic<IntPtrT>() == Magic ||
510template <
class IntPtrT>
512 if (!hasFormat(*DataBuffer))
517 DataBuffer->getBufferStart());
518 ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
519 return readHeader(*Header);
522template <
class IntPtrT>
524 const char *
End = DataBuffer->getBufferEnd();
526 while (CurrentPos !=
End && *CurrentPos == 0)
529 if (CurrentPos ==
End)
535 "not enough space for another header");
537 if (
reinterpret_cast<size_t>(CurrentPos) %
alignof(
uint64_t))
539 "insufficient padding");
542 if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
547 return readHeader(*Header);
550template <
class IntPtrT>
553 StringRef(VNamesStart, VNamesEnd - VNamesStart)))
554 return error(std::move(E));
556 const IntPtrT FPtr = swap(
I->FunctionPointer);
562 if (VTableBegin !=
nullptr && VTableEnd !=
nullptr) {
564 I != VTableEnd; ++
I) {
573 swap(
I->VTableNameHash));
579template <
class IntPtrT>
585 (
"Profile uses raw profile format version = " +
588 "\nPLEASE update this tool to version in the raw profile, or "
589 "regenerate raw profile with expected version.")
596 const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
597 const uint8_t *BufferEnd = (
const uint8_t *)DataBuffer->getBufferEnd();
598 if (BinaryIdSize %
sizeof(
uint64_t) || BinaryIdEnd > BufferEnd)
601 if (!BinaryIdsBuffer.empty()) {
603 BinaryIds, getDataEndianness()))
607 CountersDelta =
swap(Header.CountersDelta);
608 BitmapDelta =
swap(Header.BitmapDelta);
609 NamesDelta =
swap(Header.NamesDelta);
610 auto NumData =
swap(Header.NumData);
611 auto PaddingBytesBeforeCounters =
swap(Header.PaddingBytesBeforeCounters);
612 auto CountersSize =
swap(Header.NumCounters) * getCounterTypeSize();
613 auto PaddingBytesAfterCounters =
swap(Header.PaddingBytesAfterCounters);
614 auto NumBitmapBytes =
swap(Header.NumBitmapBytes);
615 auto PaddingBytesAfterBitmapBytes =
swap(Header.PaddingBytesAfterBitmapBytes);
616 auto NamesSize =
swap(Header.NamesSize);
617 auto VTableNameSize =
swap(Header.VNamesSize);
618 auto NumVTables =
swap(Header.NumVTables);
619 ValueKindLast =
swap(Header.ValueKindLast);
622 auto PaddingBytesAfterNames = getNumPaddingBytes(NamesSize);
623 auto PaddingBytesAfterVTableNames = getNumPaddingBytes(VTableNameSize);
625 auto VTableSectionSize =
627 auto PaddingBytesAfterVTableProfData = getNumPaddingBytes(VTableSectionSize);
631 ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
633 CountersOffset + CountersSize + PaddingBytesAfterCounters;
635 BitmapOffset + NumBitmapBytes + PaddingBytesAfterBitmapBytes;
637 NamesOffset + NamesSize + PaddingBytesAfterNames;
638 ptrdiff_t VTableNameOffset = VTableProfDataOffset + VTableSectionSize +
639 PaddingBytesAfterVTableProfData;
641 VTableNameOffset + VTableNameSize + PaddingBytesAfterVTableNames;
643 auto *Start =
reinterpret_cast<const char *
>(&Header);
644 if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
648 std::vector<object::BuildID> BinaryIDs;
649 if (
Error E = readBinaryIds(BinaryIDs))
652 BIDFetcher, BinaryIDs)
653 .moveInto(BIDFetcherCorrelator)) {
656 if (
auto Err = BIDFetcherCorrelator->correlateProfileData(0))
663 if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
666 Data = Correlator->getDataPointer();
670 }
else if (BIDFetcherCorrelator) {
672 dyn_cast_or_null<InstrProfCorrelatorImpl<IntPtrT>>(
673 BIDFetcherCorrelator.get());
677 NamesEnd = NamesStart + BIDFetcherCorrelatorImpl->
getNamesSize();
681 DataEnd =
Data + NumData;
684 Start + VTableProfDataOffset);
685 VTableEnd = VTableBegin + NumVTables;
686 NamesStart = Start + NamesOffset;
687 NamesEnd = NamesStart + NamesSize;
688 VNamesStart = Start + VTableNameOffset;
689 VNamesEnd = VNamesStart + VTableNameSize;
692 CountersStart = Start + CountersOffset;
693 CountersEnd = CountersStart + CountersSize;
694 BitmapStart = Start + BitmapOffset;
695 BitmapEnd = BitmapStart + NumBitmapBytes;
696 ValueDataStart =
reinterpret_cast<const uint8_t *
>(Start + ValueDataOffset);
698 std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
699 if (
Error E = createSymtab(*NewSymtab))
702 Symtab = std::move(NewSymtab);
706template <
class IntPtrT>
712template <
class IntPtrT>
718template <
class IntPtrT>
722 if (NumCounters == 0)
726 if (CounterBaseOffset < 0)
729 (
"counter offset " +
Twine(CounterBaseOffset) +
" is negative").str());
731 if (CounterBaseOffset >= CountersEnd - CountersStart)
733 (
"counter offset " +
Twine(CounterBaseOffset) +
734 " is greater than the maximum counter offset " +
735 Twine(CountersEnd - CountersStart - 1))
739 (CountersEnd - (CountersStart + CounterBaseOffset)) /
740 getCounterTypeSize();
741 if (NumCounters > MaxNumCounters)
743 (
"number of counters " +
Twine(NumCounters) +
744 " is greater than the maximum number of counters " +
745 Twine(MaxNumCounters))
749 Record.Counts.reserve(NumCounters);
752 CountersStart + CounterBaseOffset +
I * getCounterTypeSize();
753 if (
I == 0 && hasTemporalProfile()) {
755 if (TimestampValue != 0 &&
756 TimestampValue != std::numeric_limits<uint64_t>::max()) {
757 TemporalProfTimestamps.emplace_back(TimestampValue,
759 TemporalProfTraceStreamSize = 1;
761 if (hasSingleByteCoverage()) {
770 if (hasSingleByteCoverage()) {
772 Record.Counts.push_back(*
Ptr == 0 ? 1 : 0);
775 if (CounterValue > MaxCounterValue && Warn)
776 Warn(make_error<InstrProfError>(
779 Record.Counts.push_back(CounterValue);
786template <
class IntPtrT>
790 Record.BitmapBytes.clear();
791 Record.BitmapBytes.reserve(NumBitmapBytes);
795 if (NumBitmapBytes == 0)
800 if (BitmapOffset < 0)
803 (
"bitmap offset " +
Twine(BitmapOffset) +
" is negative").str());
805 if (BitmapOffset >= BitmapEnd - BitmapStart)
807 (
"bitmap offset " +
Twine(BitmapOffset) +
808 " is greater than the maximum bitmap offset " +
809 Twine(BitmapEnd - BitmapStart - 1))
813 (BitmapEnd - (BitmapStart + BitmapOffset)) /
sizeof(
uint8_t);
814 if (NumBitmapBytes > MaxNumBitmapBytes)
816 (
"number of bitmap bytes " +
Twine(NumBitmapBytes) +
817 " is greater than the maximum number of bitmap bytes " +
818 Twine(MaxNumBitmapBytes))
822 const char *
Ptr = BitmapStart + BitmapOffset +
I;
829template <
class IntPtrT>
833 CurValueDataSize = 0;
837 NumValueKinds += (
Data->NumValueSites[
I] != 0);
843 ValueProfData::getValueProfData(
844 ValueDataStart, (
const unsigned char *)DataBuffer->getBufferEnd(),
845 getDataEndianness());
853 VDataPtrOrErr.
get()->deserializeTo(
Record, Symtab.get());
854 CurValueDataSize = VDataPtrOrErr.
get()->getSize();
858template <
class IntPtrT>
864 if (
Error E = readNextHeader(getNextHeaderPos()))
865 return error(std::move(E));
869 return error(std::move(E));
873 return error(std::move(E));
877 return error(std::move(E));
881 return error(std::move(E));
885 return error(std::move(E));
892template <
class IntPtrT>
894 std::vector<llvm::object::BuildID> &BinaryIds) {
895 BinaryIds.insert(BinaryIds.begin(), this->BinaryIds.begin(),
896 this->BinaryIds.end());
900template <
class IntPtrT>
902 if (!BinaryIds.empty())
923 const unsigned char *&
D,
const unsigned char *
const End) {
925 ValueProfData::getValueProfData(
D,
End, ValueProfDataEndianness);
930 VDataPtrOrErr.
get()->deserializeTo(DataBuffer.back(),
nullptr);
931 D += VDataPtrOrErr.
get()->TotalSize;
938 using namespace support;
945 std::vector<uint64_t> CounterBuffer;
946 std::vector<uint8_t> BitmapByteBuffer;
948 const unsigned char *
End =
D +
N;
953 uint64_t Hash = endian::readNext<uint64_t, llvm::endianness::little>(
D);
961 CountsSize = endian::readNext<uint64_t, llvm::endianness::little>(
D);
967 CounterBuffer.clear();
968 CounterBuffer.reserve(CountsSize);
969 for (
uint64_t J = 0; J < CountsSize; ++J)
970 CounterBuffer.push_back(
971 endian::readNext<uint64_t, llvm::endianness::little>(
D));
978 BitmapBytes = endian::readNext<uint64_t, llvm::endianness::little>(
D);
982 BitmapByteBuffer.clear();
983 BitmapByteBuffer.reserve(BitmapBytes);
984 for (
uint64_t J = 0; J < BitmapBytes; ++J)
985 BitmapByteBuffer.push_back(
static_cast<uint8_t>(
986 endian::readNext<uint64_t, llvm::endianness::little>(
D)));
989 DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer),
990 std::move(BitmapByteBuffer));
1002template <
typename HashTableImpl>
1005 auto Iter = HashTable->find(FuncName);
1006 if (Iter == HashTable->end())
1012 "profile data is empty");
1017template <
typename HashTableImpl>
1023 Data = *RecordIterator;
1027 "profile data is empty");
1032template <
typename HashTableImpl>
1034 const unsigned char *Buckets,
const unsigned char *
const Payload,
1038 HashTable.reset(HashTableImpl::Create(
1039 Buckets, Payload,
Base,
1040 typename HashTableImpl::InfoType(HashType,
Version)));
1041 RecordIterator = HashTable->data_begin();
1044template <
typename HashTableImpl>
1056 : Underlying(Underlying) {}
1060 return Underlying.getRecords(FuncName, Data);
1066template <
typename HashTableImpl>
1071 std::unique_ptr<MemoryBuffer> RemapBuffer,
1073 : RemapBuffer(
std::
move(RemapBuffer)), Underlying(Underlying) {
1082 std::pair<StringRef, StringRef> Parts = {
StringRef(),
Name};
1085 if (Parts.first.starts_with(
"_Z"))
1087 if (Parts.second.empty())
1104 if (
Error E = Remappings.
read(*RemapBuffer))
1108 if (
auto Key = Remappings.
insert(RealName)) {
1112 MappedNames.insert({Key, RealName});
1121 if (
auto Key = Remappings.
lookup(RealName)) {
1122 StringRef Remapped = MappedNames.lookup(Key);
1123 if (!Remapped.
empty()) {
1125 RealName.
end() == FuncName.
end())
1126 FuncName = Remapped;
1131 Error E = Underlying.getRecords(Reconstituted,
Data);
1138 std::move(E), [](std::unique_ptr<InstrProfError> Err) {
1141 :
Error(std::move(Err));
1147 return Underlying.getRecords(FuncName,
Data);
1153 std::unique_ptr<MemoryBuffer> RemapBuffer;
1169 using namespace support;
1173 uint64_t Magic = endian::read<uint64_t, llvm::endianness::little, aligned>(
1179const unsigned char *
1181 const unsigned char *Cur,
bool UseCS) {
1182 using namespace IndexedInstrProf;
1183 using namespace support;
1188 uint64_t NFields = endian::byte_swap<uint64_t, llvm::endianness::little>(
1190 uint64_t NEntries = endian::byte_swap<uint64_t, llvm::endianness::little>(
1194 std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
1199 for (
unsigned I = 0;
I < SummarySize /
sizeof(
uint64_t);
I++)
1200 Dst[
I] = endian::byte_swap<uint64_t, llvm::endianness::little>(Src[
I]);
1203 for (
unsigned I = 0;
I < SummaryData->NumCutoffEntries;
I++) {
1208 std::unique_ptr<llvm::ProfileSummary> &Summary =
1209 UseCS ? this->CS_Summary : this->Summary;
1212 Summary = std::make_unique<ProfileSummary>(
1214 DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
1215 SummaryData->get(Summary::MaxBlockCount),
1216 SummaryData->get(Summary::MaxInternalBlockCount),
1217 SummaryData->get(Summary::MaxFunctionCount),
1218 SummaryData->get(Summary::TotalNumBlocks),
1219 SummaryData->get(Summary::TotalNumFunctions));
1220 return Cur + SummarySize;
1228 Summary = Builder.getSummary();
1233Error IndexedMemProfReader::deserializeV2(
const unsigned char *Start,
1234 const unsigned char *
Ptr) {
1237 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1240 const uint64_t FramePayloadOffset =
1241 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1244 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1248 uint64_t CallStackPayloadOffset = 0;
1252 CallStackPayloadOffset =
1253 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1254 CallStackTableOffset =
1255 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1261 return SchemaOr.takeError();
1262 Schema = SchemaOr.get();
1266 Start + RecordTableOffset,
1272 Start + FrameTableOffset,
1273 Start + FramePayloadOffset,
1278 Start + CallStackTableOffset,
1279 Start + CallStackPayloadOffset,
1285Error IndexedMemProfReader::deserializeV3(
const unsigned char *Start,
1286 const unsigned char *
Ptr) {
1289 const uint64_t CallStackPayloadOffset =
1290 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1292 const uint64_t RecordPayloadOffset =
1293 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1296 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1301 return SchemaOr.takeError();
1302 Schema = SchemaOr.get();
1305 CallStackBase = Start + CallStackPayloadOffset;
1310 RadixTreeSize = (RecordPayloadOffset - CallStackPayloadOffset) /
1315 Start + RecordTableOffset,
1316 Start + RecordPayloadOffset,
1324 const unsigned char *
Ptr = Start + MemProfOffset;
1328 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1334 return make_error<InstrProfError>(
1336 formatv(
"MemProf version {} not supported; "
1337 "requires version between {} and {}, inclusive",
1344 if (
Error E = deserializeV2(Start,
Ptr))
1348 if (
Error E = deserializeV3(Start,
Ptr))
1357 using namespace support;
1359 const unsigned char *Start =
1360 (
const unsigned char *)DataBuffer->getBufferStart();
1361 const unsigned char *Cur = Start;
1362 if ((
const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
1367 return HeaderOr.takeError();
1370 Cur += Header->size();
1374 if (Header->Version & VARIANT_MASK_CSIR_PROF)
1384 auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1385 Start + Header->HashOffset, Cur, Start, HashType, Header->Version);
1389 if (Header->getIndexedProfileVersion() >= 8 &&
1390 Header->Version & VARIANT_MASK_MEMPROF) {
1397 if (Header->getIndexedProfileVersion() >= 9) {
1398 const unsigned char *
Ptr = Start + Header->BinaryIdOffset;
1401 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1402 if (BinaryIdsSize %
sizeof(
uint64_t))
1406 if (
Ptr > (
const unsigned char *)DataBuffer->getBufferEnd())
1408 "corrupted binary ids");
1411 if (Header->getIndexedProfileVersion() >= 12) {
1412 const unsigned char *
Ptr = Start + Header->VTableNamesOffset;
1414 uint64_t CompressedVTableNamesLen =
1415 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1419 const char *VTableNamePtr = (
const char *)
Ptr;
1420 if (VTableNamePtr > (
const char *)DataBuffer->getBufferEnd())
1423 VTableName =
StringRef(VTableNamePtr, CompressedVTableNamesLen);
1426 if (Header->getIndexedProfileVersion() >= 10 &&
1427 Header->Version & VARIANT_MASK_TEMPORAL_PROF) {
1428 const unsigned char *
Ptr = Start + Header->TemporalProfTracesOffset;
1429 const auto *PtrEnd = (
const unsigned char *)DataBuffer->getBufferEnd();
1434 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1436 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1437 for (
unsigned i = 0; i < NumTraces; i++) {
1443 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1445 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1447 if (
Ptr + NumFunctions *
sizeof(
uint64_t) > PtrEnd)
1449 for (
unsigned j = 0; j < NumFunctions; j++) {
1451 support::endian::readNext<uint64_t, llvm::endianness::little>(
Ptr);
1452 Trace.FunctionNameRefs.push_back(NameRef);
1459 if (RemappingBuffer) {
1461 std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1462 std::move(RemappingBuffer), *IndexPtr);
1463 if (
Error E = Remapper->populateRemappings())
1466 Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1468 Index = std::move(IndexPtr);
1477 auto NewSymtab = std::make_unique<InstrProfSymtab>();
1479 if (
Error E = NewSymtab->initVTableNamesFromCompressedStrings(VTableName)) {
1485 if (
Error E = Index->populateSymtab(*NewSymtab)) {
1490 Symtab = std::move(NewSymtab);
1499 auto Err = Remapper->getRecords(FuncName,
Data);
1506 return make_error<InstrProfError>(IE);
1507 if (
auto Err = Remapper->getRecords(DeprecatedFuncName,
Data))
1512 return std::move(Err2);
1518 bool CSBitMatch =
false;
1521 for (
uint64_t CountValue : Counts) {
1525 if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1526 return std::numeric_limits<uint64_t>::max();
1527 ValueSum += CountValue;
1534 if (
I.Hash == FuncHash)
1535 return std::move(
I);
1539 if (MismatchedFuncSum ==
nullptr)
1541 FuncSum = std::max(FuncSum, getFuncSum(
I.Counts));
1545 if (MismatchedFuncSum !=
nullptr)
1546 *MismatchedFuncSum = FuncSum;
1560 MemProfCallStackTable, FrameIdConv);
1566 return make_error<InstrProfError>(
1568 "memprof call stack not found for call stack id " +
1575 "memprof frame not found for frame id " +
1584 const unsigned char *FrameBase,
1585 const unsigned char *CallStackBase) {
1595 if (MemProfRecordTable ==
nullptr)
1597 "no memprof data available in profile");
1598 auto Iter = MemProfRecordTable->find(FuncNameHash);
1599 if (Iter == MemProfRecordTable->end())
1600 return make_error<InstrProfError>(
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);
1612 assert(!MemProfFrameTable &&
"MemProfFrameTable must not be available");
1613 assert(!MemProfCallStackTable &&
1614 "MemProfCallStackTable must not be available");
1615 assert(FrameBase &&
"FrameBase must be available");
1616 assert(CallStackBase &&
"CallStackBase must be available");
1620 return make_error<InstrProfError>(
1622 formatv(
"MemProf version {} not supported; "
1623 "requires version between {} and {}, inclusive",
1630 assert(MemProfRecordTable);
1645 MemProfRecordTable->data()) {
1647 IndexedRecord.AllocSites)
1652 for (
unsigned CS : Worklist.
set_bits())
1659 for (
auto &[CallerGUID, CallList] : Pairs) {
1661 CallList.erase(
llvm::unique(CallList), CallList.end());
1670 MemProfRecordTable->getNumEntries());
1671 for (
uint64_t Key : MemProfRecordTable->keys()) {
1680 return AllMemProfData;
1685 std::vector<uint64_t> &Counts) {
1688 return error(std::move(E));
1690 Counts =
Record.get().Counts;
1699 return error(std::move(E));
1701 const auto &BitmapBytes =
Record.get().BitmapBytes;
1702 size_t I = 0, E = BitmapBytes.size();
1703 Bitmap.
resize(E * CHAR_BIT);
1706 using XTy =
decltype(
X);
1708 size_t N = std::min(E -
I,
sizeof(W));
1709 std::memset(W, 0,
sizeof(W));
1710 std::memcpy(W, &BitmapBytes[
I],
N);
1726 return error(std::move(E));
1729 if (RecordIndex >=
Data.size()) {
1730 Index->advanceToNextKey();
1737 std::vector<llvm::object::BuildID> &BinaryIds) {
1743 std::vector<llvm::object::BuildID> BinaryIds;
1752 for (
const auto &Func : *
this) {
1755 if (FuncIsCS != IsCS)
1758 Func.accumulateCounts(Sum);
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Provides ErrorOr<T> smart pointer.
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
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)
static InstrProfKind getProfileKindFromVersion(uint64_t Version)
static Expected< memprof::MemProfRecord > getMemProfRecordV2(const memprof::IndexedMemProfRecord &IndexedRecord, MemProfFrameHashTable &MemProfFrameTable, MemProfCallStackHashTable &MemProfCallStackTable)
static Expected< memprof::MemProfRecord > getMemProfRecordV3(const memprof::IndexedMemProfRecord &IndexedRecord, const unsigned char *FrameBase, const unsigned char *CallStackBase)
static void printBinaryIdsInternal(raw_ostream &OS, ArrayRef< llvm::object::BuildID > BinaryIds)
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),...
size_t size() const
size - Get the array size.
void resize(unsigned N, bool t=false)
resize - Grow or shrink 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.
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 readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
Error deserialize(const unsigned char *Start, uint64_t MemProfOffset)
memprof::AllMemProfData getAllMemProfData() const
Expected< memprof::MemProfRecord > getMemProfRecord(const uint64_t FuncNameHash) const
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.
std::optional< size_t > getDataSize() const
Return the number of ProfileData elements.
static 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.
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.
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.
static 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.
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
Provides lookup and iteration over an on disk hash table.
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).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
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.
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
Expected< MemProfSchema > readMemProfSchema(const unsigned char *&Buffer)
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
This is an optimization pass for GlobalISel generic memory operations.
RawInstrProfReader< uint32_t > RawInstrProfReader32
static Expected< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS)
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.
auto unique(Range &&R, Predicate P)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
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
@ counter_value_too_large
@ unexpected_correlation_info
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...
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.
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.
@ LoopEntriesInstrumentation
@ 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.
std::vector< GUIDMemProfRecordPair > HeapProfileRecords
std::optional< CallStackId > LastUnmappedId
std::optional< FrameId > LastUnmappedId
MemProfRecord toMemProfRecord(llvm::function_ref< std::vector< Frame >(const CallStackId)> Callback) const