[llvm] 4a1c004 - [MC] Pack scheduling class entry counts (#202649)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 18 23:54:28 PDT 2026


Author: David Zbarsky
Date: 2026-07-19T08:54:24+02:00
New Revision: 4a1c00420f7e1660d509ac32ca3d02a4aef20ab2

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

LOG: [MC] Pack scheduling class entry counts (#202649)

Generated scheduling classes currently use at most 20 write-resource
entries and 35 write-latency entries, while read-advance counts reach
504. Narrow the two write counts to `uint8_t`, order the three table
indices before the three counts, and emit target-specific compile-time
bounds assertions in generated subtarget source.

This reduces `sizeof(MCSchedClassDesc)` from 14 to 12 bytes in release
builds and from 20 to 16 bytes with debug fields. Fully stripped arm64
`llvm-mca` decreases by 544,896 bytes (1.49%), and the stripped
all-tools multicall binary decreases by 528,376 bytes (0.368%).

Work towards #202616

AI tool disclosure: Co-authored with OpenAI Codex.

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCSchedule.h
    llvm/test/TableGen/CompressWriteLatencyEntry.td
    llvm/utils/TableGen/SubtargetEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCSchedule.h b/llvm/include/llvm/MC/MCSchedule.h
index dcf07c1279cd2..dd65284671d71 100644
--- a/llvm/include/llvm/MC/MCSchedule.h
+++ b/llvm/include/llvm/MC/MCSchedule.h
@@ -137,12 +137,12 @@ struct MCSchedClassDesc {
   uint16_t BeginGroup : 1;
   uint16_t EndGroup : 1;
   uint16_t RetireOOO : 1;
+  uint16_t ReadAdvanceIdx;  // First index into ReadAdvanceTable.
   uint16_t WriteProcResIdx; // First index into WriteProcResTable.
-  uint16_t NumWriteProcResEntries;
   uint16_t WriteLatencyIdx; // First index into WriteLatencyTable.
-  uint16_t NumWriteLatencyEntries;
-  uint16_t ReadAdvanceIdx; // First index into ReadAdvanceTable.
   uint16_t NumReadAdvanceEntries;
+  uint8_t NumWriteProcResEntries;
+  uint8_t NumWriteLatencyEntries;
 
   bool isValid() const {
     return NumMicroOps != InvalidNumMicroOps;
@@ -152,6 +152,15 @@ struct MCSchedClassDesc {
   }
 };
 
+// Guard against accidental growth. If either assertion fails, try to repack
+// MCSchedClassDesc to preserve the compact layout; remove the assertion if the
+// layout can no longer be kept.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+static_assert(sizeof(MCSchedClassDesc) == 16);
+#else
+static_assert(sizeof(MCSchedClassDesc) == 12);
+#endif
+
 /// Specify the cost of a register definition in terms of number of physical
 /// register allocated at register renaming stage. For example, AMD Jaguar.
 /// natively supports 128-bit data types, and operations on 256-bit registers

diff  --git a/llvm/test/TableGen/CompressWriteLatencyEntry.td b/llvm/test/TableGen/CompressWriteLatencyEntry.td
index d6a9f0ac0dd76..53ce09629870e 100644
--- a/llvm/test/TableGen/CompressWriteLatencyEntry.td
+++ b/llvm/test/TableGen/CompressWriteLatencyEntry.td
@@ -21,6 +21,9 @@ let CompleteModel = 0 in {
 
 def Read_D : SchedRead;
 
+// CHECK: static_assert(0 <= UINT8_MAX, "NumWriteProcResEntries does not fit in uint8_t");
+// CHECK-NEXT: static_assert(1 <= UINT8_MAX, "NumWriteLatencyEntries does not fit in uint8_t");
+
 // CHECK: extern const llvm::MCWriteLatencyEntry MyTargetWriteLatencyTable[] = {
 // CHECK-NEXT:  { 0,  0}, // Invalid
 // CHECK-NEXT:  { 1,  0}, // #1 Write_A_Write_C
@@ -34,9 +37,9 @@ def Read_D : SchedRead;
 
 // CHECK:  static const llvm::MCSchedClassDesc SchedModel_ASchedClasses[] = {
 // CHECK-NEXT:  {DBGFIELD(1)  8191, false, false, false, 0, 0,  0, 0,  0, 0},
-// CHECK-NEXT:  {DBGFIELD(/*Inst_A*/ {{[0-9]+}})             1, false, false, false,  0, 0,  1, 1,  0, 0}, // #1
-// CHECK-NEXT:  {DBGFIELD(/*Inst_B*/ {{[0-9]+}})             1, false, false, false,  0, 0,  2, 1,  0, 0}, // #2
-// CHECK-NEXT:  {DBGFIELD(/*Inst_C*/ {{[0-9]+}})             1, false, false, false,  0, 0,  1, 1,  1, 1}, // #3
+// CHECK-NEXT:  {DBGFIELD(/*Inst_A*/ {{[0-9]+}})             1, false, false, false,  0,  0,  1, 0, 0, 1}, // #1
+// CHECK-NEXT:  {DBGFIELD(/*Inst_B*/ {{[0-9]+}})             1, false, false, false,  0,  0,  2, 0, 0, 1}, // #2
+// CHECK-NEXT:  {DBGFIELD(/*Inst_C*/ {{[0-9]+}})             1, false, false, false,  1,  0,  1, 1, 0, 1}, // #3
 // CHECK-NEXT: }; // SchedModel_ASchedClasses
 
 let SchedModel = SchedModel_A in {

diff  --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 5b2a740f1be32..ae41feda46d65 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -55,6 +55,8 @@ class SubtargetEmitter : TargetFeaturesEmitter {
     std::vector<MCWriteLatencyEntry> WriteLatencies;
     std::vector<std::string> WriterNames;
     std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
+    size_t MaxWriteProcResEntries = 0;
+    size_t MaxWriteLatencyEntries = 0;
 
     // Reserve an invalid entry at index 0
     SchedClassTables() {
@@ -1293,6 +1295,8 @@ void SubtargetEmitter::genSchedClassTables(const CodeGenProcModel &ProcModel,
     // WritePrecRes entries are sorted by ProcResIdx.
     llvm::sort(WriteProcResources, LessWriteProcResources());
 
+    SchedTables.MaxWriteProcResEntries =
+        std::max(SchedTables.MaxWriteProcResEntries, WriteProcResources.size());
     SCDesc.NumWriteProcResEntries = WriteProcResources.size();
     std::vector<MCWriteProcResEntry>::iterator WPRPos =
         std::search(SchedTables.WriteProcResources.begin(),
@@ -1306,6 +1310,8 @@ void SubtargetEmitter::genSchedClassTables(const CodeGenProcModel &ProcModel,
                                             WriteProcResources.end());
     }
     // Latency entries must remain in operand order.
+    SchedTables.MaxWriteLatencyEntries =
+        std::max(SchedTables.MaxWriteLatencyEntries, WriteLatencies.size());
     SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
     std::vector<MCWriteLatencyEntry>::iterator WLPos = std::search(
         SchedTables.WriteLatencies.begin(), SchedTables.WriteLatencies.end(),
@@ -1341,6 +1347,11 @@ void SubtargetEmitter::genSchedClassTables(const CodeGenProcModel &ProcModel,
 // Emit SchedClass tables for all processors and associated global tables.
 void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
                                             raw_ostream &OS) {
+  OS << "\nstatic_assert(" << SchedTables.MaxWriteProcResEntries
+     << " <= UINT8_MAX, \"NumWriteProcResEntries does not fit in uint8_t\");\n"
+     << "static_assert(" << SchedTables.MaxWriteLatencyEntries
+     << " <= UINT8_MAX, \"NumWriteLatencyEntries does not fit in uint8_t\");\n";
+
   // Emit global WriteProcResTable.
   OS << "\n// {ProcResourceIdx, ReleaseAtCycle, AcquireAtCycle}\n"
      << "extern const llvm::MCWriteProcResEntry " << Target
@@ -1404,7 +1415,9 @@ void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
         SchedTables.ProcSchedClasses[1 + Idx];
 
     OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup, RetireOOO,"
-       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
+       << " ReadAdvanceIdx, WriteProcResIdx, WriteLatencyIdx,"
+       << " NumReadAdvanceEntries, NumWriteProcResEntries,"
+       << " NumWriteLatencyEntries}\n";
     OS << "static const llvm::MCSchedClassDesc " << Proc.ModelName
        << "SchedClasses[] = {\n";
 
@@ -1426,12 +1439,13 @@ void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
       OS << MCDesc.NumMicroOps << ", " << (MCDesc.BeginGroup ? "true" : "false")
          << ", " << (MCDesc.EndGroup ? "true" : "false") << ", "
          << (MCDesc.RetireOOO ? "true" : "false") << ", "
+         << format("%2d", MCDesc.ReadAdvanceIdx) << ", "
          << format("%2d", MCDesc.WriteProcResIdx) << ", "
-         << MCDesc.NumWriteProcResEntries << ", "
          << format("%2d", MCDesc.WriteLatencyIdx) << ", "
-         << MCDesc.NumWriteLatencyEntries << ", "
-         << format("%2d", MCDesc.ReadAdvanceIdx) << ", "
-         << MCDesc.NumReadAdvanceEntries << "}, // #" << SCIdx << '\n';
+         << MCDesc.NumReadAdvanceEntries << ", "
+         << static_cast<unsigned>(MCDesc.NumWriteProcResEntries) << ", "
+         << static_cast<unsigned>(MCDesc.NumWriteLatencyEntries) << "}, // #"
+         << SCIdx << '\n';
     }
     OS << "}; // " << Proc.ModelName << "SchedClasses\n";
   }


        


More information about the llvm-commits mailing list