Skip to content

[nfc][InstrProf]Remove 'offsetOf' when parsing indexed profiles #93346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 30, 2024
Merged
94 changes: 35 additions & 59 deletions llvm/lib/ProfileData/InstrProf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1627,66 +1627,43 @@ void OverlapStats::dump(raw_fd_ostream &OS) const {
}

namespace IndexedInstrProf {
// A C++14 compatible version of the offsetof macro.
template <typename T1, typename T2>
inline size_t constexpr offsetOf(T1 T2::*Member) {
constexpr T2 Object{};
return size_t(&(Object.*Member)) - size_t(&Object);
}

// Read a uint64_t from the specified buffer offset, and swap the bytes in
// native endianness if necessary.
static inline uint64_t read(const unsigned char *Buffer, size_t Offset) {
using namespace ::support;
return endian::read<uint64_t, llvm::endianness::little, unaligned>(Buffer +
Offset);
}

Expected<Header> Header::readFromBuffer(const unsigned char *Buffer) {
using namespace support;
static_assert(std::is_standard_layout_v<Header>,
"The header should be standard layout type since we use offset "
"of fields to read.");
"Use standard layout for Header for simplicity");
Header H;

H.Magic = read(Buffer, offsetOf(&Header::Magic));
H.Magic = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
// Check the magic number.
if (H.Magic != IndexedInstrProf::Magic)
return make_error<InstrProfError>(instrprof_error::bad_magic);

// Read the version.
H.Version = read(Buffer, offsetOf(&Header::Version));
H.Version = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
if (H.getIndexedProfileVersion() >
IndexedInstrProf::ProfVersion::CurrentVersion)
return make_error<InstrProfError>(instrprof_error::unsupported_version);

switch (H.getIndexedProfileVersion()) {
// When a new field is added in the header add a case statement here to
// populate it.
static_assert(
IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
"Please update the reading code below if a new field has been added, "
"if not add a case statement to fall through to the latest version.");
case 12ull:
H.VTableNamesOffset = read(Buffer, offsetOf(&Header::VTableNamesOffset));
[[fallthrough]];
case 11ull:
[[fallthrough]];
case 10ull:
static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
"Please update the reader as needed when a new field is added "
"or when indexed profile version gets bumped.");

Buffer += sizeof(uint64_t); // Skip Header.Unused field.
H.HashType = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
H.HashOffset = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
if (H.getIndexedProfileVersion() >= 8)
H.MemProfOffset =
endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
if (H.getIndexedProfileVersion() >= 9)
H.BinaryIdOffset =
endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
// Version 11 is handled by this condition.
if (H.getIndexedProfileVersion() >= 10)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So version 11 is also handled in this condition right? Maybe add a comment to document.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

H.TemporalProfTracesOffset =
read(Buffer, offsetOf(&Header::TemporalProfTracesOffset));
[[fallthrough]];
case 9ull:
H.BinaryIdOffset = read(Buffer, offsetOf(&Header::BinaryIdOffset));
[[fallthrough]];
case 8ull:
H.MemProfOffset = read(Buffer, offsetOf(&Header::MemProfOffset));
[[fallthrough]];
default: // Version7 (when the backwards compatible header was introduced).
H.HashType = read(Buffer, offsetOf(&Header::HashType));
H.HashOffset = read(Buffer, offsetOf(&Header::HashOffset));
}

endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
if (H.getIndexedProfileVersion() >= 12)
H.VTableNamesOffset =
endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
return H;
}

Expand All @@ -1696,27 +1673,26 @@ uint64_t Header::getIndexedProfileVersion() const {

size_t Header::size() const {
switch (getIndexedProfileVersion()) {
// When a new field is added to the header add a case statement here to
// compute the size as offset of the new field + size of the new field. This
// relies on the field being added to the end of the list.
static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
"Please update the size computation below if a new field has "
"been added to the header, if not add a case statement to "
"fall through to the latest version.");
// To retain backward compatibility, new fields must be appended to the end
// of the header, and byte offset of existing fields shouldn't change when
// indexed profile version gets incremented.
static_assert(
IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
"Please update the size computation below if a new field has "
"been added to the header; for a version bump without new "
"fields, add a case statement to fall through to the latest version.");
case 12ull:
return offsetOf(&Header::VTableNamesOffset) +
sizeof(Header::VTableNamesOffset);
return 72;
case 11ull:
[[fallthrough]];
case 10ull:
return offsetOf(&Header::TemporalProfTracesOffset) +
sizeof(Header::TemporalProfTracesOffset);
return 64;
case 9ull:
return offsetOf(&Header::BinaryIdOffset) + sizeof(Header::BinaryIdOffset);
return 56;
case 8ull:
return offsetOf(&Header::MemProfOffset) + sizeof(Header::MemProfOffset);
return 48;
default: // Version7 (when the backwards compatible header was introduced).
return offsetOf(&Header::HashOffset) + sizeof(Header::HashOffset);
return 40;
}
}

Expand Down
Loading