[llvm] [TableGen][DecoderEmitter] Calculate encoding bits once (NFC) (PR #154026)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 17 13:18:29 PDT 2025
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/154026
>From 988a3dd35e503cdcde9518fe17208c95639f980f Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 17 Aug 2025 21:37:39 +0300
Subject: [PATCH] [TableGen][DecoderEmitter] Calculate encoding bits once (NFC)
`insnWithID` is called multiple times for the same encoding ID.
Call it once and store the result in NumberedEncodings.
Also, give the method a more meaningful name.
---
llvm/utils/TableGen/DecoderEmitter.cpp | 65 +++++++++++++++-----------
1 file changed, 38 insertions(+), 27 deletions(-)
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index b6d4363c7e4d5..1aa7a35133217 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -209,6 +209,7 @@ struct EncodingAndInst {
const Record *EncodingDef;
const CodeGenInstruction *Inst;
StringRef HwModeName;
+ std::vector<struct BitValue> EncodingBits;
EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst,
StringRef HwModeName = "")
@@ -340,6 +341,26 @@ static const BitsInit &getBitsField(const Record &Def, StringRef FieldName) {
// Representation of the instruction to work on.
typedef std::vector<BitValue> insn_t;
+// Populates the insn given the uid.
+static insn_t getEncodingBits(const Record *EncodingDef, unsigned BitWidth) {
+ const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
+ insn_t Insn(std::max(BitWidth, Bits.getNumBits()), BitValue::BIT_UNSET);
+ // We may have a SoftFail bitmask, which specifies a mask where an encoding
+ // may differ from the value in "Inst" and yet still be valid, but the
+ // disassembler should return SoftFail instead of Success.
+ //
+ // This is used for marking UNPREDICTABLE instructions in the ARM world.
+ const RecordVal *RV = EncodingDef->getValue("SoftFail");
+ const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
+ for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
+ if (SFBits && BitValue(*SFBits, i) == BitValue::BIT_TRUE)
+ Insn[i] = BitValue::BIT_UNSET;
+ else
+ Insn[i] = BitValue(Bits, i);
+ }
+ return Insn;
+}
+
/// Extracts a NumBits long field from Insn, starting from StartBit.
/// Returns the value of the field if all bits are well-known,
/// otherwise std::nullopt.
@@ -542,28 +563,11 @@ class FilterChooser {
unsigned getBitWidth() const { return BitWidth; }
-protected:
- // Populates the insn given the uid.
- insn_t insnWithID(unsigned Opcode) const {
- const Record *EncodingDef = AllInstructions[Opcode].EncodingDef;
- const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
- insn_t Insn(std::max(BitWidth, Bits.getNumBits()), BitValue::BIT_UNSET);
- // We may have a SoftFail bitmask, which specifies a mask where an encoding
- // may differ from the value in "Inst" and yet still be valid, but the
- // disassembler should return SoftFail instead of Success.
- //
- // This is used for marking UNPREDICTABLE instructions in the ARM world.
- const RecordVal *RV = EncodingDef->getValue("SoftFail");
- const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
- for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
- if (SFBits && BitValue(*SFBits, i) == BitValue::BIT_TRUE)
- Insn[i] = BitValue::BIT_UNSET;
- else
- Insn[i] = BitValue(Bits, i);
- }
- return Insn;
+ ArrayRef<BitValue> getEncodingBits(unsigned EncodingID) const {
+ return AllInstructions[EncodingID].EncodingBits;
}
+protected:
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
void dumpFilterArray(raw_ostream &OS, ArrayRef<BitValue> Filter) const;
@@ -657,7 +661,7 @@ Filter::Filter(const FilterChooser &owner, unsigned startBit, unsigned numBits)
for (unsigned EncodingID : Owner.EncodingIDs) {
// Populates the insn given the uid.
- insn_t Insn = Owner.insnWithID(EncodingID);
+ ArrayRef<BitValue> Insn = Owner.getEncodingBits(EncodingID);
// Scans the segment for possibly well-specified encoding bits.
std::optional<uint64_t> Field = fieldFromInsn(Insn, StartBit, NumBits);
@@ -1409,7 +1413,7 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
// Emits table entries to decode the singleton.
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
unsigned EncodingID) const {
- insn_t Insn = insnWithID(EncodingID);
+ ArrayRef<BitValue> Insn = getEncodingBits(EncodingID);
// Look for islands of undecoded bits of the singleton.
std::vector<Island> Islands = getIslands(Insn);
@@ -1512,7 +1516,7 @@ bool FilterChooser::filterProcessor(ArrayRef<bitAttr_t> BitAttrs,
assert(EncodingIDs.size() == 3);
for (unsigned EncodingID : EncodingIDs) {
- insn_t Insn = insnWithID(EncodingID);
+ ArrayRef<BitValue> Insn = getEncodingBits(EncodingID);
// Look for islands of undecoded bits of any instruction.
std::vector<Island> Islands = getIslands(Insn);
@@ -1701,7 +1705,7 @@ void FilterChooser::doFilter() {
BitAttrs[BitIndex] = ATTR_FILTERED;
for (unsigned EncodingID : EncodingIDs) {
- insn_t EncodingBits = insnWithID(EncodingID);
+ ArrayRef<BitValue> EncodingBits = getEncodingBits(EncodingID);
for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
switch (BitAttrs[BitIndex]) {
@@ -2566,10 +2570,17 @@ namespace {
unsigned OpcodeMask = 0;
for (const auto &[NSAndByteSize, EncodingIDs] : EncMap) {
const std::string &DecoderNamespace = NSAndByteSize.first;
- const unsigned BitWidth = 8 * NSAndByteSize.second;
+ unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * NSAndByteSize.second;
+
+ // Populate encoding bits in this group of encodings.
+ for (unsigned EncodingID : EncodingIDs) {
+ EncodingAndInst &Enc = NumberedEncodings[EncodingID];
+ assert(Enc.EncodingBits.empty() && "Already populated?");
+ Enc.EncodingBits = getEncodingBits(Enc.EncodingDef, BitWidth);
+ }
+
// Emit the decoder for this namespace+width combination.
- FilterChooser FC(NumberedEncodings, EncodingIDs, Operands,
- IsVarLenInst ? MaxInstLen : BitWidth, this);
+ FilterChooser FC(NumberedEncodings, EncodingIDs, Operands, BitWidth, this);
// The decode table is cleared for each top level decoder function. The
// predicates and decoders themselves, however, are shared across all
More information about the llvm-commits
mailing list