Skip to content

Commit

Permalink
[SampleFDO] Add ExtBinary format to support extension of binary profile.
Browse files Browse the repository at this point in the history
This is a patch split from https://reviews.llvm.org/D66374. It tries to add
a new format of profile called ExtBinary. The format adds a section header
table to the profile and organize the profile in sections, so the future
extension like adding a new section or extending an existing section will be
easier while keeping backward compatiblity feasible.

Differential Revision: https://reviews.llvm.org/D66513

llvm-svn: 369798
  • Loading branch information
wmi-11 committed Aug 23, 2019
1 parent b4051e5 commit be90732
Show file tree
Hide file tree
Showing 10 changed files with 441 additions and 66 deletions.
22 changes: 22 additions & 0 deletions llvm/include/llvm/ProfileData/SampleProf.h
Expand Up @@ -84,6 +84,7 @@ enum SampleProfileFormat {
SPF_Text = 0x1,
SPF_Compact_Binary = 0x2,
SPF_GCC = 0x3,
SPF_Ext_Binary = 0x4,
SPF_Binary = 0xff
};

Expand All @@ -106,6 +107,27 @@ static inline StringRef getRepInFormat(StringRef Name,

static inline uint64_t SPVersion() { return 103; }

// Section Type used by SampleProfileExtBinaryBaseReader and
// SampleProfileExtBinaryBaseWriter. Never change the existing
// value of enum. Only append new ones.
enum SecType {
SecInValid = 0,
SecProfSummary = 1,
SecNameTable = 2,
// marker for the first type of profile.
SecFuncProfileFirst = 32,
SecLBRProfile = SecFuncProfileFirst
};

// Entry type of section header table used by SampleProfileExtBinaryBaseReader
// and SampleProfileExtBinaryBaseWriter.
struct SecHdrTableEntry {
SecType Type;
uint64_t Flag;
uint64_t Offset;
uint64_t Size;
};

/// Represents the relative location of an instruction.
///
/// Instruction locations are specified by the line offset from the
Expand Down
79 changes: 65 additions & 14 deletions llvm/include/llvm/ProfileData/SampleProfReader.h
Expand Up @@ -416,38 +416,89 @@ class SampleProfileReaderBinary : public SampleProfileReader {
/// Read the contents of the given profile instance.
std::error_code readProfile(FunctionSamples &FProfile);

/// Read the contents of Magic number and Version number.
std::error_code readMagicIdent();

/// Read profile summary.
std::error_code readSummary();

/// Read the whole name table.
virtual std::error_code readNameTable();

/// Points to the current location in the buffer.
const uint8_t *Data = nullptr;

/// Points to the end of the buffer.
const uint8_t *End = nullptr;

/// Function name table.
std::vector<StringRef> NameTable;

/// Read a string indirectly via the name table.
virtual ErrorOr<StringRef> readStringFromTable();

private:
std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
};

/// Read profile summary.
std::error_code readSummary();
class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
private:
virtual std::error_code verifySPMagic(uint64_t Magic) override;

/// Read the whole name table.
virtual std::error_code readNameTable() = 0;
public:
SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
SampleProfileFormat Format = SPF_Binary)
: SampleProfileReaderBinary(std::move(B), C, Format) {}

/// Read a string indirectly via the name table.
virtual ErrorOr<StringRef> readStringFromTable() = 0;
/// \brief Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
};

class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
/// SampleProfileReaderExtBinaryBase/SampleProfileWriterExtBinaryBase defines
/// the basic structure of the extensible binary format.
/// The format is organized in sections except the magic and version number
/// at the beginning. There is a section table before all the sections, and
/// each entry in the table describes the entry type, start, size and
/// attributes. The format in each section is defined by the section itself.
///
/// It is easy to add a new section while maintaining the backward
/// compatibility of the profile. Nothing extra needs to be done. If we want
/// to extend an existing section, like add cache misses information in
/// addition to the sample count in the profile body, we can add a new section
/// with the extension and retire the existing section, and we could choose
/// to keep the parser of the old section if we want the reader to be able
/// to read both new and old format profile.
///
/// SampleProfileReaderExtBinary/SampleProfileWriterExtBinary define the
/// commonly used sections of a profile in extensible binary format. It is
/// possible to define other types of profile inherited from
/// SampleProfileReaderExtBinaryBase/SampleProfileWriterExtBinaryBase.
class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
protected:
std::vector<SecHdrTableEntry> SecHdrTable;
std::error_code readSecHdrTableEntry();
std::error_code readSecHdrTable();
virtual std::error_code readHeader() override;
virtual std::error_code verifySPMagic(uint64_t Magic) = 0;

public:
SampleProfileReaderExtBinaryBase(std::unique_ptr<MemoryBuffer> B,
LLVMContext &C, SampleProfileFormat Format)
: SampleProfileReaderBinary(std::move(B), C, Format) {}

/// Read sample profiles in extensible format from the associated file.
std::error_code read() override;
};

class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase {
private:
/// Function name table.
std::vector<StringRef> NameTable;
virtual std::error_code verifySPMagic(uint64_t Magic) override;
virtual std::error_code readNameTable() override;
/// Read a string indirectly via the name table.
virtual ErrorOr<StringRef> readStringFromTable() override;

public:
SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
: SampleProfileReaderBinary(std::move(B), C, SPF_Binary) {}
SampleProfileReaderExtBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
SampleProfileFormat Format = SPF_Ext_Binary)
: SampleProfileReaderExtBinaryBase(std::move(B), C, Format) {}

/// \brief Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
Expand Down
69 changes: 58 additions & 11 deletions llvm/include/llvm/ProfileData/SampleProfWriter.h
Expand Up @@ -36,7 +36,7 @@ class SampleProfileWriter {
/// Write sample profiles in \p S.
///
/// \returns status code of the file update operation.
virtual std::error_code write(const FunctionSamples &S) = 0;
virtual std::error_code writeSample(const FunctionSamples &S) = 0;

/// Write all the sample profiles in the given map of samples.
///
Expand Down Expand Up @@ -64,6 +64,10 @@ class SampleProfileWriter {
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0;

// Write function profiles to the profile file.
virtual std::error_code
writeFuncProfiles(const StringMap<FunctionSamples> &ProfileMap);

/// Output stream where to emit the profile to.
std::unique_ptr<raw_ostream> OutputStream;

Expand All @@ -72,12 +76,15 @@ class SampleProfileWriter {

/// Compute summary for this profile.
void computeSummary(const StringMap<FunctionSamples> &ProfileMap);

/// Profile format.
SampleProfileFormat Format;
};

/// Sample-based profile writer (text format).
class SampleProfileWriterText : public SampleProfileWriter {
public:
std::error_code write(const FunctionSamples &S) override;
std::error_code writeSample(const FunctionSamples &S) override;

protected:
SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
Expand All @@ -102,13 +109,14 @@ class SampleProfileWriterText : public SampleProfileWriter {
/// Sample-based profile writer (binary format).
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
virtual std::error_code write(const FunctionSamples &S) override;
virtual std::error_code writeSample(const FunctionSamples &S) override;

protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS) {}

protected:
virtual std::error_code writeNameTable() = 0;
virtual std::error_code writeMagicIdent() = 0;
virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
virtual std::error_code writeNameTable();
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
std::error_code writeSummary();
Expand All @@ -118,21 +126,61 @@ class SampleProfileWriterBinary : public SampleProfileWriter {

MapVector<StringRef, uint32_t> NameTable;

private:
void addName(StringRef FName);
void addNames(const FunctionSamples &S);

private:
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
SampleProfileFormat Format);
};

class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;
};

class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;

public:
virtual std::error_code
write(const StringMap<FunctionSamples> &ProfileMap) override;

protected:
virtual std::error_code writeNameTable() override;
virtual std::error_code writeMagicIdent() override;
uint64_t markSectionStart();
uint64_t addNewSection(SecType Sec, uint64_t SectionStart);
virtual void initSectionLayout() = 0;
virtual std::error_code
writeSections(const StringMap<FunctionSamples> &ProfileMap) = 0;

// Specifiy the section layout in the profile. Note that the order in
// SecHdrTable (order to collect sections) may be different from the
// order in SectionLayout (order to write out sections into profile).
SmallVector<SecType, 8> SectionLayout;

private:
void allocSecHdrTable();
std::error_code writeSecHdrTable();
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;

// The location where the output stream starts.
uint64_t FileStart;
// The location in the output stream where the SecHdrTable should be
// written to.
uint64_t SecHdrTableOffset;
std::vector<SecHdrTableEntry> SecHdrTable;
};

class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
using SampleProfileWriterExtBinaryBase::SampleProfileWriterExtBinaryBase;

private:
virtual void initSectionLayout() {
SectionLayout = {SecProfSummary, SecNameTable, SecLBRProfile};
};
virtual std::error_code
writeSections(const StringMap<FunctionSamples> &ProfileMap) override;
};

// CompactBinary is a compact format of binary profile which both reduces
Expand Down Expand Up @@ -169,7 +217,7 @@ class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
using SampleProfileWriterBinary::SampleProfileWriterBinary;

public:
virtual std::error_code write(const FunctionSamples &S) override;
virtual std::error_code writeSample(const FunctionSamples &S) override;
virtual std::error_code
write(const StringMap<FunctionSamples> &ProfileMap) override;

Expand All @@ -181,7 +229,6 @@ class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
/// towards profile start.
uint64_t TableOffset;
virtual std::error_code writeNameTable() override;
virtual std::error_code writeMagicIdent() override;
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
std::error_code writeFuncOffsetTable();
Expand Down

0 comments on commit be90732

Please sign in to comment.