aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-23 17:38:08 +0000
commit320d4fb58b6b1c6a0c7ffeab3d4672d1479d5e17 (patch)
tree4b5e279a6f091bb6bdc639752cf4139dfd7053a4 /contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp
parent814cfa6ad43c73de9b8030f241f516dad3f669ef (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp190
1 files changed, 134 insertions, 56 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp
index 23804ce604c4..d0714c9b4665 100644
--- a/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -75,6 +75,91 @@ static Error initializeReader(InstrProfReader &Reader) {
return Reader.readHeader();
}
+/// Read a list of binary ids from a profile that consist of
+/// a. uint64_t binary id length
+/// b. uint8_t binary id data
+/// c. uint8_t padding (if necessary)
+/// This function is shared between raw and indexed profiles.
+/// Raw profiles are in host-endian format, and indexed profiles are in
+/// little-endian format. So, this function takes an argument indicating the
+/// associated endian format to read the binary ids correctly.
+static Error
+readBinaryIdsInternal(const MemoryBuffer &DataBuffer,
+ const uint64_t BinaryIdsSize,
+ const uint8_t *BinaryIdsStart,
+ std::vector<llvm::object::BuildID> &BinaryIds,
+ const llvm::support::endianness Endian) {
+ using namespace support;
+
+ if (BinaryIdsSize == 0)
+ return Error::success();
+
+ const uint8_t *BI = BinaryIdsStart;
+ const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
+ const uint8_t *End =
+ reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
+
+ while (BI < BIEnd) {
+ size_t Remaining = BIEnd - BI;
+ // There should be enough left to read the binary id length.
+ if (Remaining < sizeof(uint64_t))
+ return make_error<InstrProfError>(
+ instrprof_error::malformed,
+ "not enough data to read binary id length");
+
+ uint64_t BILen = 0;
+ if (Endian == little)
+ BILen = endian::readNext<uint64_t, little, unaligned>(BI);
+ else
+ BILen = endian::readNext<uint64_t, big, unaligned>(BI);
+
+ if (BILen == 0)
+ return make_error<InstrProfError>(instrprof_error::malformed,
+ "binary id length is 0");
+
+ Remaining = BIEnd - BI;
+ // There should be enough left to read the binary id data.
+ if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
+ return make_error<InstrProfError>(
+ instrprof_error::malformed, "not enough data to read binary id data");
+
+ // Add binary id to the binary ids list.
+ BinaryIds.push_back(object::BuildID(BI, BI + BILen));
+
+ // Increment by binary id data length, which aligned to the size of uint64.
+ BI += alignToPowerOf2(BILen, sizeof(uint64_t));
+ if (BI > End)
+ return make_error<InstrProfError>(
+ instrprof_error::malformed,
+ "binary id section is greater than buffer size");
+ }
+
+ return Error::success();
+}
+
+static Error printBinaryIdsInternal(raw_ostream &OS,
+ const MemoryBuffer &DataBuffer,
+ uint64_t BinaryIdsSize,
+ const uint8_t *BinaryIdsStart,
+ llvm::support::endianness Endian) {
+ if (BinaryIdsSize == 0)
+ return Error::success();
+
+ std::vector<llvm::object::BuildID> BinaryIds;
+ if (Error E = readBinaryIdsInternal(DataBuffer, BinaryIdsSize, BinaryIdsStart,
+ BinaryIds, Endian))
+ return E;
+
+ OS << "Binary IDs: \n";
+ for (auto BI : BinaryIds) {
+ for (uint64_t I = 0; I < BI.size(); I++)
+ OS << format("%02x", BI[I]);
+ OS << "\n";
+ }
+
+ return Error::success();
+}
+
Expected<std::unique_ptr<InstrProfReader>>
InstrProfReader::create(const Twine &Path,
const InstrProfCorrelator *Correlator) {
@@ -545,7 +630,9 @@ Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
template <class IntPtrT>
Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
- if (atEnd())
+ // Keep reading profiles that consist of only headers and no profile data and
+ // counters.
+ while (atEnd())
// At this point, ValueDataStart field points to the next header.
if (Error E = readNextHeader(getNextHeaderPos()))
return error(std::move(E));
@@ -571,54 +658,17 @@ Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record)
return success();
}
-static size_t RoundUp(size_t size, size_t align) {
- return (size + align - 1) & ~(align - 1);
+template <class IntPtrT>
+Error RawInstrProfReader<IntPtrT>::readBinaryIds(
+ std::vector<llvm::object::BuildID> &BinaryIds) {
+ return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
+ BinaryIds, getDataEndianness());
}
template <class IntPtrT>
Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) {
- if (BinaryIdsSize == 0)
- return success();
-
- OS << "Binary IDs: \n";
- const uint8_t *BI = BinaryIdsStart;
- const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
- while (BI < BIEnd) {
- size_t Remaining = BIEnd - BI;
-
- // There should be enough left to read the binary ID size field.
- if (Remaining < sizeof(uint64_t))
- return make_error<InstrProfError>(
- instrprof_error::malformed,
- "not enough data to read binary id length");
-
- uint64_t BinaryIdLen = swap(*reinterpret_cast<const uint64_t *>(BI));
-
- // There should be enough left to read the binary ID size field, and the
- // binary ID.
- if (Remaining < sizeof(BinaryIdLen) + BinaryIdLen)
- return make_error<InstrProfError>(
- instrprof_error::malformed, "not enough data to read binary id data");
-
- // Increment by binary id length data type size.
- BI += sizeof(BinaryIdLen);
- if (BI > (const uint8_t *)DataBuffer->getBufferEnd())
- return make_error<InstrProfError>(
- instrprof_error::malformed,
- "binary id that is read is bigger than buffer size");
-
- for (uint64_t I = 0; I < BinaryIdLen; I++)
- OS << format("%02x", BI[I]);
- OS << "\n";
-
- // Increment by binary id data length, rounded to the next 8 bytes. This
- // accounts for the zero-padding after each build ID.
- BI += RoundUp(BinaryIdLen, sizeof(uint64_t));
- if (BI > (const uint8_t *)DataBuffer->getBufferEnd())
- return make_error<InstrProfError>(instrprof_error::malformed);
- }
-
- return success();
+ return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
+ getDataEndianness());
}
namespace llvm {
@@ -946,9 +996,9 @@ Error IndexedInstrProfReader::readHeader() {
Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
/* UseCS */ false);
if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
- Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
- /* UseCS */ true);
-
+ Cur =
+ readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
+ /* UseCS */ true);
// Read the hash type and start offset.
IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
endian::byte_swap<uint64_t, little>(Header->HashType));
@@ -961,8 +1011,8 @@ Error IndexedInstrProfReader::readHeader() {
auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
Start + HashOffset, Cur, Start, HashType, Header->formatVersion());
- // The MemProfOffset field in the header is only valid when the format version
- // is higher than 8 (when it was introduced).
+ // The MemProfOffset field in the header is only valid when the format
+ // version is higher than 8 (when it was introduced).
if (GET_VERSION(Header->formatVersion()) >= 8 &&
Header->formatVersion() & VARIANT_MASK_MEMPROF) {
uint64_t MemProfOffset =
@@ -972,7 +1022,8 @@ Error IndexedInstrProfReader::readHeader() {
// The value returned from RecordTableGenerator.Emit.
const uint64_t RecordTableOffset =
support::endian::readNext<uint64_t, little, unaligned>(Ptr);
- // The offset in the stream right before invoking FrameTableGenerator.Emit.
+ // The offset in the stream right before invoking
+ // FrameTableGenerator.Emit.
const uint64_t FramePayloadOffset =
support::endian::readNext<uint64_t, little, unaligned>(Ptr);
// The value returned from FrameTableGenerator.Emit.
@@ -998,11 +1049,28 @@ Error IndexedInstrProfReader::readHeader() {
/*Base=*/Start, memprof::FrameLookupTrait()));
}
+ // BinaryIdOffset field in the header is only valid when the format version
+ // is higher than 9 (when it was introduced).
+ if (GET_VERSION(Header->formatVersion()) >= 9) {
+ uint64_t BinaryIdOffset =
+ endian::byte_swap<uint64_t, little>(Header->BinaryIdOffset);
+ const unsigned char *Ptr = Start + BinaryIdOffset;
+ // Read binary ids size.
+ BinaryIdsSize = support::endian::readNext<uint64_t, little, unaligned>(Ptr);
+ if (BinaryIdsSize % sizeof(uint64_t))
+ return error(instrprof_error::bad_header);
+ // Set the binary ids start.
+ BinaryIdsStart = Ptr;
+ if (BinaryIdsStart > (const unsigned char *)DataBuffer->getBufferEnd())
+ return make_error<InstrProfError>(instrprof_error::malformed,
+ "corrupted binary ids");
+ }
+
// Load the remapping table now if requested.
if (RemappingBuffer) {
- Remapper = std::make_unique<
- InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
- std::move(RemappingBuffer), *IndexPtr);
+ Remapper =
+ std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
+ std::move(RemappingBuffer), *IndexPtr);
if (Error E = Remapper->populateRemappings())
return E;
} else {
@@ -1040,8 +1108,7 @@ Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord(
bool CSBitMatch = false;
auto getFuncSum = [](const std::vector<uint64_t> &Counts) {
uint64_t ValueSum = 0;
- for (unsigned I = 0, S = Counts.size(); I < S; I++) {
- uint64_t CountValue = Counts[I];
+ for (uint64_t CountValue : Counts) {
if (CountValue == (uint64_t)-1)
continue;
// Handle overflow -- if that happens, return max.
@@ -1135,6 +1202,17 @@ Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
return success();
}
+Error IndexedInstrProfReader::readBinaryIds(
+ std::vector<llvm::object::BuildID> &BinaryIds) {
+ return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
+ BinaryIds, llvm::support::little);
+}
+
+Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) {
+ return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
+ llvm::support::little);
+}
+
void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
uint64_t NumFuncs = 0;
for (const auto &Func : *this) {