[llvm] [MC] Use StringTable for MCSchedClassDesc names (PR #137012)
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 23 09:19:51 PDT 2025
https://github.com/jayfoad created https://github.com/llvm/llvm-project/pull/137012
Use StringTable for the name strings so that large arrays of
MCSchedClassDesc can live in read-only data. This only affects builds
with assertions enabled, otherwise these strings are compiled out.
This improves startup times for llc on my Ubuntu system where PIE is
enabled by default. In a Release+Asserts build it reduced the check-llvm
time from 159 to 112 seconds.
>From 236ea03e41c63a0e0961580349b865a1ca5ed4d7 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Wed, 23 Apr 2025 16:21:53 +0100
Subject: [PATCH] [MC] Use StringTable for MCSchedClassDesc names
Use StringTable for the name strings so that large arrays of
MCSchedClassDesc can live in read-only data. This only affects builds
with assertions enabled, otherwise these strings are compiled out.
This improves startup times for llc on my Ubuntu system where PIE is
enabled by default. In a Release+Asserts build it reduced the check-llvm
time from 159 to 112 seconds.
---
llvm/include/llvm/MC/MCSchedule.h | 12 +++++-
llvm/lib/MC/MCSchedule.cpp | 37 ++++++++++---------
llvm/lib/MCA/InstrBuilder.cpp | 5 ++-
.../TableGen/CompressWriteLatencyEntry.td | 8 ++--
llvm/test/TableGen/InvalidMCSchedClassDesc.td | 12 +++---
llvm/tools/llvm-exegesis/lib/Analysis.cpp | 10 +++--
llvm/utils/TableGen/SubtargetEmitter.cpp | 17 ++++++---
7 files changed, 61 insertions(+), 40 deletions(-)
diff --git a/llvm/include/llvm/MC/MCSchedule.h b/llvm/include/llvm/MC/MCSchedule.h
index 57c8ebeee02a7..2d6d0d4199ee6 100644
--- a/llvm/include/llvm/MC/MCSchedule.h
+++ b/llvm/include/llvm/MC/MCSchedule.h
@@ -15,6 +15,7 @@
#define LLVM_MC_MCSCHEDULE_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringTable.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
@@ -123,7 +124,7 @@ struct MCSchedClassDesc {
static const unsigned short VariantNumMicroOps = InvalidNumMicroOps - 1;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- const char* Name;
+ unsigned NameOffset;
#endif
uint16_t NumMicroOps : 13;
uint16_t BeginGroup : 1;
@@ -321,6 +322,9 @@ struct MCSchedModel {
unsigned ProcID;
const MCProcResourceDesc *ProcResourceTable;
const MCSchedClassDesc *SchedClassTable;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ StringTable SchedClassNameTable = "";
+#endif
unsigned NumProcResourceKinds;
unsigned NumSchedClasses;
// Instruction itinerary tables used by InstrItineraryData.
@@ -408,6 +412,12 @@ struct MCSchedModel {
/// Returns the default initialized model.
static const MCSchedModel Default;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ StringRef getSchedClassName(const MCSchedClassDesc *SCDesc) const {
+ return SchedClassNameTable[SCDesc->NameOffset];
+ }
+#endif
};
// The first three are only template'd arguments so we can get away with leaving
diff --git a/llvm/lib/MC/MCSchedule.cpp b/llvm/lib/MC/MCSchedule.cpp
index 8aea08919f469..b1e1904d654c8 100644
--- a/llvm/lib/MC/MCSchedule.cpp
+++ b/llvm/lib/MC/MCSchedule.cpp
@@ -20,24 +20,25 @@
using namespace llvm;
-static_assert(std::is_trivial_v<MCSchedModel>,
- "MCSchedModel is required to be a trivial type");
-const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
- DefaultMicroOpBufferSize,
- DefaultLoopMicroOpBufferSize,
- DefaultLoadLatency,
- DefaultHighLatency,
- DefaultMispredictPenalty,
- false,
- true,
- /*EnableIntervals=*/false,
- 0,
- nullptr,
- nullptr,
- 0,
- 0,
- nullptr,
- nullptr};
+constexpr MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
+ DefaultMicroOpBufferSize,
+ DefaultLoopMicroOpBufferSize,
+ DefaultLoadLatency,
+ DefaultHighLatency,
+ DefaultMispredictPenalty,
+ false,
+ true,
+ /*EnableIntervals=*/false,
+ 0,
+ nullptr,
+ nullptr,
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ "",
+#endif
+ 0,
+ 0,
+ nullptr,
+ nullptr};
int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
const MCSchedClassDesc &SCDesc) {
diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp
index 2bac99b6309af..d80eb28115b47 100644
--- a/llvm/lib/MCA/InstrBuilder.cpp
+++ b/llvm/lib/MCA/InstrBuilder.cpp
@@ -75,8 +75,9 @@ static void initializeUsedResources(InstrDesc &ID,
WithColor::warning()
<< "Ignoring invalid write of zero cycles on processor resource "
<< PR.Name << "\n";
- WithColor::note() << "found in scheduling class " << SCDesc.Name
- << " (write index #" << I << ")\n";
+ WithColor::note() << "found in scheduling class "
+ << SM.getSchedClassName(&SCDesc) << " (write index #"
+ << I << ")\n";
#endif
continue;
}
diff --git a/llvm/test/TableGen/CompressWriteLatencyEntry.td b/llvm/test/TableGen/CompressWriteLatencyEntry.td
index 88273e8858448..a6a942882ca7f 100644
--- a/llvm/test/TableGen/CompressWriteLatencyEntry.td
+++ b/llvm/test/TableGen/CompressWriteLatencyEntry.td
@@ -33,10 +33,10 @@ def Read_D : SchedRead;
// CHECK-NEXT: }; // MyTargetReadAdvanceTable
// CHECK: static const llvm::MCSchedClassDesc SchedModel_ASchedClasses[] = {
-// CHECK-NEXT: {DBGFIELD("InvalidSchedClass") 8191, false, false, false, 0, 0, 0, 0, 0, 0},
-// CHECK-NEXT: {DBGFIELD("Inst_A") 1, false, false, false, 0, 0, 1, 1, 0, 0}, // #1
-// CHECK-NEXT: {DBGFIELD("Inst_B") 1, false, false, false, 0, 0, 2, 1, 0, 0}, // #2
-// CHECK-NEXT: {DBGFIELD("Inst_C") 1, false, false, false, 0, 0, 1, 1, 1, 1}, // #3
+// CHECK-NEXT: {DBGFIELD(1 /* InvalidSchedClass */) 8191, false, false, false, 0, 0, 0, 0, 0, 0},
+// CHECK-NEXT: {DBGFIELD(19 /* Inst_A */) 1, false, false, false, 0, 0, 1, 1, 0, 0}, // #1
+// CHECK-NEXT: {DBGFIELD(26 /* Inst_B */) 1, false, false, false, 0, 0, 2, 1, 0, 0}, // #2
+// CHECK-NEXT: {DBGFIELD(33 /* Inst_C */) 1, false, false, false, 0, 0, 1, 1, 1, 1}, // #3
// CHECK-NEXT: }; // SchedModel_ASchedClasses
let SchedModel = SchedModel_A in {
diff --git a/llvm/test/TableGen/InvalidMCSchedClassDesc.td b/llvm/test/TableGen/InvalidMCSchedClassDesc.td
index de5392237a84c..5e12d088088ac 100644
--- a/llvm/test/TableGen/InvalidMCSchedClassDesc.td
+++ b/llvm/test/TableGen/InvalidMCSchedClassDesc.td
@@ -18,8 +18,8 @@ let CompleteModel = 0 in {
// Inst_B didn't have the resoures, and it is invalid.
// CHECK: SchedModel_ASchedClasses[] = {
-// CHECK: {DBGFIELD("Inst_A") 1
-// CHECK-NEXT: {DBGFIELD("Inst_B") 8191
+// CHECK: {DBGFIELD(19 /* Inst_A */) 1
+// CHECK-NEXT: {DBGFIELD(26 /* Inst_B */) 8191
let SchedModel = SchedModel_A in {
def Write_A : SchedWriteRes<[]>;
def : InstRW<[Write_A], (instrs Inst_A)>;
@@ -27,16 +27,16 @@ let SchedModel = SchedModel_A in {
// Inst_A didn't have the resoures, and it is invalid.
// CHECK: SchedModel_BSchedClasses[] = {
-// CHECK: {DBGFIELD("Inst_A") 8191
-// CHECK-NEXT: {DBGFIELD("Inst_B") 1
+// CHECK: {DBGFIELD(19 /* Inst_A */) 8191
+// CHECK-NEXT: {DBGFIELD(26 /* Inst_B */) 1
let SchedModel = SchedModel_B in {
def Write_B: SchedWriteRes<[]>;
def : InstRW<[Write_B], (instrs Inst_B)>;
}
// CHECK: SchedModel_CSchedClasses[] = {
-// CHECK: {DBGFIELD("Inst_A") 1
-// CHECK-NEXT: {DBGFIELD("Inst_B") 1
+// CHECK: {DBGFIELD(19 /* Inst_A */) 1
+// CHECK-NEXT: {DBGFIELD(26 /* Inst_B */) 1
let SchedModel = SchedModel_C in {
def Write_C: SchedWriteRes<[]>;
def : InstRW<[Write_C], (instrs Inst_A, Inst_B)>;
diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
index be10c32cf08d5..496f23b016a7e 100644
--- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -137,9 +137,9 @@ void Analysis::printInstructionRowCsv(const size_t PointId,
std::tie(SchedClassId, std::ignore) = ResolvedSchedClass::resolveSchedClassId(
State_.getSubtargetInfo(), State_.getInstrInfo(), MCI);
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- const MCSchedClassDesc *const SCDesc =
- State_.getSubtargetInfo().getSchedModel().getSchedClassDesc(SchedClassId);
- writeEscaped<kEscapeCsv>(OS, SCDesc->Name);
+ const MCSchedModel &SM = State_.getSubtargetInfo().getSchedModel();
+ const MCSchedClassDesc *const SCDesc = SM.getSchedClassDesc(SchedClassId);
+ writeEscaped<kEscapeCsv>(OS, SM.getSchedClassName(SCDesc));
#else
OS << SchedClassId;
#endif
@@ -563,7 +563,9 @@ Error Analysis::run<Analysis::PrintSchedClassInconsistencies>(
OS << "<div class=\"inconsistency\"><p>Sched Class <span "
"class=\"sched-class-name\">";
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- writeEscaped<kEscapeHtml>(OS, RSCAndPoints.RSC.SCDesc->Name);
+ const auto &SM = SI.getSchedModel();
+ writeEscaped<kEscapeHtml>(OS,
+ SM.getSchedClassName(RSCAndPoints.RSC.SCDesc));
#else
OS << RSCAndPoints.RSC.SchedClassId;
#endif
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 8d2fc99f84670..a454575e609e2 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -29,6 +29,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include <algorithm>
@@ -1430,6 +1431,7 @@ void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
OS << "}; // " << Target << "ReadAdvanceTable\n";
// Emit a SchedClass table for each processor.
+ StringToOffsetTable NameTable;
for (const auto &[Idx, Proc] : enumerate(SchedModels.procModels())) {
if (!Proc.hasInstrSchedModel())
continue;
@@ -1446,14 +1448,17 @@ void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
// name and position.
assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" &&
"invalid class not first");
- OS << " {DBGFIELD(\"InvalidSchedClass\") "
+ unsigned NameOffset = NameTable.GetOrAddStringOffset("InvalidSchedClass");
+ OS << " {DBGFIELD(" << NameOffset << " /* InvalidSchedClass */) "
<< MCSchedClassDesc::InvalidNumMicroOps
<< ", false, false, false, 0, 0, 0, 0, 0, 0},\n";
for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
MCSchedClassDesc &MCDesc = SCTab[SCIdx];
const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
- OS << " {DBGFIELD(\"" << SchedClass.Name << "\") ";
+ NameOffset = NameTable.GetOrAddStringOffset(SchedClass.Name);
+ OS << " {DBGFIELD(" << NameOffset << " /* " << SchedClass.Name
+ << " */) ";
if (SchedClass.Name.size() < 18)
OS.indent(18 - SchedClass.Name.size());
OS << MCDesc.NumMicroOps << ", " << (MCDesc.BeginGroup ? "true" : "false")
@@ -1467,6 +1472,7 @@ void SubtargetEmitter::emitSchedClassTables(SchedClassTables &SchedTables,
<< MCDesc.NumReadAdvanceEntries << "}, // #" << SCIdx << '\n';
}
OS << "}; // " << Proc.ModelName << "SchedClasses\n";
+ NameTable.EmitStringTableDef(OS, Proc.ModelName + "SchedClassNames");
}
}
@@ -1516,10 +1522,11 @@ void SubtargetEmitter::emitProcessorModels(raw_ostream &OS) {
if (PM.hasInstrSchedModel())
OS << " " << PM.ModelName << "ProcResources" << ",\n"
<< " " << PM.ModelName << "SchedClasses" << ",\n"
+ << " DBGFIELD(" << PM.ModelName << "SchedClassNames" << ")\n"
<< " " << PM.ProcResourceDefs.size() + 1 << ",\n"
<< " " << SchedModels.schedClasses().size() << ",\n";
else
- OS << " nullptr, nullptr, 0, 0,"
+ OS << " nullptr, nullptr, DBGFIELD(\"\") 0, 0,"
<< " // No instruction-level machine model.\n";
if (PM.hasItineraries())
OS << " " << PM.ItinsDef->getName() << ",\n";
@@ -1561,10 +1568,10 @@ void SubtargetEmitter::emitSchedModel(raw_ostream &OS) {
}
emitSchedClassTables(SchedTables, OS);
- OS << "\n#undef DBGFIELD\n";
-
// Emit the processor machine model
emitProcessorModels(OS);
+
+ OS << "\n#undef DBGFIELD\n";
}
static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) {
More information about the llvm-commits
mailing list