[llvm] Introduction of typified section in ExtBinary format (PR #166553)
Sergey Shcherbinin via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 11 02:40:24 PST 2025
https://github.com/SergeyShch01 updated https://github.com/llvm/llvm-project/pull/166553
>From ecf9cc31e50af12d460ddc2ea44812c2aab87ab4 Mon Sep 17 00:00:00 2001
From: Sergey Shcherbinin <sscherbinin at nvidia.com>
Date: Wed, 5 Nov 2025 17:12:18 +0400
Subject: [PATCH 1/3] Introduction of typified section in ExtBinary format
---
llvm/include/llvm/ProfileData/SampleProf.h | 28 ++++++-
.../llvm/ProfileData/SampleProfReader.h | 5 ++
.../llvm/ProfileData/SampleProfWriter.h | 13 +++
llvm/lib/ProfileData/SampleProfReader.cpp | 51 +++++++++++-
llvm/lib/ProfileData/SampleProfWriter.cpp | 82 ++++++++++++++++---
.../llvm-profdata/sample-flatten-profile.test | 2 +
6 files changed, 166 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index 3dd34aba2d716..a9417dae93f81 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -128,9 +128,13 @@ enum SecType {
SecFuncOffsetTable = 4,
SecFuncMetadata = 5,
SecCSNameTable = 6,
+ // Substitution to SecFuncOffsetTable when we have non-LBR profile types
+ SecTypifiedFuncOffsetTable = 7,
// marker for the first type of profile.
SecFuncProfileFirst = 32,
- SecLBRProfile = SecFuncProfileFirst
+ SecLBRProfile = SecFuncProfileFirst,
+ // Substitution to SecLBRProfile when we have non-LBR profile types
+ SecTypifiedProfile = 33
};
static inline std::string getSecName(SecType Type) {
@@ -149,13 +153,20 @@ static inline std::string getSecName(SecType Type) {
return "FunctionMetadata";
case SecCSNameTable:
return "CSNameTableSection";
+ case SecTypifiedFuncOffsetTable:
+ return "TypifiedFuncOffsetTableSection";
case SecLBRProfile:
return "LBRProfileSection";
+ case SecTypifiedProfile:
+ return "TypifiedProfileSection";
default:
return "UnknownSection";
}
}
+// Types of sample profile which can be in placed in SecTypifiedProfile
+enum ProfTypes { ProfTypeLBR = 0, ProfTypeNum };
+
// Entry type of section header table used by SampleProfileExtBinaryBaseReader
// and SampleProfileExtBinaryBaseWriter.
struct SecHdrTableEntry {
@@ -1341,6 +1352,12 @@ class FunctionSamples {
return !(*this == Other);
}
+ bool hasNonLBRSamples() const {
+ // currently just a stub - should be implemented when
+ // first non-LBR profile is encountered
+ return false;
+ }
+
private:
/// CFG hash value for the function.
uint64_t FunctionHash = 0;
@@ -1466,6 +1483,15 @@ class SampleProfileMap
size_t erase(const key_type &Key) { return base_type::erase(Key); }
iterator erase(iterator It) { return base_type::erase(It); }
+
+ bool hasNonLBRProfile() const {
+ for (const auto &[Context, FuncSamples] : *this) {
+ if (FuncSamples.hasNonLBRSamples()) {
+ return true;
+ }
+ }
+ return false;
+ }
};
using NameFunctionSamples = std::pair<hash_code, const FunctionSamples *>;
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index 799938ab901c1..74e3f1773656d 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -570,6 +570,7 @@ class SampleProfileReader {
FuncMetadataIndex;
std::pair<const uint8_t *, const uint8_t *> ProfileSecRange;
+ bool IsProfileTypified = false;
/// Whether the profile has attribute metadata.
bool ProfileHasAttribute = false;
@@ -687,6 +688,10 @@ class LLVM_ABI SampleProfileReaderBinary : public SampleProfileReader {
/// Read the contents of the given profile instance.
std::error_code readProfile(FunctionSamples &FProfile);
+ /// Read specific profile types.
+ std::error_code readLBRProfile(FunctionSamples &FProfile);
+ std::error_code readTypifiedProfile(FunctionSamples &FProfile);
+
/// Read the contents of Magic number and Version number.
std::error_code readMagicIdent();
diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index 9dbeaf56509b0..052843f9f55ac 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -215,6 +215,10 @@ class LLVM_ABI SampleProfileWriterBinary : public SampleProfileWriter {
virtual std::error_code writeContextIdx(const SampleContext &Context);
std::error_code writeNameIdx(FunctionId FName);
std::error_code writeBody(const FunctionSamples &S);
+ void writeLBRProfile(const FunctionSamples &S);
+ /// Writes typified profile for function
+ void writeTypifiedProfile(const FunctionSamples &S);
+
inline void stablizeNameTable(MapVector<FunctionId, uint32_t> &NameTable,
std::set<FunctionId> &V);
@@ -230,6 +234,7 @@ class LLVM_ABI SampleProfileWriterBinary : public SampleProfileWriter {
raw_ostream &OS);
bool WriteVTableProf = false;
+ bool WriteTypifiedProf = false;
private:
LLVM_ABI friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
@@ -427,6 +432,9 @@ class LLVM_ABI SampleProfileWriterExtBinary
std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
+ // Configure whether to use typified profile sections
+ void configureTypifiedProfile(const SampleProfileMap &ProfileMap);
+
std::error_code writeCustomSection(SecType Type) override {
return sampleprof_error::success;
};
@@ -435,6 +443,11 @@ class LLVM_ABI SampleProfileWriterExtBinary
assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
"Unsupported layout");
}
+
+ /// Section types for profile storage and bookkeeping (used to switch between
+ /// typified and non-typified profiles).
+ SecType ProfSection = SecLBRProfile;
+ SecType FuncOffsetSection = SecFuncOffsetTable;
};
} // end namespace sampleprof
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 766c0814ca067..d97cc8a6f6b88 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -710,7 +710,7 @@ SampleProfileReaderBinary::readCallsiteVTableProf(FunctionSamples &FProfile) {
}
std::error_code
-SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
+SampleProfileReaderBinary::readLBRProfile(FunctionSamples &FProfile) {
auto NumSamples = readNumber<uint64_t>();
if (std::error_code EC = NumSamples.getError())
return EC;
@@ -761,6 +761,52 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
}
+ return sampleprof_error::success;
+}
+
+std::error_code
+SampleProfileReaderBinary::readTypifiedProfile(FunctionSamples &FProfile) {
+ // read the number of profile types
+ auto ProfNum = readNumber<uint64_t>();
+ if (std::error_code EC = ProfNum.getError())
+ return EC;
+
+ // read specified number of typified profiles
+ for (uint64_t i = 0; i < *ProfNum; i++) {
+ auto Type = readNumber<uint64_t>();
+ if (std::error_code EC = Type.getError())
+ return EC;
+ auto Size = readUnencodedNumber<uint64_t>();
+ if (std::error_code EC = Size.getError())
+ return EC;
+
+ switch (*Type) {
+ case ProfTypeLBR:
+ if (std::error_code EC = readLBRProfile(FProfile))
+ return EC;
+ break;
+ default:
+ // skip unknown profile type for forward compatibility
+ Data += *Size;
+ if (Data > End)
+ return sampleprof_error::truncated;
+ break;
+ }
+ }
+
+ return sampleprof_error::success;
+}
+
+std::error_code
+SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
+ if (IsProfileTypified) {
+ if (std::error_code EC = readTypifiedProfile(FProfile))
+ return EC;
+ } else {
+ if (std::error_code EC = readLBRProfile(FProfile))
+ return EC;
+ }
+
// Read all the samples for inlined function calls.
auto NumCallsites = readNumber<uint32_t>();
if (std::error_code EC = NumCallsites.getError())
@@ -876,11 +922,14 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
break;
}
case SecLBRProfile:
+ case SecTypifiedProfile:
ProfileSecRange = std::make_pair(Data, End);
+ IsProfileTypified = Entry.Type == SecTypifiedProfile;
if (std::error_code EC = readFuncProfiles())
return EC;
break;
case SecFuncOffsetTable:
+ case SecTypifiedFuncOffsetTable:
// If module is absent, we are using LLVM tools, and need to read all
// profiles, so skip reading the function offset table.
if (!M) {
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index e5f31348578b8..c9787f367156c 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -46,6 +46,10 @@ static cl::opt<bool> ExtBinaryWriteVTableTypeProf(
"extbinary-write-vtable-type-prof", cl::init(false), cl::Hidden,
cl::desc("Write vtable type profile in ext-binary sample profile writer"));
+static cl::opt<bool> ExtBinaryForceTypifiedProf(
+ "extbinary-force-typified-prof", cl::init(false), cl::Hidden,
+ cl::desc("Force utilization of typified profile format"));
+
namespace llvm {
namespace support {
namespace endian {
@@ -460,11 +464,13 @@ std::error_code SampleProfileWriterExtBinaryBase::writeOneSection(
return EC;
break;
case SecLBRProfile:
+ case SecTypifiedProfile:
SecLBRProfileStart = OutputStream->tell();
if (std::error_code EC = writeFuncProfiles(ProfileMap))
return EC;
break;
case SecFuncOffsetTable:
+ case SecTypifiedFuncOffsetTable:
if (auto EC = writeFuncOffsetTable())
return EC;
break;
@@ -504,11 +510,11 @@ std::error_code SampleProfileWriterExtBinary::writeDefaultLayout(
return EC;
if (auto EC = writeOneSection(SecCSNameTable, 2, ProfileMap))
return EC;
- if (auto EC = writeOneSection(SecLBRProfile, 4, ProfileMap))
+ if (auto EC = writeOneSection(ProfSection, 4, ProfileMap))
return EC;
if (auto EC = writeOneSection(SecProfileSymbolList, 5, ProfileMap))
return EC;
- if (auto EC = writeOneSection(SecFuncOffsetTable, 3, ProfileMap))
+ if (auto EC = writeOneSection(FuncOffsetSection, 3, ProfileMap))
return EC;
if (auto EC = writeOneSection(SecFuncMetadata, 6, ProfileMap))
return EC;
@@ -530,24 +536,23 @@ std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
const SampleProfileMap &ProfileMap) {
SampleProfileMap ContextProfileMap, NoContextProfileMap;
splitProfileMapToTwo(ProfileMap, ContextProfileMap, NoContextProfileMap);
-
if (auto EC = writeOneSection(SecProfSummary, 0, ProfileMap))
return EC;
if (auto EC = writeOneSection(SecNameTable, 1, ProfileMap))
return EC;
- if (auto EC = writeOneSection(SecLBRProfile, 3, ContextProfileMap))
+ if (auto EC = writeOneSection(ProfSection, 3, ContextProfileMap))
return EC;
- if (auto EC = writeOneSection(SecFuncOffsetTable, 2, ContextProfileMap))
+ if (auto EC = writeOneSection(FuncOffsetSection, 2, ContextProfileMap))
return EC;
// Mark the section to have no context. Note section flag needs to be set
// before writing the section.
addSectionFlag(5, SecCommonFlags::SecFlagFlat);
- if (auto EC = writeOneSection(SecLBRProfile, 5, NoContextProfileMap))
+ if (auto EC = writeOneSection(ProfSection, 5, NoContextProfileMap))
return EC;
// Mark the section to have no context. Note section flag needs to be set
// before writing the section.
addSectionFlag(4, SecCommonFlags::SecFlagFlat);
- if (auto EC = writeOneSection(SecFuncOffsetTable, 4, NoContextProfileMap))
+ if (auto EC = writeOneSection(FuncOffsetSection, 4, NoContextProfileMap))
return EC;
if (auto EC = writeOneSection(SecProfileSymbolList, 6, ProfileMap))
return EC;
@@ -557,8 +562,30 @@ std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
return sampleprof_error::success;
}
+void SampleProfileWriterExtBinary::configureTypifiedProfile(
+ const SampleProfileMap &ProfileMap) {
+ if (!ExtBinaryForceTypifiedProf && !ProfileMap.hasNonLBRProfile()) {
+ WriteTypifiedProf = false;
+ ProfSection = SecLBRProfile;
+ FuncOffsetSection = SecFuncOffsetTable;
+ return;
+ }
+ // Use typified profile sections: directly change the section types
+ // to avoid duplicating the whole layout and its handling.
+ WriteTypifiedProf = true;
+ FuncOffsetSection = SecTypifiedFuncOffsetTable;
+ ProfSection = SecTypifiedProfile;
+ for (auto &Entry : SectionHdrLayout) {
+ if (Entry.Type == SecFuncOffsetTable)
+ Entry.Type = SecTypifiedFuncOffsetTable;
+ else if (Entry.Type == SecLBRProfile)
+ Entry.Type = SecTypifiedProfile;
+ }
+}
+
std::error_code SampleProfileWriterExtBinary::writeSections(
const SampleProfileMap &ProfileMap) {
+ configureTypifiedProfile(ProfileMap);
std::error_code EC;
if (SecLayout == DefaultLayout)
EC = writeDefaultLayout(ProfileMap);
@@ -885,14 +912,10 @@ std::error_code SampleProfileWriterBinary::writeSummary() {
}
return sampleprof_error::success;
}
-std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
- auto &OS = *OutputStream;
- if (std::error_code EC = writeContextIdx(S.getContext()))
- return EC;
+void SampleProfileWriterBinary::writeLBRProfile(const FunctionSamples &S) {
+ auto &OS = *OutputStream;
encodeULEB128(S.getTotalSamples(), OS);
-
- // Emit all the body samples.
encodeULEB128(S.getBodySamples().size(), OS);
for (const auto &I : S.getBodySamples()) {
LineLocation Loc = I.first;
@@ -900,6 +923,39 @@ std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
Loc.serialize(OS);
Sample.serialize(OS, getNameTable());
}
+}
+
+void SampleProfileWriterBinary::writeTypifiedProfile(const FunctionSamples &S) {
+ // Currently only LBR profile is supported as typified profile.
+ auto &OS = *OutputStream;
+ // write the number of profile types for function
+ encodeULEB128(1, OS);
+ // Start first profile writing: write profile type
+ encodeULEB128(ProfTypeLBR, OS);
+ // create placeholder for profile size
+ uint64_t SizeOffset = OS.tell();
+ support::endian::Writer PlaceWriter(OS, llvm::endianness::little);
+ PlaceWriter.write(static_cast<uint64_t>(-1));
+ // write the profile itself
+ uint64_t BodyStart = OS.tell();
+ writeLBRProfile(S);
+ uint64_t BodySize = OS.tell() - BodyStart;
+ // write profile size
+ support::endian::SeekableWriter PWriter(static_cast<raw_pwrite_stream &>(OS),
+ llvm::endianness::little);
+ PWriter.pwrite(BodySize, SizeOffset);
+}
+
+std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
+ auto &OS = *OutputStream;
+ if (std::error_code EC = writeContextIdx(S.getContext()))
+ return EC;
+
+ // Emit all the body samples.
+ if (WriteTypifiedProf)
+ writeTypifiedProfile(S);
+ else
+ writeLBRProfile(S);
// Recursively emit all the callsite samples.
uint64_t NumCallsites = 0;
diff --git a/llvm/test/tools/llvm-profdata/sample-flatten-profile.test b/llvm/test/tools/llvm-profdata/sample-flatten-profile.test
index f99021bc6b723..34dab716a067f 100644
--- a/llvm/test/tools/llvm-profdata/sample-flatten-profile.test
+++ b/llvm/test/tools/llvm-profdata/sample-flatten-profile.test
@@ -1,8 +1,10 @@
; RUN: llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %S/Inputs/sample-flatten-profile.proftext -o - | FileCheck %s --match-full-lines --strict-whitespace
; RUN: llvm-profdata merge --sample --extbinary %S/Inputs/sample-flatten-profile.proftext -o %t2 && llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %t2 -o - | FileCheck %s --match-full-lines --strict-whitespace
+; RUN: llvm-profdata merge --sample --extbinary-force-typified-prof --extbinary %S/Inputs/sample-flatten-profile.proftext -o %t2 && llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %t2 -o - | FileCheck %s --match-full-lines --strict-whitespace
; RUN: llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %S/Inputs/sample-flatten-profile-cs.proftext -o - | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=CHECK-CS
; RUN: llvm-profdata merge --sample --extbinary %S/Inputs/sample-flatten-profile-cs.proftext -o %t2 && llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %t2 -o - | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=CHECK-CS
+; RUN: llvm-profdata merge --sample --extbinary-force-typified-prof --extbinary %S/Inputs/sample-flatten-profile-cs.proftext -o %t2 && llvm-profdata merge --sample --convert-sample-profile-layout=flat --text %t2 -o - | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=CHECK-CS
; CHECK:baz:169:10
; CHECK-NEXT: 1: 10
>From 8f82e75bfd20f8bb4d7e6100e8795db49012364e Mon Sep 17 00:00:00 2001
From: Sergey Shcherbinin <sscherbinin at nvidia.com>
Date: Tue, 11 Nov 2025 13:25:02 +0400
Subject: [PATCH 2/3] Typo fixed
Co-authored-by: Mingming Liu <minglotus6 at gmail.com>
---
llvm/include/llvm/ProfileData/SampleProf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index a9417dae93f81..26972ca443481 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -164,7 +164,7 @@ static inline std::string getSecName(SecType Type) {
}
}
-// Types of sample profile which can be in placed in SecTypifiedProfile
+// Types of sample profile which can be placed in SecTypifiedProfile
enum ProfTypes { ProfTypeLBR = 0, ProfTypeNum };
// Entry type of section header table used by SampleProfileExtBinaryBaseReader
>From 9cddd78414aedc12dc0b06649a53d0fdb5b0fcd6 Mon Sep 17 00:00:00 2001
From: Sergey Shcherbinin <sscherbinin at nvidia.com>
Date: Tue, 11 Nov 2025 14:39:46 +0400
Subject: [PATCH 3/3] Small additional changes
+ Comments LLVM-fication
+ Typified profile writing is split into several interfaces to support future introduction of new profile types
---
llvm/include/llvm/ProfileData/SampleProf.h | 4 +-
.../llvm/ProfileData/SampleProfWriter.h | 8 +++-
llvm/lib/ProfileData/SampleProfReader.cpp | 2 +-
llvm/lib/ProfileData/SampleProfWriter.cpp | 46 ++++++++++++++-----
4 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index 26972ca443481..1bb8bdc9bfcfd 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -1353,8 +1353,8 @@ class FunctionSamples {
}
bool hasNonLBRSamples() const {
- // currently just a stub - should be implemented when
- // first non-LBR profile is encountered
+ // Currently just a stub - should be implemented when
+ // first non-LBR profile is encountered.
return false;
}
diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index 052843f9f55ac..770fcbe5afb92 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -216,8 +216,12 @@ class LLVM_ABI SampleProfileWriterBinary : public SampleProfileWriter {
std::error_code writeNameIdx(FunctionId FName);
std::error_code writeBody(const FunctionSamples &S);
void writeLBRProfile(const FunctionSamples &S);
- /// Writes typified profile for function
+
+ /// Interfaces for typified profile writing.
void writeTypifiedProfile(const FunctionSamples &S);
+ std::pair<uint64_t, uint64_t> startProfileType(ProfTypes Type);
+ void finishProfileType(uint64_t SizeOffset, uint64_t BodyOffset);
+ void writeTypifiedLBRProfile(const FunctionSamples &S);
inline void stablizeNameTable(MapVector<FunctionId, uint32_t> &NameTable,
std::set<FunctionId> &V);
@@ -432,7 +436,7 @@ class LLVM_ABI SampleProfileWriterExtBinary
std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
- // Configure whether to use typified profile sections
+ // Configure whether to use typified profile sections.
void configureTypifiedProfile(const SampleProfileMap &ProfileMap);
std::error_code writeCustomSection(SecType Type) override {
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index d97cc8a6f6b88..843e38782b440 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -766,7 +766,7 @@ SampleProfileReaderBinary::readLBRProfile(FunctionSamples &FProfile) {
std::error_code
SampleProfileReaderBinary::readTypifiedProfile(FunctionSamples &FProfile) {
- // read the number of profile types
+ // Read the number of profile types.
auto ProfNum = readNumber<uint64_t>();
if (std::error_code EC = ProfNum.getError())
return EC;
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index c9787f367156c..941e3e9eab2ac 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -925,27 +925,49 @@ void SampleProfileWriterBinary::writeLBRProfile(const FunctionSamples &S) {
}
}
-void SampleProfileWriterBinary::writeTypifiedProfile(const FunctionSamples &S) {
- // Currently only LBR profile is supported as typified profile.
+std::pair<uint64_t, uint64_t>
+SampleProfileWriterBinary::startProfileType(ProfTypes Type) {
auto &OS = *OutputStream;
- // write the number of profile types for function
- encodeULEB128(1, OS);
- // Start first profile writing: write profile type
- encodeULEB128(ProfTypeLBR, OS);
- // create placeholder for profile size
+ encodeULEB128(Type, OS);
+ // Create placeholder for profile size.
uint64_t SizeOffset = OS.tell();
support::endian::Writer PlaceWriter(OS, llvm::endianness::little);
PlaceWriter.write(static_cast<uint64_t>(-1));
- // write the profile itself
- uint64_t BodyStart = OS.tell();
- writeLBRProfile(S);
- uint64_t BodySize = OS.tell() - BodyStart;
- // write profile size
+ uint64_t BodyOffset = OS.tell();
+ return {SizeOffset, BodyOffset};
+}
+
+void SampleProfileWriterBinary::finishProfileType(uint64_t SizeOffset,
+ uint64_t BodyOffset) {
+ auto &OS = *OutputStream;
+ uint64_t BodySize = OS.tell() - BodyOffset;
+ // Write profile size.
support::endian::SeekableWriter PWriter(static_cast<raw_pwrite_stream &>(OS),
llvm::endianness::little);
PWriter.pwrite(BodySize, SizeOffset);
}
+void SampleProfileWriterBinary::writeTypifiedLBRProfile(
+ const FunctionSamples &S) {
+ auto [SizeOffset, BodyOffset] = startProfileType(ProfTypeLBR);
+ writeLBRProfile(S);
+ finishProfileType(SizeOffset, BodyOffset);
+}
+
+void SampleProfileWriterBinary::writeTypifiedProfile(const FunctionSamples &S) {
+ auto &OS = *OutputStream;
+ bool WriteLBRProf = !S.getBodySamples().empty();
+ // Other profile types should be added here.
+ uint32_t TypesNum = WriteLBRProf;
+ assert(TypesNum && "Empty function samples");
+
+ // Write the number of profile types for function.
+ encodeULEB128(TypesNum, OS);
+
+ if (WriteLBRProf)
+ writeTypifiedLBRProfile(S);
+}
+
std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
auto &OS = *OutputStream;
if (std::error_code EC = writeContextIdx(S.getContext()))
More information about the llvm-commits
mailing list