aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/DecoderEmitter.cpp
diff options
context:
space:
mode:
authorRahul Joshi <rjoshi@nvidia.com>2025-04-21 08:15:08 -0700
committerGitHub <noreply@github.com>2025-04-21 08:15:08 -0700
commite1bb7f6ddec37567230d3e46719aee5bcd268d5a (patch)
tree91fa11acfd1a9a0e871705ce2feb07e695085981 /llvm/utils/TableGen/DecoderEmitter.cpp
parentcfc2b0d094f705aa0995eff0dc5f1faf1440a769 (diff)
downloadllvm-e1bb7f6ddec37567230d3e46719aee5bcd268d5a.zip
llvm-e1bb7f6ddec37567230d3e46719aee5bcd268d5a.tar.gz
llvm-e1bb7f6ddec37567230d3e46719aee5bcd268d5a.tar.bz2
[LLVM][TableGen] Parameterize NumToSkip in DecoderEmitter (#136456)
- Add command line option `num-to-skip-size` to parameterize the size of `NumToSkip` bytes in the decoder table. Default value will be 2, and targets that need larger size can use 3. - Keep all existing targets, except AArch64, to use size 2, and change AArch64 to use size 3 since it run into the "disassembler decoding table too large" error with size 2. - Additional fixes on top of earlier revert: mark `decodeNumToSkip` as static (not necessary anymore as the generated code is now in anonymous namespace, but doing it for consistency) and incorporate Bazel build changes from https://github.com/llvm/llvm-project/pull/136212 - Following is a rough reduction in size for the decoder tables by switching to size 2. ``` Target Old Size New Size % Reduction ================================================ AArch64 153254 153254 0.00 AMDGPU 471566 412805 12.46 ARC 5724 5061 11.58 ARM 84936 73831 13.07 AVR 1497 1306 12.76 BPF 2172 1927 11.28 CSKY 10064 8692 13.63 Hexagon 47967 41965 12.51 Lanai 1108 982 11.37 LoongArch 24446 21621 11.56 MSP430 4200 3716 11.52 Mips 36330 31415 13.53 PPC 31897 28098 11.91 RISCV 37979 32790 13.66 Sparc 8331 7252 12.95 SystemZ 36722 32248 12.18 VE 48296 42873 11.23 XCore 2590 2316 10.58 Xtensa 3827 3316 13.35 ```
Diffstat (limited to 'llvm/utils/TableGen/DecoderEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/DecoderEmitter.cpp107
1 files changed, 57 insertions, 50 deletions
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 7d63126..ba36033 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -32,8 +32,10 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
@@ -76,6 +78,12 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates(
"significantly reducing Table Duplications")),
cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat));
+static cl::opt<bool> LargeTable(
+ "large-decoder-table",
+ cl::desc("Use large decoder table format. This uses 24 bits for offset\n"
+ "in the table instead of the default 16 bits."),
+ cl::init(false), cl::cat(DisassemblerEmitterCat));
+
STATISTIC(NumEncodings, "Number of encodings considered");
STATISTIC(NumEncodingsLackingDisasm,
"Number of encodings without disassembler info");
@@ -85,6 +93,8 @@ STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
namespace {
+unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
+
struct EncodingField {
unsigned Base, Width, Offset;
EncodingField(unsigned B, unsigned W, unsigned O)
@@ -130,10 +140,29 @@ struct DecoderTable : public std::vector<uint8_t> {
// in the table for patching.
size_t insertNumToSkip() {
size_t Size = size();
- insert(end(), 3, 0);
+ insert(end(), getNumToSkipInBytes(), 0);
return Size;
}
+
+ void patchNumToSkip(size_t FixupIdx, uint32_t DestIdx) {
+ // Calculate the distance from the byte following the fixup entry byte
+ // to the destination. The Target is calculated from after the
+ // `getNumToSkipInBytes()`-byte NumToSkip entry itself, so subtract
+ // `getNumToSkipInBytes()` from the displacement here to account for that.
+ assert(DestIdx >= FixupIdx + getNumToSkipInBytes() &&
+ "Expecting a forward jump in the decoding table");
+ uint32_t Delta = DestIdx - FixupIdx - getNumToSkipInBytes();
+ if (!isUIntN(8 * getNumToSkipInBytes(), Delta))
+ PrintFatalError(
+ "disassembler decoding table too large, try --large-decoder-table");
+
+ (*this)[FixupIdx] = static_cast<uint8_t>(Delta);
+ (*this)[FixupIdx + 1] = static_cast<uint8_t>(Delta >> 8);
+ if (getNumToSkipInBytes() == 3)
+ (*this)[FixupIdx + 2] = static_cast<uint8_t>(Delta >> 16);
+ }
};
+
struct DecoderTableInfo {
DecoderTable Table;
FixupScopeList FixupStack;
@@ -690,19 +719,8 @@ static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups,
uint32_t DestIdx) {
// Any NumToSkip fixups in the current scope can resolve to the
// current location.
- for (uint32_t FixupIdx : reverse(Fixups)) {
- // Calculate the distance from the byte following the fixup entry byte
- // to the destination. The Target is calculated from after the 24-bit
- // NumToSkip entry itself, so subtract three from the displacement here
- // to account for that.
- uint32_t Delta = DestIdx - FixupIdx - 3;
- // Our NumToSkip entries are 24-bits. Make sure our table isn't too
- // big.
- assert(isUInt<24>(Delta));
- Table[FixupIdx] = (uint8_t)Delta;
- Table[FixupIdx + 1] = (uint8_t)(Delta >> 8);
- Table[FixupIdx + 2] = (uint8_t)(Delta >> 16);
- }
+ for (uint32_t FixupIdx : Fixups)
+ Table.patchNumToSkip(FixupIdx, DestIdx);
}
// Emit table entries to decode instructions given a segment or segments
@@ -759,15 +777,9 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
Delegate->emitTableEntries(TableInfo);
// Now that we've emitted the body of the handler, update the NumToSkip
- // of the filter itself to be able to skip forward when false. Subtract
- // three as to account for the width of the NumToSkip field itself.
- if (PrevFilter) {
- uint32_t NumToSkip = Table.size() - PrevFilter - 3;
- assert(isUInt<24>(NumToSkip) && "disassembler decoding table too large!");
- Table[PrevFilter] = (uint8_t)NumToSkip;
- Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8);
- Table[PrevFilter + 2] = (uint8_t)(NumToSkip >> 16);
- }
+ // of the filter itself to be able to skip forward when false.
+ if (PrevFilter)
+ Table.patchNumToSkip(PrevFilter, Table.size());
}
// If there is no fallthrough, then the final filter should get fixed
@@ -814,7 +826,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << (unsigned)*I++ << ", ";
};
- // Emit 24-bit numtoskip value to OS, returning the NumToSkip value.
+ // Emit `getNumToSkipInBytes()`-byte numtoskip value to OS, returning the
+ // NumToSkip value.
auto emitNumToSkip = [](DecoderTable::const_iterator &I,
formatted_raw_ostream &OS) {
uint8_t Byte = *I++;
@@ -823,9 +836,11 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
Byte = *I++;
OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
- Byte = *I++;
- OS << (unsigned)(Byte) << ", ";
- NumToSkip |= Byte << 16;
+ if (getNumToSkipInBytes() == 3) {
+ Byte = *I++;
+ OS << (unsigned)(Byte) << ", ";
+ NumToSkip |= Byte << 16;
+ }
return NumToSkip;
};
@@ -866,7 +881,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// The filter value is ULEB128 encoded.
emitULEB128(I, OS);
- // 24-bit numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -881,7 +895,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// ULEB128 encoded field value.
emitULEB128(I, OS);
- // 24-bit numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -890,7 +903,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << Indent << "MCD::OPC_CheckPredicate, ";
emitULEB128(I, OS);
- // 24-bit numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -920,7 +932,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// Fallthrough for OPC_TryDecode.
- // 24-bit numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Opcode: " << NumberedEncodings[EncodingID]
@@ -1392,9 +1403,8 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
TableInfo.Table.push_back(NumBits);
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
- // The fixup is always 24-bits, so go ahead and allocate the space
- // in the table so all our relative position calculations work OK even
- // before we fully resolve the real value here.
+ // Allocate space in the table for fixup so all our relative position
+ // calculations work OK even before we fully resolve the real value here.
// Push location for NumToSkip backpatching.
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
@@ -2139,6 +2149,15 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits)
static void emitDecodeInstruction(formatted_raw_ostream &OS,
bool IsVarLenInst) {
OS << R"(
+static unsigned decodeNumToSkip(const uint8_t *&Ptr) {
+ unsigned NumToSkip = *Ptr++;
+ NumToSkip |= (*Ptr++) << 8;
+)";
+ if (getNumToSkipInBytes() == 3)
+ OS << " NumToSkip |= (*Ptr++) << 16;\n";
+ OS << R"( return NumToSkip;
+}
+
template <typename InsnType>
static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
InsnType insn, uint64_t Address,
@@ -2176,10 +2195,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
// Decode the field value.
uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
bool Failed = Val != CurFieldValue;
- // NumToSkip is a plain 24-bit integer.
- unsigned NumToSkip = *Ptr++;
- NumToSkip |= (*Ptr++) << 8;
- NumToSkip |= (*Ptr++) << 16;
+ unsigned NumToSkip = decodeNumToSkip(Ptr);
// Perform the filter operation.
if (Failed)
@@ -2203,10 +2219,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
Ptr += PtrLen;
bool Failed = ExpectedValue != FieldValue;
- // NumToSkip is a plain 24-bit integer.
- unsigned NumToSkip = *Ptr++;
- NumToSkip |= (*Ptr++) << 8;
- NumToSkip |= (*Ptr++) << 16;
+ unsigned NumToSkip = decodeNumToSkip(Ptr);
// If the actual and expected values don't match, skip.
if (Failed)
@@ -2221,10 +2234,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
case MCD::OPC_CheckPredicate: {
// Decode the Predicate Index value.
unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr);
- // NumToSkip is a plain 24-bit integer.
- unsigned NumToSkip = *Ptr++;
- NumToSkip |= (*Ptr++) << 8;
- NumToSkip |= (*Ptr++) << 16;
+ unsigned NumToSkip = decodeNumToSkip(Ptr);
// Check the predicate.
bool Failed = !checkDecoderPredicate(PIdx, Bits);
if (Failed)
@@ -2259,10 +2269,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
// Decode the Opcode value.
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
- // NumToSkip is a plain 24-bit integer.
- unsigned NumToSkip = *Ptr++;
- NumToSkip |= (*Ptr++) << 8;
- NumToSkip |= (*Ptr++) << 16;
+ unsigned NumToSkip = decodeNumToSkip(Ptr);
// Perform the decode operation.
MCInst TmpMI;