[llvm] [LLVM][TableGen] Parameterize NumToSkip in DecoderEmitter (PR #136456)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 20 06:12:07 PDT 2025
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/136456
>From dda3726fc991d3978f14fe6e8b3af0bdda2a28b7 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Sat, 19 Apr 2025 12:33:53 -0700
Subject: [PATCH 1/2] Reapply "Reapply "[LLVM][TableGen] Parameterize NumToSkip
in DecoderEmitter" (#136017)" (#136068)
This reverts commit 6d8bf3cf3dcc5d85bec7b1e70a59a02cdfdaa1b4.
---
llvm/lib/Target/AArch64/CMakeLists.txt | 2 +-
llvm/test/TableGen/VarLenDecoder.td | 4 +-
llvm/test/TableGen/trydecode-emission.td | 10 +-
llvm/test/TableGen/trydecode-emission2.td | 16 +--
llvm/test/TableGen/trydecode-emission3.td | 2 +-
llvm/test/TableGen/trydecode-emission4.td | 2 +-
llvm/utils/TableGen/DecoderEmitter.cpp | 115 ++++++++++++----------
7 files changed, 83 insertions(+), 68 deletions(-)
diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt
index 2300e479bc110..ba1d1605ec104 100644
--- a/llvm/lib/Target/AArch64/CMakeLists.txt
+++ b/llvm/lib/Target/AArch64/CMakeLists.txt
@@ -7,7 +7,7 @@ tablegen(LLVM AArch64GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
-tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler)
+tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler --num-to-skip-size=3)
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner
diff --git a/llvm/test/TableGen/VarLenDecoder.td b/llvm/test/TableGen/VarLenDecoder.td
index 5cf0bf8911859..b77702ff7c5c1 100644
--- a/llvm/test/TableGen/VarLenDecoder.td
+++ b/llvm/test/TableGen/VarLenDecoder.td
@@ -47,9 +47,9 @@ def FOO32 : MyVarInst<MemOp32> {
}
// CHECK: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
-// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
+// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
-// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
+// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
// CHECK-NEXT: MCD::OPC_Fail,
diff --git a/llvm/test/TableGen/trydecode-emission.td b/llvm/test/TableGen/trydecode-emission.td
index 20d2446eeac7f..2b4239f4fbe65 100644
--- a/llvm/test/TableGen/trydecode-emission.td
+++ b/llvm/test/TableGen/trydecode-emission.td
@@ -34,10 +34,10 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
-// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
-// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
-// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
+// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
+// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
+// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission2.td b/llvm/test/TableGen/trydecode-emission2.td
index 0584034e41233..7d30474058f73 100644
--- a/llvm/test/TableGen/trydecode-emission2.td
+++ b/llvm/test/TableGen/trydecode-emission2.td
@@ -31,14 +31,14 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
-// CHECK-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
-// CHECK-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
-// CHECK-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
-// CHECK-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
-// CHECK-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
-// CHECK-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
-// CHECK-NEXT: /* 44 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 31, 0, // Skip to: 38
+// CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
+// CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 24, 0, // Skip to: 38
+// CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 26
+// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 26
+// CHECK-NEXT: /* 26 */ MCD::OPC_CheckField, 3, 2, 0, 6, 0, // Skip to: 38
+// CHECK-NEXT: /* 32 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, // Opcode: InstA, skip to: 38
+// CHECK-NEXT: /* 38 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission3.td b/llvm/test/TableGen/trydecode-emission3.td
index 4c5be7e1af229..0abbe62fe337e 100644
--- a/llvm/test/TableGen/trydecode-emission3.td
+++ b/llvm/test/TableGen/trydecode-emission3.td
@@ -1,4 +1,4 @@
-// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+ // RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
include "llvm/Target/Target.td"
diff --git a/llvm/test/TableGen/trydecode-emission4.td b/llvm/test/TableGen/trydecode-emission4.td
index 1e51ba5e40768..413e4a0d1275a 100644
--- a/llvm/test/TableGen/trydecode-emission4.td
+++ b/llvm/test/TableGen/trydecode-emission4.td
@@ -1,4 +1,4 @@
-// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
// Test for OPC_ExtractField/OPC_CheckField with start bit > 255.
// These large start values may arise for architectures with long instruction
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 7d63126f65ac4..f394bab44bd4e 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<uint32_t>
+ NumToSkipSizeInBytes("num-to-skip-size",
+ cl::desc("number of bytes to use for num-to-skip "
+ "entries in the decoder table (2 or 3)"),
+ cl::init(2), cl::cat(DisassemblerEmitterCat));
+
STATISTIC(NumEncodings, "Number of encodings considered");
STATISTIC(NumEncodingsLackingDisasm,
"Number of encodings without disassembler info");
@@ -130,10 +138,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(), NumToSkipSizeInBytes, 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
+ // `NumToSkipSizeInBytes`-byte NumToSkip entry itself, so subtract
+ // `NumToSkipSizeInBytes` from the displacement here to account for that.
+ assert(DestIdx >= FixupIdx + NumToSkipSizeInBytes &&
+ "Expecting a forward jump in the decoding table");
+ uint32_t Delta = DestIdx - FixupIdx - NumToSkipSizeInBytes;
+ if (!isUIntN(8 * NumToSkipSizeInBytes, Delta))
+ PrintFatalError(
+ "disassembler decoding table too large, try --num-to-skip-size=3");
+
+ (*this)[FixupIdx] = static_cast<uint8_t>(Delta);
+ (*this)[FixupIdx + 1] = static_cast<uint8_t>(Delta >> 8);
+ if (NumToSkipSizeInBytes == 3)
+ (*this)[FixupIdx + 2] = static_cast<uint8_t>(Delta >> 16);
+ }
};
+
struct DecoderTableInfo {
DecoderTable Table;
FixupScopeList FixupStack;
@@ -690,19 +717,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 +775,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 +824,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 `NumToSkipSizeInBytes`-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 +834,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 (NumToSkipSizeInBytes == 3) {
+ Byte = *I++;
+ OS << (unsigned)(Byte) << ", ";
+ NumToSkip |= Byte << 16;
+ }
return NumToSkip;
};
@@ -866,7 +879,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// The filter value is ULEB128 encoded.
emitULEB128(I, OS);
- // 24-bit numtoskip value.
+ // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -881,7 +894,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// ULEB128 encoded field value.
emitULEB128(I, OS);
- // 24-bit numtoskip value.
+ // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -890,7 +903,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << Indent << "MCD::OPC_CheckPredicate, ";
emitULEB128(I, OS);
- // 24-bit numtoskip value.
+ // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -920,7 +933,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// Fallthrough for OPC_TryDecode.
- // 24-bit numtoskip value.
+ // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Opcode: " << NumberedEncodings[EncodingID]
@@ -1392,9 +1405,9 @@ 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 (NumToSkipSizeInBytes) 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());
@@ -2138,7 +2151,18 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits)
// decodeInstruction().
static void emitDecodeInstruction(formatted_raw_ostream &OS,
bool IsVarLenInst) {
+ OS << formatv("\nconstexpr unsigned NumToSkipSizeInBytes = {};\n",
+ NumToSkipSizeInBytes);
+
OS << R"(
+inline unsigned decodeNumToSkip(const uint8_t *&Ptr) {
+ unsigned NumToSkip = *Ptr++;
+ NumToSkip |= (*Ptr++) << 8;
+ if constexpr (NumToSkipSizeInBytes == 3)
+ NumToSkip |= (*Ptr++) << 16;
+ return NumToSkip;
+}
+
template <typename InsnType>
static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
InsnType insn, uint64_t Address,
@@ -2176,10 +2200,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 +2224,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 +2239,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 +2274,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;
@@ -2387,6 +2399,9 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr,
// Emits disassembler code for instruction decoding.
void DecoderEmitter::run(raw_ostream &o) {
+ if (NumToSkipSizeInBytes != 2 && NumToSkipSizeInBytes != 3)
+ PrintFatalError("Invalid value for num-to-skip-size, must be 2 or 3");
+
formatted_raw_ostream OS(o);
OS << R"(
#include "llvm/MC/MCInst.h"
>From a82cfbd132ebd01adb72487c0529edf7c44fddd8 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Sat, 19 Apr 2025 12:36:09 -0700
Subject: [PATCH 2/2] Fixes
---
llvm/lib/Target/AArch64/CMakeLists.txt | 3 +-
llvm/test/TableGen/VarLenDecoder.td | 22 +++++---
llvm/test/TableGen/trydecode-emission.td | 19 +++++++
llvm/test/TableGen/trydecode-emission2.td | 14 +++++
llvm/test/TableGen/trydecode-emission3.td | 22 ++++++--
llvm/test/TableGen/trydecode-emission4.td | 24 +++++---
llvm/utils/TableGen/DecoderEmitter.cpp | 56 ++++++++-----------
.../llvm-project-overlay/llvm/BUILD.bazel | 2 +-
8 files changed, 108 insertions(+), 54 deletions(-)
diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt
index ba1d1605ec104..583003f2f46e6 100644
--- a/llvm/lib/Target/AArch64/CMakeLists.txt
+++ b/llvm/lib/Target/AArch64/CMakeLists.txt
@@ -7,7 +7,8 @@ tablegen(LLVM AArch64GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
-tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler --num-to-skip-size=3)
+tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler
+ --large-decoder-table)
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner
diff --git a/llvm/test/TableGen/VarLenDecoder.td b/llvm/test/TableGen/VarLenDecoder.td
index b77702ff7c5c1..0ca5c6ce53506 100644
--- a/llvm/test/TableGen/VarLenDecoder.td
+++ b/llvm/test/TableGen/VarLenDecoder.td
@@ -1,4 +1,5 @@
-// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s --check-prefixes=CHECK,CHECK-SMALL
+// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../include %s | FileCheck %s --check-prefixes=CHECK,CHECK-LARGE
include "llvm/Target/Target.td"
@@ -46,12 +47,19 @@ def FOO32 : MyVarInst<MemOp32> {
);
}
-// CHECK: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
-// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
-// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
-// CHECK-NEXT: MCD::OPC_Fail,
+// CHECK-SMALL: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
+// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
+// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
+// CHECK-SMALL-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
+// CHECK-SMALL-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
+// CHECK-SMALL-NEXT: MCD::OPC_Fail,
+
+// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_Decode, 178, 2, 0, // Opcode: FOO16
+// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
+// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_Decode, 179, 2, 1, // Opcode: FOO32
+// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Fail,
// Instruction length table
// CHECK: 27,
diff --git a/llvm/test/TableGen/trydecode-emission.td b/llvm/test/TableGen/trydecode-emission.td
index 2b4239f4fbe65..ebd7169b96f3d 100644
--- a/llvm/test/TableGen/trydecode-emission.td
+++ b/llvm/test/TableGen/trydecode-emission.td
@@ -1,4 +1,5 @@
// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
// Check that if decoding of an instruction fails and the instruction does not
// have a complete decoder method that can determine if the bitpattern is valid
@@ -41,3 +42,21 @@ def InstB : TestInstruction {
// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
+// CHECK: unsigned NumToSkip = *Ptr++;
+// CHECK-NEXT: NumToSkip |= (*Ptr++) << 8;
+// CHECK-NEXT: return NumToSkip;
+
+// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
+// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, 179, 2, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
+// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, 178, 2, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
+
+// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
+// CHECK-LARGE: unsigned NumToSkip = *Ptr++;
+// CHECK-LARGE-NEXT: NumToSkip |= (*Ptr++) << 8;
+// CHECK-LARGE-NEXT: NumToSkip |= (*Ptr++) << 16;
+// CHECK-LARGE-NEXT: return NumToSkip;
diff --git a/llvm/test/TableGen/trydecode-emission2.td b/llvm/test/TableGen/trydecode-emission2.td
index 7d30474058f73..f455c6345f40c 100644
--- a/llvm/test/TableGen/trydecode-emission2.td
+++ b/llvm/test/TableGen/trydecode-emission2.td
@@ -1,4 +1,5 @@
// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
include "llvm/Target/Target.td"
@@ -42,3 +43,16 @@ def InstB : TestInstruction {
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
+// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
+// CHECK-LARGE-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
+// CHECK-LARGE-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
+// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_TryDecode, 179, 2, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
+// CHECK-LARGE-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
+// CHECK-LARGE-NEXT: /* 37 */ MCD::OPC_TryDecode, 178, 2, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
+// CHECK-LARGE-NEXT: /* 44 */ MCD::OPC_Fail,
+
+// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+// CHECK-LARGE: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission3.td b/llvm/test/TableGen/trydecode-emission3.td
index 0abbe62fe337e..acd61a14b89c5 100644
--- a/llvm/test/TableGen/trydecode-emission3.td
+++ b/llvm/test/TableGen/trydecode-emission3.td
@@ -1,4 +1,5 @@
- // RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
include "llvm/Target/Target.td"
@@ -35,10 +36,19 @@ def InstB : TestInstruction {
}
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
-// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
-// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
-// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
-// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
+// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
+// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 179, 2, 0, 0, 0, // Opcode: InstB, skip to: 19
+// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, 178, 2, 1, // Opcode: InstA
+// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
+// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
+// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
+// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
+// CHECK-LARGE-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
+// CHECK-LARGE-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 26 */ MCD::OPC_Fail,
+
+// CHECK-LARGE: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
diff --git a/llvm/test/TableGen/trydecode-emission4.td b/llvm/test/TableGen/trydecode-emission4.td
index 413e4a0d1275a..57eec0fa139d5 100644
--- a/llvm/test/TableGen/trydecode-emission4.td
+++ b/llvm/test/TableGen/trydecode-emission4.td
@@ -1,4 +1,5 @@
-// RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
+// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
// Test for OPC_ExtractField/OPC_CheckField with start bit > 255.
// These large start values may arise for architectures with long instruction
@@ -32,13 +33,22 @@ def InstB : TestInstruction {
let hasCompleteDecoder = 0;
}
-
// CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
-// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 19, 0, 0, // Skip to: 28
-// CHECK-NEXT: /* 9 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 24
-// CHECK-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 24
-// CHECK-NEXT: /* 24 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
-// CHECK-NEXT: /* 28 */ MCD::OPC_Fail,
+// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 17, 0, // Skip to: 25
+// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 21
+// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, 179, 2, 0, 0, 0, // Opcode: InstB, skip to: 21
+// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, 178, 2, 1, // Opcode: InstA
+// CHECK-NEXT: /* 25 */ MCD::OPC_Fail,
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
+// CHECK-LARGE: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ...
+// CHECK-LARGE-NEXT: /* 4 */ MCD::OPC_FilterValue, 0, 19, 0, 0, // Skip to: 28
+// CHECK-LARGE-NEXT: /* 9 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 24
+// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 24
+// CHECK-LARGE-NEXT: /* 24 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_Fail,
+
+// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
+
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index f394bab44bd4e..ba360333f86e5 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -78,11 +78,11 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates(
"significantly reducing Table Duplications")),
cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat));
-static cl::opt<uint32_t>
- NumToSkipSizeInBytes("num-to-skip-size",
- cl::desc("number of bytes to use for num-to-skip "
- "entries in the decoder table (2 or 3)"),
- cl::init(2), 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,
@@ -93,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)
@@ -138,25 +140,25 @@ struct DecoderTable : public std::vector<uint8_t> {
// in the table for patching.
size_t insertNumToSkip() {
size_t Size = size();
- insert(end(), NumToSkipSizeInBytes, 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
- // `NumToSkipSizeInBytes`-byte NumToSkip entry itself, so subtract
- // `NumToSkipSizeInBytes` from the displacement here to account for that.
- assert(DestIdx >= FixupIdx + NumToSkipSizeInBytes &&
+ // `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 - NumToSkipSizeInBytes;
- if (!isUIntN(8 * NumToSkipSizeInBytes, Delta))
+ uint32_t Delta = DestIdx - FixupIdx - getNumToSkipInBytes();
+ if (!isUIntN(8 * getNumToSkipInBytes(), Delta))
PrintFatalError(
- "disassembler decoding table too large, try --num-to-skip-size=3");
+ "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 (NumToSkipSizeInBytes == 3)
+ if (getNumToSkipInBytes() == 3)
(*this)[FixupIdx + 2] = static_cast<uint8_t>(Delta >> 16);
}
};
@@ -824,7 +826,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << (unsigned)*I++ << ", ";
};
- // Emit `NumToSkipSizeInBytes`-byte numtoskip value to OS, returning the
+ // Emit `getNumToSkipInBytes()`-byte numtoskip value to OS, returning the
// NumToSkip value.
auto emitNumToSkip = [](DecoderTable::const_iterator &I,
formatted_raw_ostream &OS) {
@@ -834,7 +836,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
Byte = *I++;
OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
- if (NumToSkipSizeInBytes == 3) {
+ if (getNumToSkipInBytes() == 3) {
Byte = *I++;
OS << (unsigned)(Byte) << ", ";
NumToSkip |= Byte << 16;
@@ -879,7 +881,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// The filter value is ULEB128 encoded.
emitULEB128(I, OS);
- // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -894,7 +895,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// ULEB128 encoded field value.
emitULEB128(I, OS);
- // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -903,7 +903,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << Indent << "MCD::OPC_CheckPredicate, ";
emitULEB128(I, OS);
- // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -933,7 +932,6 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
// Fallthrough for OPC_TryDecode.
- // numtoskip value.
uint32_t NumToSkip = emitNumToSkip(I, OS);
OS << "// Opcode: " << NumberedEncodings[EncodingID]
@@ -1405,9 +1403,8 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
TableInfo.Table.push_back(NumBits);
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
- // Allocate space in the table for fixup (NumToSkipSizeInBytes) 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());
@@ -2151,16 +2148,14 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits)
// decodeInstruction().
static void emitDecodeInstruction(formatted_raw_ostream &OS,
bool IsVarLenInst) {
- OS << formatv("\nconstexpr unsigned NumToSkipSizeInBytes = {};\n",
- NumToSkipSizeInBytes);
-
OS << R"(
-inline unsigned decodeNumToSkip(const uint8_t *&Ptr) {
+static unsigned decodeNumToSkip(const uint8_t *&Ptr) {
unsigned NumToSkip = *Ptr++;
NumToSkip |= (*Ptr++) << 8;
- if constexpr (NumToSkipSizeInBytes == 3)
- NumToSkip |= (*Ptr++) << 16;
- return NumToSkip;
+)";
+ if (getNumToSkipInBytes() == 3)
+ OS << " NumToSkip |= (*Ptr++) << 16;\n";
+ OS << R"( return NumToSkip;
}
template <typename InsnType>
@@ -2399,9 +2394,6 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr,
// Emits disassembler code for instruction decoding.
void DecoderEmitter::run(raw_ostream &o) {
- if (NumToSkipSizeInBytes != 2 && NumToSkipSizeInBytes != 3)
- PrintFatalError("Invalid value for num-to-skip-size, must be 2 or 3");
-
formatted_raw_ostream OS(o);
OS << R"(
#include "llvm/MC/MCInst.h"
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index b77ddf634eec6..b03dbff10cf5e 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -2148,7 +2148,7 @@ llvm_target_lib_list = [lib for lib in [
"lib/Target/AArch64/AArch64GenSubtargetInfo.inc",
),
(
- ["-gen-disassembler"],
+ ["-gen-disassembler", "--large-decoder-table"],
"lib/Target/AArch64/AArch64GenDisassemblerTables.inc",
),
(
More information about the llvm-commits
mailing list