summaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/InstrProfReader.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/ProfileData/InstrProfReader.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
Diffstat (limited to 'llvm/lib/ProfileData/InstrProfReader.cpp')
-rw-r--r--llvm/lib/ProfileData/InstrProfReader.cpp146
1 files changed, 103 insertions, 43 deletions
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 138b1532d778..ee8989979a26 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -14,11 +14,11 @@
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/MemProf.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -27,7 +27,6 @@
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/SymbolRemappingReader.h"
#include <algorithm>
-#include <cctype>
#include <cstddef>
#include <cstdint>
#include <limits>
@@ -43,13 +42,13 @@ using namespace llvm;
static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
InstrProfKind ProfileKind = InstrProfKind::Unknown;
if (Version & VARIANT_MASK_IR_PROF) {
- ProfileKind |= InstrProfKind::IR;
+ ProfileKind |= InstrProfKind::IRInstrumentation;
}
if (Version & VARIANT_MASK_CSIR_PROF) {
- ProfileKind |= InstrProfKind::CS;
+ ProfileKind |= InstrProfKind::ContextSensitive;
}
if (Version & VARIANT_MASK_INSTR_ENTRY) {
- ProfileKind |= InstrProfKind::BB;
+ ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
}
if (Version & VARIANT_MASK_BYTE_COVERAGE) {
ProfileKind |= InstrProfKind::SingleByteCoverage;
@@ -57,6 +56,9 @@ static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
ProfileKind |= InstrProfKind::FunctionEntryOnly;
}
+ if (Version & VARIANT_MASK_MEMPROF) {
+ ProfileKind |= InstrProfKind::MemProf;
+ }
return ProfileKind;
}
@@ -153,14 +155,6 @@ IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
return std::move(Result);
}
-void InstrProfIterator::Increment() {
- if (auto E = Reader->readNextRecord(Record)) {
- // Handle errors in the reader.
- InstrProfError::take(std::move(E));
- *this = InstrProfIterator();
- }
-}
-
bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
// Verify that this really looks like plain ASCII text by checking a
// 'reasonable' number of characters (up to profile magic size).
@@ -180,16 +174,16 @@ Error TextInstrProfReader::readHeader() {
while (Line->startswith(":")) {
StringRef Str = Line->substr(1);
if (Str.equals_insensitive("ir"))
- ProfileKind |= InstrProfKind::IR;
+ ProfileKind |= InstrProfKind::IRInstrumentation;
else if (Str.equals_insensitive("fe"))
- ProfileKind |= InstrProfKind::FE;
+ ProfileKind |= InstrProfKind::FrontendInstrumentation;
else if (Str.equals_insensitive("csir")) {
- ProfileKind |= InstrProfKind::IR;
- ProfileKind |= InstrProfKind::CS;
+ ProfileKind |= InstrProfKind::IRInstrumentation;
+ ProfileKind |= InstrProfKind::ContextSensitive;
} else if (Str.equals_insensitive("entry_first"))
- ProfileKind |= InstrProfKind::BB;
+ ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
else if (Str.equals_insensitive("not_entry_first"))
- ProfileKind &= ~InstrProfKind::BB;
+ ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation;
else
return error(instrprof_error::bad_header);
++Line;
@@ -454,7 +448,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
return error(instrprof_error::bad_header);
std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
- if (Error E = createSymtab(*NewSymtab.get()))
+ if (Error E = createSymtab(*NewSymtab))
return E;
Symtab = std::move(NewSymtab);
@@ -942,24 +936,17 @@ Error IndexedInstrProfReader::readHeader() {
if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
return error(instrprof_error::truncated);
- auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
- Cur += sizeof(IndexedInstrProf::Header);
-
- // Check the magic number.
- uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic);
- if (Magic != IndexedInstrProf::Magic)
- return error(instrprof_error::bad_magic);
+ auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
+ if (!HeaderOr)
+ return HeaderOr.takeError();
- // Read the version.
- uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version);
- if (GET_VERSION(FormatVersion) >
- IndexedInstrProf::ProfVersion::CurrentVersion)
- return error(instrprof_error::unsupported_version);
+ const IndexedInstrProf::Header *Header = &HeaderOr.get();
+ Cur += Header->size();
- Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
+ Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
/* UseCS */ false);
- if (FormatVersion & VARIANT_MASK_CSIR_PROF)
- Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
+ if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
+ Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
/* UseCS */ true);
// Read the hash type and start offset.
@@ -970,10 +957,46 @@ Error IndexedInstrProfReader::readHeader() {
uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
- // The rest of the file is an on disk hash table.
- auto IndexPtr =
- std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
- Start + HashOffset, Cur, Start, HashType, FormatVersion);
+ // The hash table with profile counts comes next.
+ 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).
+ if (GET_VERSION(Header->formatVersion()) >= 8 &&
+ Header->formatVersion() & VARIANT_MASK_MEMPROF) {
+ uint64_t MemProfOffset =
+ endian::byte_swap<uint64_t, little>(Header->MemProfOffset);
+
+ const unsigned char *Ptr = Start + MemProfOffset;
+ // 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.
+ const uint64_t FramePayloadOffset =
+ support::endian::readNext<uint64_t, little, unaligned>(Ptr);
+ // The value returned from FrameTableGenerator.Emit.
+ const uint64_t FrameTableOffset =
+ support::endian::readNext<uint64_t, little, unaligned>(Ptr);
+
+ // Read the schema.
+ auto SchemaOr = memprof::readMemProfSchema(Ptr);
+ if (!SchemaOr)
+ return SchemaOr.takeError();
+ Schema = SchemaOr.get();
+
+ // Now initialize the table reader with a pointer into data buffer.
+ MemProfRecordTable.reset(MemProfRecordHashTable::Create(
+ /*Buckets=*/Start + RecordTableOffset,
+ /*Payload=*/Ptr,
+ /*Base=*/Start, memprof::RecordLookupTrait(Schema)));
+
+ // Initialize the frame table reader with the payload and bucket offsets.
+ MemProfFrameTable.reset(MemProfFrameHashTable::Create(
+ /*Buckets=*/Start + FrameTableOffset,
+ /*Payload=*/Start + FramePayloadOffset,
+ /*Base=*/Start, memprof::FrameLookupTrait()));
+ }
// Load the remapping table now if requested.
if (RemappingBuffer) {
@@ -991,16 +1014,16 @@ Error IndexedInstrProfReader::readHeader() {
}
InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
- if (Symtab.get())
- return *Symtab.get();
+ if (Symtab)
+ return *Symtab;
std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
- if (Error E = Index->populateSymtab(*NewSymtab.get())) {
+ if (Error E = Index->populateSymtab(*NewSymtab)) {
consumeError(error(InstrProfError::take(std::move(E))));
}
Symtab = std::move(NewSymtab);
- return *Symtab.get();
+ return *Symtab;
}
Expected<InstrProfRecord>
@@ -1019,6 +1042,43 @@ IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName,
return error(instrprof_error::hash_mismatch);
}
+Expected<memprof::MemProfRecord>
+IndexedInstrProfReader::getMemProfRecord(const uint64_t FuncNameHash) {
+ // TODO: Add memprof specific errors.
+ if (MemProfRecordTable == nullptr)
+ return make_error<InstrProfError>(instrprof_error::invalid_prof,
+ "no memprof data available in profile");
+ auto Iter = MemProfRecordTable->find(FuncNameHash);
+ if (Iter == MemProfRecordTable->end())
+ return make_error<InstrProfError>(
+ instrprof_error::unknown_function,
+ "memprof record not found for function hash " + Twine(FuncNameHash));
+
+ // Setup a callback to convert from frame ids to frame using the on-disk
+ // FrameData hash table.
+ memprof::FrameId LastUnmappedFrameId = 0;
+ bool HasFrameMappingError = false;
+ auto IdToFrameCallback = [&](const memprof::FrameId Id) {
+ auto FrIter = MemProfFrameTable->find(Id);
+ if (FrIter == MemProfFrameTable->end()) {
+ LastUnmappedFrameId = Id;
+ HasFrameMappingError = true;
+ return memprof::Frame(0, 0, 0, false);
+ }
+ return *FrIter;
+ };
+
+ memprof::MemProfRecord Record(*Iter, IdToFrameCallback);
+
+ // Check that all frame ids were successfully converted to frames.
+ if (HasFrameMappingError) {
+ return make_error<InstrProfError>(instrprof_error::hash_mismatch,
+ "memprof frame not found for frame id " +
+ Twine(LastUnmappedFrameId));
+ }
+ return Record;
+}
+
Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
uint64_t FuncHash,
std::vector<uint64_t> &Counts) {