[llvm-branch-commits] [llvm] TableGen: Store super-register class sets as bit vectors (PR #234798)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Oct 22 16:46:30 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/234798
extendSuperRegClasses adds the super-register classes of each register
class's super-classes to its own, by merging their sets. The sets were
DenseSets, so most of the time went to hashing classes that were already
present.
Store the sets as bit vectors instead, so merging is a bitwise or. They
are indexed by a new CreationIndex, since EnumValue isn't assigned until
all classes have been inferred.
AMDGPU tablegen runs that build the register bank:
Gigainstructions Gigacycles CPU seconds
Before 700 435 135
After 622 (-11.1%) 381 (-12.5%) 120 (-11.2%)
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
>From a7ce27bd5825ea29a9ddf8974c19a63c5c619850 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 22 Oct 2026 10:34:38 -0700
Subject: [PATCH] TableGen: Store super-register class sets as bit vectors
extendSuperRegClasses adds the super-register classes of each register
class's super-classes to its own, by merging their sets. The sets were
DenseSets, so most of the time went to hashing classes that were already
present.
Store the sets as bit vectors instead, so merging is a bitwise or. They
are indexed by a new CreationIndex, since EnumValue isn't assigned until
all classes have been inferred.
AMDGPU tablegen runs that build the register bank:
Gigainstructions Gigacycles CPU seconds
Before 700 435 135
After 622 (-11.1%) 381 (-12.5%) 120 (-11.2%)
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
.../TableGen/Common/CodeGenRegisters.cpp | 32 ++++++++++++-------
llvm/utils/TableGen/Common/CodeGenRegisters.h | 29 ++++++++++++++---
llvm/utils/TableGen/RegisterInfoEmitter.cpp | 2 +-
3 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 0af3a5a3c7d3a..3b5451e0d32b5 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -1174,23 +1174,29 @@ bool CodeGenRegisterClass::hasAnySuperRegClasses(
bool CodeGenRegisterClass::hasSuperRegClass(
const CodeGenSubRegIndex *SubIdx, const CodeGenRegisterClass *RC) const {
auto FindI = SuperRegClasses.find(SubIdx);
+ if (FindI == SuperRegClasses.end())
+ return false;
- return FindI != SuperRegClasses.end() && FindI->second.contains(RC);
+ const BitVector &Supers = FindI->second;
+ return RC->CreationIndex < Supers.size() && Supers.test(RC->CreationIndex);
}
bool CodeGenRegisterClass::hasSuperRegClass(
const CodeGenRegisterClass *RC) const {
- return any_of(SuperRegClasses,
- [RC](const auto &Entry) { return Entry.second.contains(RC); });
+ return any_of(SuperRegClasses, [RC](const auto &Entry) {
+ const BitVector &Supers = Entry.second;
+ return RC->CreationIndex < Supers.size() && Supers.test(RC->CreationIndex);
+ });
}
void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
+ const CodeGenRegBank &RegBank,
BitVector &Out) const {
auto FindI = SuperRegClasses.find(SubIdx);
if (FindI == SuperRegClasses.end())
return;
- for (CodeGenRegisterClass *RC : FindI->second)
- Out.set(RC->EnumValue);
+ for (unsigned I : FindI->second.set_bits())
+ Out.set(RegBank.getRegClassByCreationIndex(I)->EnumValue);
}
// Populate a unique sorted list of units from a register set.
@@ -1211,21 +1217,21 @@ void CodeGenRegisterClass::buildRegUnitSet(
// Combine our super classes of the given sub-register index with all of their
// super classes in turn.
-void CodeGenRegisterClass::extendSuperRegClasses(CodeGenSubRegIndex *SubIdx) {
+void CodeGenRegisterClass::extendSuperRegClasses(
+ CodeGenSubRegIndex *SubIdx, const CodeGenRegBank &RegBank) {
auto It = SuperRegClasses.find(SubIdx);
if (It == SuperRegClasses.end())
return;
- SmallVector<CodeGenRegisterClass *> MidRCs;
- llvm::append_range(MidRCs, It->second);
-
- for (CodeGenRegisterClass *MidRC : MidRCs) {
+ BitVector MidRCs = It->second;
+ for (unsigned I : MidRCs.set_bits()) {
+ const CodeGenRegisterClass *MidRC = RegBank.getRegClassByCreationIndex(I);
for (auto &Pair : MidRC->SuperRegClasses) {
CodeGenSubRegIndex *ComposedSubIdx = Pair.first->compose(SubIdx);
if (!ComposedSubIdx)
continue;
- SuperRegClasses[ComposedSubIdx].insert_range(Pair.second);
+ SuperRegClasses[ComposedSubIdx] |= Pair.second;
}
}
}
@@ -1364,6 +1370,7 @@ CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
for (const Record *R : RCs) {
RegClasses.emplace_back(*this, R);
CodeGenRegisterClass &RC = RegClasses.back();
+ setCreationIndex(RC);
RegClassNames.insert(RC.getName());
if (!RC.Artificial)
addToMaps(&RC);
@@ -1442,6 +1449,7 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
// Sub-class doesn't exist, create a new one.
RegClasses.emplace_back(*this, Name, K);
+ setCreationIndex(RegClasses.back());
RegClassNames.insert(Name);
addToMaps(&RegClasses.back());
return {&RegClasses.back(), true};
@@ -2777,7 +2785,7 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
// pass.
for (CodeGenSubRegIndex *SubIdx : SubRegIndicesRPOT) {
for (CodeGenRegisterClass &SubRC : RegClasses)
- SubRC.extendSuperRegClasses(SubIdx);
+ SubRC.extendSuperRegClasses(SubIdx, *this);
}
Records.getTimer().stopTimer();
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h
index 6f30e517c758a..4b58b8d844169 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h
@@ -405,8 +405,8 @@ class CodeGenRegisterClass {
//
// R:SubRegIndex in this RC for all R in SuperRC.
//
- DenseMap<CodeGenSubRegIndex *, DenseSet<CodeGenRegisterClass *>>
- SuperRegClasses;
+ // The sets are indexed by CreationIndex.
+ DenseMap<CodeGenSubRegIndex *, BitVector> SuperRegClasses;
// Bit vector of TopoSigs for the registers with super registers in this
// class. This will be very sparse on regular architectures.
@@ -420,6 +420,9 @@ class CodeGenRegisterClass {
public:
unsigned EnumValue;
+ // Position in creation order, see CodeGenRegBank::getRegClassByCreationIndex.
+ // Unlike EnumValue, this is known while classes are being inferred.
+ unsigned CreationIndex = ~0u;
StringRef Namespace;
SmallVector<ValueTypeByHwMode, 4> VTs;
RegSizeInfoByHwMode RSI;
@@ -518,15 +521,19 @@ class CodeGenRegisterClass {
// getSuperRegClasses - Returns a bit vector of all register classes
// containing only SubIdx super-registers of this class.
void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
- BitVector &Out) const;
+ const CodeGenRegBank &RegBank, BitVector &Out) const;
// addSuperRegClass - Add a class containing only SubIdx super-registers.
void addSuperRegClass(CodeGenSubRegIndex *SubIdx,
CodeGenRegisterClass *SuperRC) {
- SuperRegClasses[SubIdx].insert(SuperRC);
+ BitVector &Supers = SuperRegClasses[SubIdx];
+ if (Supers.size() <= SuperRC->CreationIndex)
+ Supers.resize(SuperRC->CreationIndex + 1);
+ Supers.set(SuperRC->CreationIndex);
}
- void extendSuperRegClasses(CodeGenSubRegIndex *SubIdx);
+ void extendSuperRegClasses(CodeGenSubRegIndex *SubIdx,
+ const CodeGenRegBank &RegBank);
// getSubClasses - Returns a constant BitVector of subclasses indexed by
// EnumValue.
@@ -727,6 +734,8 @@ class CodeGenRegBank {
// Register classes.
std::list<CodeGenRegisterClass> RegClasses;
+ // RegClasses in creation order, indexed by CreationIndex.
+ std::vector<CodeGenRegisterClass *> RegClassesByCreationIndex;
StringSet<> RegClassNames;
DenseMap<const Record *, CodeGenRegisterClass *> Def2RC;
using RCKeyMap = std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass *>;
@@ -760,6 +769,12 @@ class CodeGenRegBank {
// Add RC to *2RC maps.
void addToMaps(CodeGenRegisterClass *);
+ // Set the CreationIndex of the newest register class.
+ void setCreationIndex(CodeGenRegisterClass &RC) {
+ RC.CreationIndex = RegClassesByCreationIndex.size();
+ RegClassesByCreationIndex.push_back(&RC);
+ }
+
// Create a synthetic sub-class if it is missing. Returns (RC, inserted).
std::pair<CodeGenRegisterClass *, bool>
getOrCreateSubClass(const CodeGenRegisterClass *RC,
@@ -901,6 +916,10 @@ class CodeGenRegBank {
return RegClasses;
}
+ CodeGenRegisterClass *getRegClassByCreationIndex(unsigned Idx) const {
+ return RegClassesByCreationIndex[Idx];
+ }
+
std::list<CodeGenRegisterCategory> &getRegCategories() {
return RegCategories;
}
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 05a7ff8b77c2d..9a3b78244f4ea 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1207,7 +1207,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
SmallVector<unsigned, 8> &MaskIndices = SuperRegMaskIndices[RC.EnumValue];
for (auto &Idx : SubRegIndices) {
MaskBV.reset();
- RC.getSuperRegClasses(&Idx, MaskBV);
+ RC.getSuperRegClasses(&Idx, RegBank, MaskBV);
if (MaskBV.none())
continue;
SRIList.push_back(&Idx);
More information about the llvm-branch-commits
mailing list