diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
| commit | 145449b1e420787bb99721a429341fa6be3adfb6 (patch) | |
| tree | 1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/ProfileData/InstrProfReader.cpp | |
| parent | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff) | |
Diffstat (limited to 'llvm/lib/ProfileData/InstrProfReader.cpp')
| -rw-r--r-- | llvm/lib/ProfileData/InstrProfReader.cpp | 146 |
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) { |
