[llvm] febf507 - [SampleProfile] Disambiguate terminology around "CS" in Eytzinger layout (NFC) (#215358)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 23:56:01 PDT 2026


Author: Kazu Hirata
Date: 2026-08-10T23:55:55-07:00
New Revision: febf50748effc5fb381ad479cf129f1ebcdc4bec

URL: https://github.com/llvm/llvm-project/commit/febf50748effc5fb381ad479cf129f1ebcdc4bec
DIFF: https://github.com/llvm/llvm-project/commit/febf50748effc5fb381ad479cf129f1ebcdc4bec.diff

LOG: [SampleProfile] Disambiguate terminology around "CS" in Eytzinger layout (NFC) (#215358)

The abbreviation CS (Context-Sensitive) is overloaded across LLVM
AutoFDO to describe two different concepts:

1. CSSPGO (FunctionSamples::ProfileIsCS == true): Profiles with
   SecCSNameTable where top-level entries are keyed by full callstack
   vectors (e.g., "A", "A->B", "A->B->C"). Multiple top-level keys can
   end in the same leaf GUID, making a 1-to-1 GUID offset array
   impossible.

2. Nested Profiles (IsCS / CSKeys when ProfileIsCS == false): Regular
   AutoFDO profiles where top-level entries are strictly individual
   function GUIDs ("A"), but their sample trees contain nested inline
   callsite samples. The Eytzinger layout is 100% compatible with this
   mode.

Using CS for both features is very confusing because IsCS and CSKeys
may appear to be related to CSSPGO.

This patch renames Eytzinger layout identifiers to contrast "Nested"
against "Flat", leaving FunctionSamples::ProfileIsCS intact:

- EytzingerSpan::CS -> EytzingerSpan::Nested
- CSKeys -> NestedKeys
- IsCS -> IsNested
- isContextSensitiveTopLevel() -> hasCallsiteSamples()

Assisted-by: Antigravity

Added: 
    

Modified: 
    llvm/include/llvm/ProfileData/SampleProf.h
    llvm/include/llvm/ProfileData/SampleProfReader.h
    llvm/include/llvm/ProfileData/SampleProfWriter.h
    llvm/lib/ProfileData/SampleProfReader.cpp
    llvm/lib/ProfileData/SampleProfWriter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index eaf347b62b24e..3d69b7711588a 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -193,7 +193,7 @@ struct SecHdrTableEntry {
 enum class SecCommonFlags : uint32_t {
   SecFlagInValid = 0,
   SecFlagCompress = (1 << 0),
-  // Indicate the section contains only profile without context.
+  // Indicate the section contains flat profiles (without callsite samples).
   SecFlagFlat = (1 << 1)
 };
 
@@ -209,11 +209,11 @@ enum class SecNameTableFlags : uint32_t {
   // Profile contains ".__uniq." suffix name. Compiler shouldn't strip
   // the suffix when doing profile matching when seeing the flag.
   SecFlagUniqSuffix = (1 << 2),
-  // Name table is stored in 3-span Eytzinger layout (CS, Flat, Inlinees).
+  // Name table is stored in 3-span Eytzinger layout (Nested, Flat, Inlinees).
   SecFlagEytzinger = (1 << 3)
 };
 
-enum class EytzingerSpan : size_t { CS, Flat, Inlinee, NumSpans };
+enum class EytzingerSpan : size_t { Nested, Flat, Inlinee, NumSpans };
 
 enum class SecProfileSymbolListFlags : uint32_t {
   SecFlagInValid = 0,
@@ -1067,8 +1067,8 @@ class FunctionSamples {
     return CallsiteSamples;
   }
 
-  /// Return whether this top-level function profile is context sensitive.
-  bool isContextSensitiveTopLevel() const { return !CallsiteSamples.empty(); }
+  /// Return whether this function profile contains callsite samples.
+  bool hasCallsiteSamples() const { return !CallsiteSamples.empty(); }
 
   /// Returns vtable access samples for the C++ types collected in this
   /// function.

diff  --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index e0d140c0c8d2c..fd0902f06b4aa 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -399,7 +399,7 @@ class SampleProfileNameTable {
   virtual FunctionId operator[](size_t Idx) const = 0;
 
   virtual EytzingerTableSpan<support::ulittle64_t>
-  getEytzingerSpan(bool IsCS) const {
+  getEytzingerSpan(bool IsNested) const {
     llvm_unreachable(
         "getEytzingerSpan is exclusively supported for Eytzinger layout");
   }
@@ -507,12 +507,12 @@ class EytzingerSampleProfileNameTable final : public SampleProfileNameTable {
 
 public:
   EytzingerSampleProfileNameTable(const support::ulittle64_t *Data,
-                                  size_t NumCS, size_t NumFlat,
+                                  size_t NumNested, size_t NumFlat,
                                   size_t NumInlinees)
-      : Array(Data, NumCS + NumFlat + NumInlinees),
-        Spans{{{Data, NumCS},
-               {Data + NumCS, NumFlat},
-               {Data + NumCS + NumFlat, NumInlinees}}} {}
+      : Array(Data, NumNested + NumFlat + NumInlinees),
+        Spans{{{Data, NumNested},
+               {Data + NumNested, NumFlat},
+               {Data + NumNested + NumFlat, NumInlinees}}} {}
 
   size_t size() const override { return Array.size(); }
 
@@ -521,9 +521,9 @@ class EytzingerSampleProfileNameTable final : public SampleProfileNameTable {
   }
 
   EytzingerTableSpan<support::ulittle64_t>
-  getEytzingerSpan(bool IsCS) const override {
-    return Spans[static_cast<size_t>(IsCS ? EytzingerSpan::CS
-                                          : EytzingerSpan::Flat)];
+  getEytzingerSpan(bool IsNested) const override {
+    return Spans[static_cast<size_t>(IsNested ? EytzingerSpan::Nested
+                                              : EytzingerSpan::Flat)];
   }
 
   bool contains(uint64_t GUID) const override {
@@ -1166,8 +1166,8 @@ class LLVM_ABI SampleProfileReaderExtBinaryBase
   std::error_code readFuncMetadata(DenseSet<FunctionSamples *> &Profiles);
   std::error_code readFuncMetadata();
   std::error_code readFuncMetadata(FunctionSamples *FProfile);
-  std::error_code readFuncOffsetTable(bool IsEytzinger, bool IsCS);
-  std::error_code readEytzingerFuncOffsetTable(bool IsCS);
+  std::error_code readFuncOffsetTable(bool IsEytzinger, bool IsNested);
+  std::error_code readEytzingerFuncOffsetTable(bool IsNested);
   std::error_code readLegacyFuncOffsetTable();
   std::error_code readFuncProfiles();
   std::error_code readFuncProfiles(const DenseSet<StringRef> &FuncsToUse,

diff  --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index b9797c458617a..7c2776a0ea3a7 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -417,8 +417,8 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
   std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
   std::error_code
   writeEytzingerNameTableSection(const SampleProfileMap &ProfileMap);
-  std::error_code writeFuncOffsetTable(bool IsCS);
-  std::error_code writeEytzingerFuncOffsetTable(bool IsCS);
+  std::error_code writeFuncOffsetTable(bool IsNested);
+  std::error_code writeEytzingerFuncOffsetTable(bool IsNested);
   std::error_code writeLegacyFuncOffsetTable();
   std::error_code writeProfileSymbolListSection();
   std::error_code writeStringBasedProfileSymbolListSection();
@@ -468,7 +468,7 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
   MapVector<SampleContext, uint64_t> FuncOffsetTable;
   // Whether to use MD5 to represent string.
   bool UseMD5 = false;
-  size_t NumCS = 0;
+  size_t NumNested = 0;
   size_t NumFlat = 0;
 
   /// CSNameTable maps function context to its offset in SecCSNameTable section.

diff  --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index eb8e064da198e..8f50873c72d03 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -899,14 +899,14 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
           hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagEytzinger);
       bool IsFlat = hasSecFlag(Entry, SecCommonFlags::SecFlagFlat);
       // An unflagged function offset table inherently indexes the primary
-      // context-sensitive symbol span.
-      bool IsCS = !IsFlat;
+      // Nested symbol span.
+      bool IsNested = !IsFlat;
       assert((!ProfileIsCS ||
               hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered) ||
               IsEytzinger) &&
              "func offset table should always be sorted or in Eytzinger BFS "
              "order in CS profile");
-      if (std::error_code EC = readFuncOffsetTable(IsEytzinger, IsCS))
+      if (std::error_code EC = readFuncOffsetTable(IsEytzinger, IsNested))
         return EC;
     }
     break;
@@ -995,27 +995,27 @@ bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() {
 
 std::error_code
 SampleProfileReaderExtBinaryBase::readFuncOffsetTable(bool IsEytzinger,
-                                                      bool IsCS) {
+                                                      bool IsNested) {
   if (IsEytzinger)
-    return readEytzingerFuncOffsetTable(IsCS);
+    return readEytzingerFuncOffsetTable(IsNested);
   return readLegacyFuncOffsetTable();
 }
 
 std::error_code
-SampleProfileReaderExtBinaryBase::readEytzingerFuncOffsetTable(bool IsCS) {
+SampleProfileReaderExtBinaryBase::readEytzingerFuncOffsetTable(bool IsNested) {
   // If there are more than one function offset section, the profile associated
   // with the previous section has to be done reading before next one is read.
   FuncOffsetTable.reset();
 
   size_t Size = End - Data;
-  size_t SpanSize = NameTable->getEytzingerSpan(IsCS).size();
+  size_t SpanSize = NameTable->getEytzingerSpan(IsNested).size();
   if (Size != SpanSize * sizeof(uint32_t))
     return sampleprof_error::malformed;
 
   auto *Array = reinterpret_cast<const support::ulittle32_t *>(Data);
   ArrayRef<support::ulittle32_t> Offsets(Array, SpanSize);
 
-  FuncOffsetTable.emplace(EytzingerMode, NameTable->getEytzingerSpan(IsCS),
+  FuncOffsetTable.emplace(EytzingerMode, NameTable->getEytzingerSpan(IsNested),
                           Offsets);
 
   Data = End;
@@ -1365,16 +1365,16 @@ std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(
 
 // Read the Eytzinger layout for SecNameTable from an ExtBinary MD5 profile.
 //
-// The section consists of three sequential ULEB128 symbol counts (CS, Flat, and
-// Inlinees) followed by their corresponding arrays of 64-bit MD5 hash keys laid
-// out in Eytzinger order.
+// The section consists of three sequential ULEB128 symbol counts (Nested, Flat,
+// and Inlinees) followed by their corresponding arrays of 64-bit MD5 hash keys
+// laid out in Eytzinger order.
 std::error_code SampleProfileReaderExtBinaryBase::readNameTableSecEytzinger(
     bool IsMD5, bool FixedLengthMD5) {
   assert(IsMD5 && "Eytzinger name tables require MD5 representation");
   if (!IsMD5)
     return sampleprof_error::malformed;
 
-  // Read the table sizes for CS, flat, and inlinee symbols.
+  // Read the table sizes for Nested, flat, and inlinee symbols.
   std::array<uint64_t, static_cast<size_t>(EytzingerSpan::NumSpans)> Counts;
   for (uint64_t &Count : Counts) {
     auto ValOrErr = readNumber<uint64_t>();
@@ -1382,20 +1382,20 @@ std::error_code SampleProfileReaderExtBinaryBase::readNameTableSecEytzinger(
       return EC;
     Count = *ValOrErr;
   }
-  auto [NumCS, NumFlat, NumInlinees] = Counts;
+  auto [NumNested, NumFlat, NumInlinees] = Counts;
 
   // Guard against unsigned overflow in total entry computation.
-  if (NumCS > std::numeric_limits<uint32_t>::max() ||
+  if (NumNested > std::numeric_limits<uint32_t>::max() ||
       NumFlat > std::numeric_limits<uint32_t>::max() ||
       NumInlinees > std::numeric_limits<uint32_t>::max())
     return sampleprof_error::malformed;
 
-  uint64_t TotalEntries = NumCS + NumFlat + NumInlinees;
+  uint64_t TotalEntries = NumNested + NumFlat + NumInlinees;
   if (static_cast<size_t>(End - Data) < TotalEntries * sizeof(uint64_t))
     return sampleprof_error::truncated;
 
   NameTable = std::make_unique<EytzingerSampleProfileNameTable>(
-      reinterpret_cast<const support::ulittle64_t *>(Data), NumCS, NumFlat,
+      reinterpret_cast<const support::ulittle64_t *>(Data), NumNested, NumFlat,
       NumInlinees);
 
   if (!ProfileIsCS)

diff  --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index 1962c83e6e7e6..5c6ca653b0cd9 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -279,25 +279,25 @@ SampleProfileWriterExtBinaryBase::writeSample(const FunctionSamples &S) {
 }
 
 std::error_code
-SampleProfileWriterExtBinaryBase::writeFuncOffsetTable(bool IsCS) {
+SampleProfileWriterExtBinaryBase::writeFuncOffsetTable(bool IsNested) {
   if (WriteEytzingerNameTables) {
     // Eytzinger layout requires MD5 representation and does not support
     // multi-context Context-Sensitive profiles.
     if (!UseMD5 || FunctionSamples::ProfileIsCS)
       return sampleprof_error::unsupported_writing_format;
-    return writeEytzingerFuncOffsetTable(IsCS);
+    return writeEytzingerFuncOffsetTable(IsNested);
   }
   return writeLegacyFuncOffsetTable();
 }
 
 std::error_code
-SampleProfileWriterExtBinaryBase::writeEytzingerFuncOffsetTable(bool IsCS) {
-  assert((NumCS + NumFlat > 0 || FuncOffsetTable.empty()) &&
+SampleProfileWriterExtBinaryBase::writeEytzingerFuncOffsetTable(bool IsNested) {
+  assert((NumNested + NumFlat > 0 || FuncOffsetTable.empty()) &&
          "SecNameTable must be written before SecFuncOffsetTable to establish "
          "Eytzinger indices!");
 
-  size_t SpanSize = IsCS ? NumCS : NumFlat;
-  size_t BaseIdx = IsCS ? 0 : NumCS;
+  size_t SpanSize = IsNested ? NumNested : NumFlat;
+  size_t BaseIdx = IsNested ? 0 : NumNested;
 
   std::vector<support::ulittle32_t> FuncOffsets(
       SpanSize, support::ulittle32_t(UINT32_MAX));
@@ -486,11 +486,11 @@ namespace {
 //
 // The on-disk layout of the Eytzinger name table section consists of symbol
 // counts followed by three contiguous Eytzinger hash arrays:
-// - ULEB128 count of Context-Sensitive (CS) top-level profile symbol keys
+// - ULEB128 count of Nested top-level profile symbol keys
 // - ULEB128 count of Flat top-level profile symbol keys
 // - ULEB128 count of Inlinee and auxiliary profile symbol keys
-// - Array of 64-bit little-endian MD5 hash keys for CS profiles in Eytzinger
-//   order
+// - Array of 64-bit little-endian MD5 hash keys for Nested profiles in
+//   Eytzinger order
 // - Array of 64-bit little-endian MD5 hash keys for Flat profiles in Eytzinger
 //   order
 // - Array of 64-bit little-endian MD5 hash keys for Inlinees in Eytzinger order
@@ -499,10 +499,10 @@ class EytzingerNameTable {
   std::array<TableT, static_cast<size_t>(EytzingerSpan::NumSpans)> Spans;
 
 public:
-  EytzingerNameTable(std::vector<support::ulittle64_t> CSKeys,
+  EytzingerNameTable(std::vector<support::ulittle64_t> NestedKeys,
                      std::vector<support::ulittle64_t> FlatKeys,
                      std::vector<support::ulittle64_t> InlineeKeys)
-      : Spans{TableT::create(std::move(CSKeys)),
+      : Spans{TableT::create(std::move(NestedKeys)),
               TableT::create(std::move(FlatKeys)),
               TableT::create(std::move(InlineeKeys))} {}
 
@@ -536,17 +536,18 @@ std::error_code
 SampleProfileWriterExtBinaryBase::writeEytzingerNameTableSection(
     const SampleProfileMap &ProfileMap) {
   DenseSet<uint64_t> TopLevelGUIDs;
-  std::vector<support::ulittle64_t> CSKeys, FlatKeys, InlineeKeys;
+  std::vector<support::ulittle64_t> NestedKeys, FlatKeys, InlineeKeys;
 
-  // Collect top-level CS and Flat keys directly from ProfileMap.
+  // Collect top-level Nested and Flat keys directly from ProfileMap.
   for (const auto &I : ProfileMap) {
     const SampleContext &Ctx = I.second.getContext();
     uint64_t GUID = Ctx.getFunction().getHashCode();
     if (TopLevelGUIDs.insert(GUID).second) {
-      // In single-table default layouts, unify all top-level symbols in the CS
-      // partition so they match the single unflagged function offset table.
-      if (SecLayout != CtxSplitLayout || I.second.isContextSensitiveTopLevel())
-        CSKeys.emplace_back(GUID);
+      // In single-table default layouts, unify all top-level symbols in the
+      // Nested partition so they match the single unflagged function offset
+      // table.
+      if (SecLayout != CtxSplitLayout || I.second.hasCallsiteSamples())
+        NestedKeys.emplace_back(GUID);
       else
         FlatKeys.emplace_back(GUID);
     }
@@ -560,7 +561,7 @@ SampleProfileWriterExtBinaryBase::writeEytzingerNameTableSection(
       InlineeKeys.emplace_back(GUID);
   }
 
-  EytzingerNameTable Tables(std::move(CSKeys), std::move(FlatKeys),
+  EytzingerNameTable Tables(std::move(NestedKeys), std::move(FlatKeys),
                             std::move(InlineeKeys));
 
   // Assign each symbol its corresponding index in the Eytzinger layout.
@@ -568,7 +569,7 @@ SampleProfileWriterExtBinaryBase::writeEytzingerNameTableSection(
     Idx = Tables.findGlobalIdx(FId.getHashCode());
 
   Tables.write(*OutputStream);
-  NumCS = Tables.size(EytzingerSpan::CS);
+  NumNested = Tables.size(EytzingerSpan::Nested);
   NumFlat = Tables.size(EytzingerSpan::Flat);
 
   return sampleprof_error::success;
@@ -678,9 +679,9 @@ std::error_code SampleProfileWriterExtBinaryBase::writeOneSection(
     bool IsFlat =
         hasSecFlag(SectionHdrLayout[LayoutIdx], SecCommonFlags::SecFlagFlat);
     // An unflagged function offset table inherently indexes the primary
-    // context-sensitive symbol span.
-    bool IsCS = !IsFlat;
-    if (auto EC = writeFuncOffsetTable(IsCS))
+    // Nested symbol span.
+    bool IsNested = !IsFlat;
+    if (auto EC = writeFuncOffsetTable(IsNested))
       return EC;
     break;
   }
@@ -732,38 +733,38 @@ std::error_code SampleProfileWriterExtBinary::writeDefaultLayout(
 }
 
 static void splitProfileMapToTwo(const SampleProfileMap &ProfileMap,
-                                 SampleProfileMap &ContextProfileMap,
-                                 SampleProfileMap &NoContextProfileMap) {
+                                 SampleProfileMap &NestedProfileMap,
+                                 SampleProfileMap &FlatProfileMap) {
   for (const auto &I : ProfileMap) {
-    if (I.second.isContextSensitiveTopLevel())
-      ContextProfileMap.insert({I.first, I.second});
+    if (I.second.hasCallsiteSamples())
+      NestedProfileMap.insert({I.first, I.second});
     else
-      NoContextProfileMap.insert({I.first, I.second});
+      FlatProfileMap.insert({I.first, I.second});
   }
 }
 
 std::error_code SampleProfileWriterExtBinary::writeCtxSplitLayout(
     const SampleProfileMap &ProfileMap) {
-  SampleProfileMap ContextProfileMap, NoContextProfileMap;
-  splitProfileMapToTwo(ProfileMap, ContextProfileMap, NoContextProfileMap);
+  SampleProfileMap NestedProfileMap, FlatProfileMap;
+  splitProfileMapToTwo(ProfileMap, NestedProfileMap, FlatProfileMap);
 
   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(SecLBRProfile, 3, NestedProfileMap))
     return EC;
-  if (auto EC = writeOneSection(SecFuncOffsetTable, 2, ContextProfileMap))
+  if (auto EC = writeOneSection(SecFuncOffsetTable, 2, NestedProfileMap))
     return EC;
-  // Mark the section to have no context. Note section flag needs to be set
-  // before writing the section.
+  // Mark the section as flat (without callsite samples). 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(SecLBRProfile, 5, FlatProfileMap))
     return EC;
-  // Mark the section to have no context. Note section flag needs to be set
-  // before writing the section.
+  // Mark the section as flat (without callsite samples). 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(SecFuncOffsetTable, 4, FlatProfileMap))
     return EC;
   if (auto EC = writeOneSection(SecProfileSymbolList, 6, ProfileMap))
     return EC;


        


More information about the llvm-commits mailing list