Skip to content

Commit 8d709a0

Browse files
committed
[LLVM][TableGen] Paramaterize NumToSkip in DecoderEmitter.
- 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. - 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
1 parent 6cfec29 commit 8d709a0

File tree

7 files changed

+79
-62
lines changed

7 files changed

+79
-62
lines changed

llvm/lib/Target/AArch64/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tablegen(LLVM AArch64GenAsmWriter.inc -gen-asm-writer)
77
tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1)
88
tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv)
99
tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel)
10-
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler)
10+
tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler --num-to-skip-size=3)
1111
tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel)
1212
tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel)
1313
tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner

llvm/test/TableGen/VarLenDecoder.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ def FOO32 : MyVarInst<MemOp32> {
4747
}
4848

4949
// CHECK: MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ...
50-
// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
50+
// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11
5151
// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
52-
// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
52+
// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, // Skip to: 19
5353
// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
5454
// CHECK-NEXT: MCD::OPC_Fail,
5555

llvm/test/TableGen/trydecode-emission.td

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ def InstB : TestInstruction {
3434
}
3535

3636
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
37-
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
38-
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
39-
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
40-
// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
41-
// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
37+
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, // Skip to: 23
38+
// CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 19
39+
// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 19
40+
// CHECK-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
41+
// CHECK-NEXT: /* 23 */ MCD::OPC_Fail,
4242

4343
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

llvm/test/TableGen/trydecode-emission2.td

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ def InstB : TestInstruction {
3131
}
3232

3333
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
34-
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
35-
// CHECK-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
36-
// CHECK-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
37-
// CHECK-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
38-
// CHECK-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
39-
// CHECK-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
40-
// CHECK-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
41-
// CHECK-NEXT: /* 44 */ MCD::OPC_Fail,
34+
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 31, 0, // Skip to: 38
35+
// CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
36+
// CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 24, 0, // Skip to: 38
37+
// CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 26
38+
// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 26
39+
// CHECK-NEXT: /* 26 */ MCD::OPC_CheckField, 3, 2, 0, 6, 0, // Skip to: 38
40+
// CHECK-NEXT: /* 32 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, // Opcode: InstA, skip to: 38
41+
// CHECK-NEXT: /* 38 */ MCD::OPC_Fail,
4242

4343
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4444
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

llvm/test/TableGen/trydecode-emission3.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
1+
// RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
22

33
include "llvm/Target/Target.td"
44

llvm/test/TableGen/trydecode-emission4.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
1+
// RUN: llvm-tblgen -gen-disassembler --num-to-skip-size=3 -I %p/../../include %s | FileCheck %s
22

33
// Test for OPC_ExtractField/OPC_CheckField with start bit > 255.
44
// These large start values may arise for architectures with long instruction

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
#include "llvm/Support/CommandLine.h"
3333
#include "llvm/Support/Debug.h"
3434
#include "llvm/Support/ErrorHandling.h"
35+
#include "llvm/Support/FormatVariadic.h"
3536
#include "llvm/Support/FormattedStream.h"
3637
#include "llvm/Support/LEB128.h"
38+
#include "llvm/Support/MathExtras.h"
3739
#include "llvm/Support/raw_ostream.h"
3840
#include "llvm/TableGen/Error.h"
3941
#include "llvm/TableGen/Record.h"
@@ -76,6 +78,12 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates(
7678
"significantly reducing Table Duplications")),
7779
cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat));
7880

81+
static cl::opt<uint32_t>
82+
NumToSkipSizeInBytes("num-to-skip-size",
83+
cl::desc("number of bytes to use for num-to-skip "
84+
"entries in the decoder table (2 or 3)"),
85+
cl::init(2), cl::cat(DisassemblerEmitterCat));
86+
7987
STATISTIC(NumEncodings, "Number of encodings considered");
8088
STATISTIC(NumEncodingsLackingDisasm,
8189
"Number of encodings without disassembler info");
@@ -130,9 +138,20 @@ struct DecoderTable : public std::vector<uint8_t> {
130138
// in the table for patching.
131139
size_t insertNumToSkip() {
132140
size_t Size = size();
133-
insert(end(), 3, 0);
141+
insert(end(), NumToSkipSizeInBytes, 0);
134142
return Size;
135143
}
144+
145+
void patchNumToSkip(size_t FixupIdx, uint32_t Value) {
146+
if (!isUIntN(8 * NumToSkipSizeInBytes, Value))
147+
PrintFatalError(
148+
"disassembler decoding table too large, try --num-to-skip-size=3");
149+
150+
(*this)[FixupIdx] = static_cast<uint8_t>(Value);
151+
(*this)[FixupIdx + 1] = static_cast<uint8_t>(Value >> 8);
152+
if (NumToSkipSizeInBytes == 3)
153+
(*this)[FixupIdx + 2] = static_cast<uint8_t>(Value >> 16);
154+
}
136155
};
137156
struct DecoderTableInfo {
138157
DecoderTable Table;
@@ -692,16 +711,11 @@ static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups,
692711
// current location.
693712
for (uint32_t FixupIdx : reverse(Fixups)) {
694713
// Calculate the distance from the byte following the fixup entry byte
695-
// to the destination. The Target is calculated from after the 24-bit
696-
// NumToSkip entry itself, so subtract three from the displacement here
697-
// to account for that.
698-
uint32_t Delta = DestIdx - FixupIdx - 3;
699-
// Our NumToSkip entries are 24-bits. Make sure our table isn't too
700-
// big.
701-
assert(isUInt<24>(Delta));
702-
Table[FixupIdx] = (uint8_t)Delta;
703-
Table[FixupIdx + 1] = (uint8_t)(Delta >> 8);
704-
Table[FixupIdx + 2] = (uint8_t)(Delta >> 16);
714+
// to the destination. The Target is calculated from after the
715+
// `NumToSkipSizeInBytes`-byte NumToSkip entry itself, so subtract
716+
// `NumToSkipSizeInBytes` from the displacement here to account for that.
717+
uint32_t Delta = DestIdx - FixupIdx - NumToSkipSizeInBytes;
718+
Table.patchNumToSkip(FixupIdx, Delta);
705719
}
706720
}
707721

@@ -760,13 +774,11 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
760774

761775
// Now that we've emitted the body of the handler, update the NumToSkip
762776
// of the filter itself to be able to skip forward when false. Subtract
763-
// three as to account for the width of the NumToSkip field itself.
777+
// `NumToSkipSizeInBytes` as to account for the width of the NumToSkip
778+
// field itself.
764779
if (PrevFilter) {
765-
uint32_t NumToSkip = Table.size() - PrevFilter - 3;
766-
assert(isUInt<24>(NumToSkip) && "disassembler decoding table too large!");
767-
Table[PrevFilter] = (uint8_t)NumToSkip;
768-
Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8);
769-
Table[PrevFilter + 2] = (uint8_t)(NumToSkip >> 16);
780+
uint32_t NumToSkip = Table.size() - PrevFilter - NumToSkipSizeInBytes;
781+
Table.patchNumToSkip(PrevFilter, NumToSkip);
770782
}
771783
}
772784

@@ -814,7 +826,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
814826
OS << (unsigned)*I++ << ", ";
815827
};
816828

817-
// Emit 24-bit numtoskip value to OS, returning the NumToSkip value.
829+
// Emit `NumToSkipSizeInBytes`-byte numtoskip value to OS, returning the
830+
// NumToSkip value.
818831
auto emitNumToSkip = [](DecoderTable::const_iterator &I,
819832
formatted_raw_ostream &OS) {
820833
uint8_t Byte = *I++;
@@ -823,9 +836,11 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
823836
Byte = *I++;
824837
OS << (unsigned)Byte << ", ";
825838
NumToSkip |= Byte << 8;
826-
Byte = *I++;
827-
OS << (unsigned)(Byte) << ", ";
828-
NumToSkip |= Byte << 16;
839+
if (NumToSkipSizeInBytes == 3) {
840+
Byte = *I++;
841+
OS << (unsigned)(Byte) << ", ";
842+
NumToSkip |= Byte << 16;
843+
}
829844
return NumToSkip;
830845
};
831846

@@ -867,7 +882,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
867882
// The filter value is ULEB128 encoded.
868883
emitULEB128(I, OS);
869884

870-
// 24-bit numtoskip value.
885+
// numtoskip value.
871886
uint32_t NumToSkip = emitNumToSkip(I, OS);
872887
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
873888
break;
@@ -883,7 +898,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
883898
// ULEB128 encoded field value.
884899
emitULEB128(I, OS);
885900

886-
// 24-bit numtoskip value.
901+
// numtoskip value.
887902
uint32_t NumToSkip = emitNumToSkip(I, OS);
888903
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
889904
break;
@@ -893,7 +908,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
893908
OS << Indent << "MCD::OPC_CheckPredicate, ";
894909
emitULEB128(I, OS);
895910

896-
// 24-bit numtoskip value.
911+
// numtoskip value.
897912
uint32_t NumToSkip = emitNumToSkip(I, OS);
898913
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
899914
break;
@@ -925,7 +940,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
925940

926941
// Fallthrough for OPC_TryDecode.
927942

928-
// 24-bit numtoskip value.
943+
// numtoskip value.
929944
uint32_t NumToSkip = emitNumToSkip(I, OS);
930945

931946
OS << "// Opcode: " << NumberedEncodings[EncodingID]
@@ -1411,9 +1426,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14111426
TableInfo.Table.push_back(NumBits);
14121427
TableInfo.Table.insertULEB128(Ilnd.FieldVal);
14131428

1414-
// The fixup is always 24-bits, so go ahead and allocate the space
1415-
// in the table so all our relative position calculations work OK even
1416-
// before we fully resolve the real value here.
1429+
// Allocate space in the table for fixup (NumToSkipSizeInBytes) so all
1430+
// our relative position calculations work OK even before we fully
1431+
// resolve the real value here.
14171432

14181433
// Push location for NumToSkip backpatching.
14191434
TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
@@ -2157,7 +2172,18 @@ insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits)
21572172
// decodeInstruction().
21582173
static void emitDecodeInstruction(formatted_raw_ostream &OS,
21592174
bool IsVarLenInst) {
2175+
OS << formatv("\nconstexpr unsigned NumToSkipSizeInBytes = {};\n",
2176+
NumToSkipSizeInBytes);
2177+
21602178
OS << R"(
2179+
inline unsigned decodeNumToSkip(const uint8_t *&Ptr) {
2180+
unsigned NumToSkip = *Ptr++;
2181+
NumToSkip |= (*Ptr++) << 8;
2182+
if constexpr (NumToSkipSizeInBytes == 3)
2183+
NumToSkip |= (*Ptr++) << 16;
2184+
return NumToSkip;
2185+
}
2186+
21612187
template <typename InsnType>
21622188
static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
21632189
InsnType insn, uint64_t Address,
@@ -2195,10 +2221,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
21952221
// Decode the field value.
21962222
uint64_t Val = decodeULEB128AndIncUnsafe(++Ptr);
21972223
bool Failed = Val != CurFieldValue;
2198-
// NumToSkip is a plain 24-bit integer.
2199-
unsigned NumToSkip = *Ptr++;
2200-
NumToSkip |= (*Ptr++) << 8;
2201-
NumToSkip |= (*Ptr++) << 16;
2224+
unsigned NumToSkip = decodeNumToSkip(Ptr);
22022225
22032226
// Perform the filter operation.
22042227
if (Failed)
@@ -2222,10 +2245,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22222245
uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
22232246
Ptr += PtrLen;
22242247
bool Failed = ExpectedValue != FieldValue;
2225-
// NumToSkip is a plain 24-bit integer.
2226-
unsigned NumToSkip = *Ptr++;
2227-
NumToSkip |= (*Ptr++) << 8;
2228-
NumToSkip |= (*Ptr++) << 16;
2248+
unsigned NumToSkip = decodeNumToSkip(Ptr);
22292249
22302250
// If the actual and expected values don't match, skip.
22312251
if (Failed)
@@ -2240,10 +2260,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22402260
case MCD::OPC_CheckPredicate: {
22412261
// Decode the Predicate Index value.
22422262
unsigned PIdx = decodeULEB128AndIncUnsafe(++Ptr);
2243-
// NumToSkip is a plain 24-bit integer.
2244-
unsigned NumToSkip = *Ptr++;
2245-
NumToSkip |= (*Ptr++) << 8;
2246-
NumToSkip |= (*Ptr++) << 16;
2263+
unsigned NumToSkip = decodeNumToSkip(Ptr);
22472264
// Check the predicate.
22482265
bool Failed = !checkDecoderPredicate(PIdx, Bits);
22492266
if (Failed)
@@ -2278,10 +2295,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22782295
// Decode the Opcode value.
22792296
unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
22802297
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
2281-
// NumToSkip is a plain 24-bit integer.
2282-
unsigned NumToSkip = *Ptr++;
2283-
NumToSkip |= (*Ptr++) << 8;
2284-
NumToSkip |= (*Ptr++) << 16;
2298+
unsigned NumToSkip = decodeNumToSkip(Ptr);
22852299
22862300
// Perform the decode operation.
22872301
MCInst TmpMI;
@@ -2406,6 +2420,9 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr,
24062420

24072421
// Emits disassembler code for instruction decoding.
24082422
void DecoderEmitter::run(raw_ostream &o) {
2423+
if (NumToSkipSizeInBytes != 2 && NumToSkipSizeInBytes != 3)
2424+
PrintFatalError("Invalid value for num-to-skip-size, must be 2 or 3");
2425+
24092426
formatted_raw_ostream OS(o);
24102427
OS << R"(
24112428
#include "llvm/MC/MCInst.h"

0 commit comments

Comments
 (0)