[llvm] [MC][NFC] Store RegBitSet more compact (PR #218701)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 07:53:23 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-mc
Author: Alexis Engelke (aengelke)
<details>
<summary>Changes</summary>
Most register bit sets have their first register at a large offset,
causing a lot of 0 bytes to be stored in the RegBitSets. Avoid this by
storing the number of the lowest register in the MCRegisterClass. This
substantially reduces the size of the bit sets:
- AArch64: 35010 -> 1356
- AMDGPU: 1500754 -> 118320
- PowerPC: 2202 -> 610
- RISCV: 5700 -> 429
- X86: 2329 -> 927
This also opens up deduplication potential for the future -- in addition
to duplicates, a common pattern is a streak of the first N bits. To ease
future deduplication, store the maximum register offset instead of the
bitset size in bytes (so the bitset 0xff,0xff could absorb the bitsets
0xff,0x3f and 0x01).
---
Full diff: https://github.com/llvm/llvm-project/pull/218701.diff
3 Files Affected:
- (modified) llvm/include/llvm/MC/MCRegisterInfo.h (+6-4)
- (modified) llvm/unittests/CodeGen/MachineInstrTest.cpp (+1-1)
- (modified) llvm/utils/TableGen/RegisterInfoEmitter.cpp (+20-10)
``````````diff
diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h
index 9b894f5b6bf37..76c72bb08007d 100644
--- a/llvm/include/llvm/MC/MCRegisterInfo.h
+++ b/llvm/include/llvm/MC/MCRegisterInfo.h
@@ -45,6 +45,8 @@ class MCRegisterClass {
const uint32_t NameIdx;
const uint32_t RegSizeInBits;
const uint16_t RegsSize;
+ /// Register denoted by first bit in RegSet.
+ const MCPhysReg RegSetBegin;
const uint16_t RegSetSize;
const uint16_t ID;
const uint8_t CopyCost;
@@ -102,11 +104,11 @@ class MCRegisterClass {
/// contains - Return true if the specified register is included in this
/// register class. This does not include virtual registers.
bool contains(MCRegister Reg) const {
- unsigned RegNo = Reg.id();
- unsigned InByte = RegNo % 8;
- unsigned Byte = RegNo / 8;
- if (Byte >= RegSetSize)
+ unsigned RegSetIdx = Reg.id() - RegSetBegin;
+ if (RegSetIdx >= RegSetSize)
return false;
+ unsigned InByte = RegSetIdx % 8;
+ unsigned Byte = RegSetIdx / 8;
const uint8_t *RegSet = reinterpret_cast<const uint8_t *>(this) + RegSetOff;
return (RegSet[Byte] & (1 << InByte)) != 0;
}
diff --git a/llvm/unittests/CodeGen/MachineInstrTest.cpp b/llvm/unittests/CodeGen/MachineInstrTest.cpp
index 03f4077ea55ac..8ac5ad175a3b5 100644
--- a/llvm/unittests/CodeGen/MachineInstrTest.cpp
+++ b/llvm/unittests/CodeGen/MachineInstrTest.cpp
@@ -593,7 +593,7 @@ TEST(MachineInstrTest, SpliceOperands) {
// test tied operands
MCRegisterClass RC{
- 0, 0, 0, 0, 0, 0, 0, 0, /*Allocatable=*/true, /*BaseClass=*/true,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, /*Allocatable=*/true, /*BaseClass=*/true,
0, 0, {}, 0, 0, 0, 0, 0, 0, 0, 0};
// MachineRegisterInfo will be very upset if these registers aren't
// allocatable.
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 6c64330c1f374..c57345d020708 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1145,10 +1145,13 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
unsigned BitSetIdx;
unsigned SubClassMaskIdx;
unsigned SuperClassIdx;
+ // Not strictly an index, but to avoid recomputation: cache reg set range.
+ unsigned MinRegVal;
+ unsigned RegSetSize;
};
SmallVector<StartIndex> StartIndices;
StartIndices.reserve(RegisterClasses.size() + 1);
- StartIndices.push_back(StartIndex{0, 0, 0, 0});
+ StartIndices.push_back(StartIndex{0, 0, 0, 0, 0, 0});
// For compressing the sub-reg index lists.
using IdxList = std::vector<const CodeGenSubRegIndex *>;
@@ -1159,9 +1162,11 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
ArrayRef<const Record *> Order = RC.getOrder();
RegClassStrings.add(RC.getName());
- unsigned MaxRegVal = 0;
- for (const Record *Reg : Order)
+ unsigned MinRegVal = UINT_MAX, MaxRegVal = 0;
+ for (const Record *Reg : Order) {
+ MinRegVal = std::min(MinRegVal, RegBank.getReg(Reg)->EnumValue);
MaxRegVal = std::max(MaxRegVal, RegBank.getReg(Reg)->EnumValue);
+ }
unsigned SubClassMaskSize = (RC.getSubClasses().size() + 31) / 32;
IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
@@ -1175,13 +1180,18 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
}
SuperRegIdxSeqs.add(SRIList);
- const auto &Last = StartIndices.back();
+ auto &Last = StartIndices.back();
+ Last.MinRegVal = Order.empty() ? 0 : MinRegVal;
+ Last.RegSetSize = Order.empty() ? 0 : MaxRegVal - MinRegVal + 1;
StartIndices.push_back(StartIndex{
Last.RegIdx + unsigned(Order.size()),
// Round to next byte size.
- Last.BitSetIdx + (Order.empty() ? 0 : (MaxRegVal / 8) + 1),
+ Last.BitSetIdx +
+ (Order.empty() ? 0 : ((MaxRegVal - MinRegVal) / 8) + 1),
Last.SubClassMaskIdx + SubClassMaskSize,
Last.SuperClassIdx + unsigned(RC.getSuperClasses().size()),
+ 0, // MinRegVal for next RegClass.
+ 0, // RegSetSize for next RegClass.
});
}
@@ -1219,13 +1229,13 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
.str();
};
- unsigned BitSetSize =
- StartIndices[It.index() + 1].BitSetIdx - RCIndices.BitSetIdx;
OS << " {\n " << GetOff("Regs", RCIndices.RegIdx) << ",\n "
<< GetOff("BitSets", RCIndices.BitSetIdx) << ",\n "
<< RegClassStrings.get(RC.getName()) << ",\n " << RegSize
- << ",\n " << RC.getOrder().size() << ",\n " << BitSetSize
- << ",\n " << RC.getQualifiedIdName() << ",\n "
+ << ",\n " << RC.getOrder().size() << ",\n "
+ << RCIndices.MinRegVal << ", /* MinRegVal */\n "
+ << RCIndices.RegSetSize << ", /* RegSetSize */\n "
+ << RC.getQualifiedIdName() << ",\n "
<< static_cast<unsigned>(RC.CopyCost) << ", /* CopyCost */\n "
<< (RC.Allocatable ? "true" : "false") << ", /* Allocatable */\n "
<< (RC.getBaseClassOrder() ? "true" : "false") << ",\n "
@@ -1269,7 +1279,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
OS << " /* " << StartIndices[Idx].BitSetIdx << " */ ";
BitVectorEmitter BVE;
for (const Record *Reg : Order)
- BVE.add(RegBank.getReg(Reg)->EnumValue);
+ BVE.add(RegBank.getReg(Reg)->EnumValue - StartIndices[Idx].MinRegVal);
BVE.print(OS);
OS << "\n";
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/218701
More information about the llvm-commits
mailing list