Skip to content

Commit c327fba

Browse files
s-barannikovgithub-actions[bot]
authored andcommitted
Automerge: [TableGen][DecoderEmitter] Rework table construction/emission (#155889)
### Current state We have FilterChooser class, which can be thought of as a **tree of encodings**. Tree nodes are instances of FilterChooser itself, and come in two types: * A node containing single encoding that has *constant* bits in the specified bit range, a.k.a. singleton node. * A node containing only child nodes, where each child represents a set of encodings that have the same *constant* bits in the specified bit range. Either of these nodes can have an additional child, which represents a set of encodings that have some *unknown* bits in the same bit range. As can be seen, the **data structure is very high level**. The encoding tree represented by FilterChooser is then converted into a finite-state machine (FSM), represented as **byte array**. The translation is straightforward: for each node of the tree we emit a sequence of opcodes that check encoding bits and predicates for each encoding. For a singleton node we also emit a terminal "decode" opcode. The translation is done in one go, and this has negative consequences: * We miss optimization opportunities. * We have to use "fixups" when encoding transitions in the FSM since we don't know the size of the data we want to jump over in advance. We have to emit the data first and then fix up the location of the jump. This means the fixup size has to be large enough to encode the longest jump, so **most of the transitions are encoded inefficiently**. * Finally, when converting the FSM into human readable form, we have to **decode the byte array we've just emitted**. This is also done in one go, so we **can't do any pretty printing**. ### This PR We introduce an intermediary data structure, decoder tree, that can be thought as **AST of the decoder program**. This data structure is **low level** and as such allows for optimization and analysis. It resolves all the issues listed above. We now can: * Emit more optimal opcode sequences. * Compute the size of the data to be emitted in advance, avoiding fixups. * Do pretty printing. Serialization is done by a new class, DecoderTableEmitter, which converts the AST into a FSM in **textual form**, streamed right into the output file. ### Results * The new approach immediately resulted in 12% total table size savings across all in-tree targets, without implementing any optimizations on the AST. Many tables observe ~20% size reduction. * The generated file is much more readable. * The implementation is arguably simpler and more straightforward (the diff is only +150~200 lines, which feels rather small for the benefits the change gives).
2 parents f8acd64 + 60bdf09 commit c327fba

19 files changed

+967
-774
lines changed

llvm/include/llvm/MC/MCDecoderOps.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@
1313
namespace llvm::MCD {
1414

1515
// Disassembler state machine opcodes.
16-
// nts_t is either uint16_t or uint24_t based on whether large decoder table is
17-
// enabled.
1816
enum DecoderOps {
19-
OPC_Scope = 1, // OPC_Scope(nts_t NumToSkip)
20-
OPC_ExtractField, // OPC_ExtractField(uleb128 Start, uint8_t Len)
21-
OPC_FilterValueOrSkip, // OPC_FilterValueOrSkip(uleb128 Val, nts_t NumToSkip)
22-
OPC_FilterValue, // OPC_FilterValue(uleb128 Val)
23-
OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len,
24-
// uleb128 Val)
25-
OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx)
26-
OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
27-
OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
17+
OPC_Scope = 1, // OPC_Scope(uleb128 Size)
18+
OPC_SwitchField, // OPC_SwitchField(uleb128 Start, uint8_t Len,
19+
// [uleb128 Val, uleb128 Size]...)
20+
OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len, uleb128 Val)
21+
OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx)
22+
OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
23+
OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
2824
};
2925

3026
} // namespace llvm::MCD

llvm/test/TableGen/DecoderEmitter/DecoderEmitterBitwidthSpecialization.td

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ def Inst3 : Instruction16Bit<3> {
8484
// In the default case, we emit a single decodeToMCinst function and DecodeIdx
8585
// is shared across all bitwidths.
8686

87-
// CHECK-DEFAULT-LABEL: DecoderTable8[25]
88-
// CHECK-DEFAULT: DecodeIdx: 0
89-
// CHECK-DEFAULT: DecodeIdx: 1
87+
// CHECK-DEFAULT-LABEL: DecoderTable8
88+
// CHECK-DEFAULT: using decoder 0
89+
// CHECK-DEFAULT: using decoder 1
9090
// CHECK-DEFAULT: };
9191

92-
// CHECK-DEFAULT-LABEL: DecoderTable16[25]
93-
// CHECK-DEFAULT: DecodeIdx: 2
94-
// CHECK-DEFAULT: DecodeIdx: 3
92+
// CHECK-DEFAULT-LABEL: DecoderTable16
93+
// CHECK-DEFAULT: using decoder 2
94+
// CHECK-DEFAULT: using decoder 3
9595
// CHECK-DEFAULT: };
9696

9797
// CHECK-DEFAULT-LABEL: template <typename InsnType>
@@ -105,10 +105,10 @@ def Inst3 : Instruction16Bit<3> {
105105
// When we specialize per bitwidth, we emit 2 decodeToMCInst functions and
106106
// DecodeIdx is assigned per bit width.
107107

108-
// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable8[26]
109-
// CHECK-SPECIALIZE-NO-TABLE: /* 0 */ 8, // Bitwidth 8
110-
// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 0
111-
// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 1
108+
// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable8
109+
// CHECK-SPECIALIZE-NO-TABLE: 8, // 0: BitWidth 8
110+
// CHECK-SPECIALIZE-NO-TABLE: using decoder 0
111+
// CHECK-SPECIALIZE-NO-TABLE: using decoder 1
112112
// CHECK-SPECIALIZE-NO-TABLE: };
113113

114114
// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>
@@ -117,10 +117,10 @@ def Inst3 : Instruction16Bit<3> {
117117
// CHECK-SPECIALIZE-NO-TABLE: case 0
118118
// CHECK-SPECIALIZE-NO-TABLE: case 1
119119

120-
// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable16[26]
121-
// CHECK-SPECIALIZE-NO-TABLE: /* 0 */ 16, // Bitwidth 16
122-
// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 0
123-
// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 1
120+
// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable16
121+
// CHECK-SPECIALIZE-NO-TABLE: 16, // 0: BitWidth 16
122+
// CHECK-SPECIALIZE-NO-TABLE: using decoder 0
123+
// CHECK-SPECIALIZE-NO-TABLE: using decoder 1
124124
// CHECK-SPECIALIZE-NO-TABLE: };
125125

126126
// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>
@@ -138,10 +138,10 @@ def Inst3 : Instruction16Bit<3> {
138138
// Per bitwidth specialization with function table.
139139

140140
// 8 bit deccoder table, functions, and function table.
141-
// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable8[26]
142-
// CHECK-SPECIALIZE-TABLE: /* 0 */ 8, // Bitwidth 8
143-
// CHECK-SPECIALIZE-TABLE: DecodeIdx: 0
144-
// CHECK-SPECIALIZE-TABLE: DecodeIdx: 1
141+
// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable8
142+
// CHECK-SPECIALIZE-TABLE: 8, // 0: BitWidth 8
143+
// CHECK-SPECIALIZE-TABLE: using decoder 0
144+
// CHECK-SPECIALIZE-TABLE: using decoder 1
145145
// CHECK-SPECIALIZE-TABLE: };
146146

147147
// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
@@ -161,10 +161,10 @@ def Inst3 : Instruction16Bit<3> {
161161
// CHECK-SPECIALIZE-TABLE-NEXT: };
162162

163163
// 16 bit deccoder table, functions, and function table.
164-
// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable16[26]
165-
// CHECK-SPECIALIZE-TABLE: /* 0 */ 16, // Bitwidth 16
166-
// CHECK-SPECIALIZE-TABLE: DecodeIdx: 0
167-
// CHECK-SPECIALIZE-TABLE: DecodeIdx: 1
164+
// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable16
165+
// CHECK-SPECIALIZE-TABLE: 16, // 0: BitWidth 16
166+
// CHECK-SPECIALIZE-TABLE: using decoder 0
167+
// CHECK-SPECIALIZE-TABLE: using decoder 1
168168
// CHECK-SPECIALIZE-TABLE: };
169169

170170
// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>

llvm/test/TableGen/DecoderEmitter/VarLenDecoder.td

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s --check-prefixes=CHECK,CHECK-SMALL
2-
// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../../include %s | FileCheck %s --check-prefixes=CHECK,CHECK-LARGE
1+
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s --check-prefixes=CHECK
32

43
include "llvm/Target/Target.td"
54

@@ -53,19 +52,16 @@ def FOO32 : MyVarInst<MemOp32> {
5352
// CHECK-NEXT: 43,
5453
// CHECK-NEXT: };
5554

56-
// CHECK-SMALL: /* 0 */ OPC_ExtractField, 3, 5, // Field = Inst{7-3}
57-
// CHECK-SMALL-NEXT: /* 3 */ OPC_FilterValueOrSkip, 8, 4, 0, // if Field != 0x8 skip to 11
58-
// CHECK-SMALL-NEXT: /* 7 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
59-
// CHECK-SMALL-NEXT: /* 11 */ OPC_FilterValue, 9, // if Field != 0x9 pop scope
60-
// CHECK-SMALL-NEXT: /* 13 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
61-
// CHECK-SMALL-NEXT: };
62-
63-
// CHECK-LARGE: /* 0 */ OPC_ExtractField, 3, 5, // Field = Inst{7-3}
64-
// CHECK-LARGE-NEXT: /* 3 */ OPC_FilterValueOrSkip, 8, 4, 0, 0, // if Field != 0x8 skip to 12
65-
// CHECK-LARGE-NEXT: /* 8 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16
66-
// CHECK-LARGE-NEXT: /* 12 */ OPC_FilterValue, 9, // if Field != 0x9 pop scope
67-
// CHECK-LARGE-NEXT: /* 14 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
68-
// CHECK-LARGE-NEXT: };
55+
// CHECK-LABEL: static const uint8_t DecoderTable43[15] = {
56+
// CHECK-NEXT: OPC_SwitchField, 3, 5, // 0: switch Inst[7:3] {
57+
// CHECK-NEXT: 8, 4, // 3: case 0x8: {
58+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 5: decode to FOO16 using decoder 0
59+
// CHECK-NEXT: // 5: }
60+
// CHECK-NEXT: 9, 0, // 9: case 0x9: {
61+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 11: decode to FOO32 using decoder 1
62+
// CHECK-NEXT: // 11: }
63+
// CHECK-NEXT: // 11: } // switch Inst[7:3]
64+
// CHECK-NEXT: };
6965

7066
// CHECK: case 0:
7167
// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
@@ -86,7 +82,7 @@ def FOO32 : MyVarInst<MemOp32> {
8682
// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
8783
// CHECK-NEXT: return S;
8884

89-
// CHECK-LABEL: case OPC_ExtractField: {
85+
// CHECK-LABEL: case OPC_SwitchField: {
9086
// CHECK: makeUp(insn, Start + Len);
9187

9288
// CHECK-LABEL: case OPC_CheckField: {

llvm/test/TableGen/DecoderEmitter/additional-encoding.td

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,42 @@ class I<dag out_ops, dag in_ops> : Instruction {
3030
let OutOperandList = out_ops;
3131
}
3232

33-
// CHECK: /* 0 */ OPC_ExtractField, 12, 4, // Field = Inst{15-12}
34-
// CHECK-NEXT: /* 3 */ OPC_FilterValueOrSkip, 0, 15, 0, // if Field != 0x0 skip to 22
35-
// CHECK-NEXT: /* 7 */ OPC_Scope, 8, 0, // end scope at 18
36-
// CHECK-NEXT: /* 10 */ OPC_CheckField, 6, 6, 0, // if Inst{11-6} != 0x0
37-
// CHECK-NEXT: /* 14 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
38-
// CHECK-NEXT: /* 18 */ OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: SHIFT0, DecodeIdx: 1
39-
// CHECK-NEXT: /* 22 */ OPC_FilterValueOrSkip, 1, 15, 0, // if Field != 0x1 skip to 41
40-
// CHECK-NEXT: /* 26 */ OPC_Scope, 8, 0, // end scope at 37
41-
// CHECK-NEXT: /* 29 */ OPC_CheckField, 6, 6, 0, // if Inst{11-6} != 0x0
42-
// CHECK-NEXT: /* 33 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
43-
// CHECK-NEXT: /* 37 */ OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: SHIFT1, DecodeIdx: 1
44-
// CHECK-NEXT: /* 41 */ OPC_FilterValueOrSkip, 2, 15, 0, // if Field != 0x2 skip to 60
45-
// CHECK-NEXT: /* 45 */ OPC_Scope, 8, 0, // end scope at 56
46-
// CHECK-NEXT: /* 48 */ OPC_CheckField, 6, 6, 0, // if Inst{11-6} != 0x0
47-
// CHECK-NEXT: /* 52 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
48-
// CHECK-NEXT: /* 56 */ OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: SHIFT2, DecodeIdx: 1
49-
// CHECK-NEXT: /* 60 */ OPC_FilterValue, 3, // if Field != 0x3
50-
// CHECK-NEXT: /* 62 */ OPC_Scope, 8, 0, // end scope at 73
51-
// CHECK-NEXT: /* 65 */ OPC_CheckField, 6, 6, 0, // if Inst{11-6} != 0x0
52-
// CHECK-NEXT: /* 69 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
53-
// CHECK-NEXT: /* 73 */ OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: SHIFT3, DecodeIdx: 1
54-
33+
// CHECK-LABEL: static const uint8_t DecoderTable16[67] = {
34+
// CHECK-NEXT: OPC_SwitchField, 12, 4, // 0: switch Inst[15:12] {
35+
// CHECK-NEXT: 0, 14, // 3: case 0x0: {
36+
// CHECK-NEXT: OPC_Scope, 8, // 5: try {
37+
// CHECK-NEXT: OPC_CheckField, 6, 6, 0, // 7: check Inst[11:6] == 0x0
38+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 11: decode to NOP using decoder 0
39+
// CHECK-NEXT: // 11: } else try {
40+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 15: decode to SHIFT0 using decoder 1
41+
// CHECK-NEXT: // 15: }
42+
// CHECK-NEXT: // 15: }
43+
// CHECK-NEXT: 1, 14, // 19: case 0x1: {
44+
// CHECK-NEXT: OPC_Scope, 8, // 21: try {
45+
// CHECK-NEXT: OPC_CheckField, 6, 6, 0, // 23: check Inst[11:6] == 0x0
46+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 27: decode to {{.*}}:NOP using decoder 0
47+
// CHECK-NEXT: // 27: } else try {
48+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 31: decode to SHIFT1 using decoder 1
49+
// CHECK-NEXT: // 31: }
50+
// CHECK-NEXT: // 31: }
51+
// CHECK-NEXT: 2, 14, // 35: case 0x2: {
52+
// CHECK-NEXT: OPC_Scope, 8, // 37: try {
53+
// CHECK-NEXT: OPC_CheckField, 6, 6, 0, // 39: check Inst[11:6] == 0x0
54+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 43: decode to {{.*}}:NOP using decoder 0
55+
// CHECK-NEXT: // 43: } else try {
56+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 47: decode to SHIFT2 using decoder 1
57+
// CHECK-NEXT: // 47: }
58+
// CHECK-NEXT: // 47: }
59+
// CHECK-NEXT: 3, 0, // 51: case 0x3: {
60+
// CHECK-NEXT: OPC_Scope, 8, // 53: try {
61+
// CHECK-NEXT: OPC_CheckField, 6, 6, 0, // 55: check Inst[11:6] == 0x0
62+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 59: decode to {{.*}}:NOP using decoder 0
63+
// CHECK-NEXT: // 59: } else try {
64+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 63: decode to SHIFT3 using decoder 1
65+
// CHECK-NEXT: // 63: }
66+
// CHECK-NEXT: // 63: }
67+
// CHECK-NEXT: // 63: } // switch Inst[15:12]
68+
// CHECK-NEXT: };
5569

5670
class SHIFT<bits<2> opc> : I<(outs), (ins ShAmtOp:$shamt)>, EncSHIFT<opc>;
5771
def SHIFT0 : SHIFT<0>;

llvm/test/TableGen/DecoderEmitter/big-filter.td

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@ class I : Instruction {
1111

1212
// Check that a 64-bit filter with all bits set does not confuse DecoderEmitter.
1313
//
14-
// CHECK-LABEL: static const uint8_t DecoderTable128[34] = {
15-
// CHECK-NEXT: /* 0 */ OPC_ExtractField, 0, 64, // Field = Inst{63-0}
16-
// CHECK-NEXT: /* 3 */ OPC_FilterValueOrSkip, 1, 8, 0, // if Field != 0x1 skip to 15
17-
// CHECK-NEXT: /* 7 */ OPC_CheckField, 127, 1, 1, // if Inst{127} != 0x1
18-
// CHECK-NEXT: /* 11 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I2, DecodeIdx: 0
19-
// CHECK-NEXT: /* 15 */ OPC_FilterValue, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, // if Field != 0xffffffffffffffff
20-
// CHECK-NEXT: /* 26 */ OPC_CheckField, 127, 1, 0, // if Inst{127} != 0x0
21-
// CHECK-NEXT: /* 30 */ OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I1, DecodeIdx: 0
14+
// CHECK-LABEL: static const uint8_t DecoderTable128[32] = {
15+
// CHECK-NEXT: OPC_SwitchField, 0, 64, // 0: switch Inst[63:0] {
16+
// CHECK-NEXT: 1, 8, // 3: case 0x1: {
17+
// CHECK-NEXT: OPC_CheckField, 127, 1, 1, // 5: check Inst[127] == 0x1
18+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 9: decode to I2 using decoder 0
19+
// CHECK-NEXT: // 9: }
20+
// CHECK-NEXT: 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0,
21+
// CHECK-NEXT: // 13: case 0xffffffffffffffff: {
22+
// CHECK-NEXT: OPC_CheckField, 127, 1, 0, // 24: check Inst[127] == 0x0
23+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 28: decode to I1 using decoder 0
24+
// CHECK-NEXT: // 28: }
25+
// CHECK-NEXT: // 28: } // switch Inst[63:0]
2226
// CHECK-NEXT: };
2327

2428
def I1 : I {

llvm/test/TableGen/DecoderEmitter/trydecode-emission.td

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s
2-
// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
32

43
// Check that if decoding of an instruction fails and the instruction does not
54
// have a complete decoder method that can determine if the bitpattern is valid
@@ -34,29 +33,14 @@ def InstB : TestInstruction {
3433
let hasCompleteDecoder = 0;
3534
}
3635

37-
// CHECK: /* 0 */ OPC_CheckField, 4, 4, 0, // if Inst{7-4} != 0x0
38-
// CHECK-NEXT: /* 4 */ OPC_Scope, 8, 0, // end scope at 15
39-
// CHECK-NEXT: /* 7 */ OPC_CheckField, 2, 2, 0, // if Inst{3-2} != 0x0
40-
// CHECK-NEXT: /* 11 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: InstB, DecodeIdx: 0
41-
// CHECK-NEXT: /* 15 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
36+
// CHECK-LABEL: static const uint8_t DecoderTable8[18] = {
37+
// CHECK-NEXT: OPC_CheckField, 4, 4, 0, // 0: check Inst[7:4] == 0x0
38+
// CHECK-NEXT: OPC_Scope, 8, // 4: try {
39+
// CHECK-NEXT: OPC_CheckField, 2, 2, 0, // 6: check Inst[3:2] == 0x0
40+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 10: decode to InstB using decoder 0
41+
// CHECK-NEXT: // 10: } else try {
42+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 14: decode to InstA using decoder 1
43+
// CHECK-NEXT: // 14: }
4244
// CHECK-NEXT: };
4345

4446
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
45-
46-
// CHECK: unsigned NumToSkip = *Ptr++;
47-
// CHECK-NEXT: NumToSkip |= (*Ptr++) << 8;
48-
// CHECK-NEXT: return NumToSkip;
49-
50-
// CHECK-LARGE: /* 0 */ OPC_CheckField, 4, 4, 0, // if Inst{7-4} != 0x0
51-
// CHECK-LARGE-NEXT: /* 4 */ OPC_Scope, 8, 0, 0, // end scope at 16
52-
// CHECK-LARGE-NEXT: /* 8 */ OPC_CheckField, 2, 2, 0, // if Inst{3-2} != 0x0
53-
// CHECK-LARGE-NEXT: /* 12 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: InstB, DecodeIdx: 0
54-
// CHECK-LARGE-NEXT: /* 16 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
55-
// CHECK-LARGE-NEXT: };
56-
57-
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
58-
59-
// CHECK-LARGE: unsigned NumToSkip = *Ptr++;
60-
// CHECK-LARGE-NEXT: NumToSkip |= (*Ptr++) << 8;
61-
// CHECK-LARGE-NEXT: NumToSkip |= (*Ptr++) << 16;
62-
// CHECK-LARGE-NEXT: return NumToSkip;

llvm/test/TableGen/DecoderEmitter/trydecode-emission2.td

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s
2-
// RUN: llvm-tblgen -gen-disassembler --large-decoder-table -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-LARGE
32

43
include "llvm/Target/Target.td"
54

@@ -31,25 +30,17 @@ def InstB : TestInstruction {
3130
let hasCompleteDecoder = 0;
3231
}
3332

34-
// CHECK: /* 0 */ OPC_CheckField, 2, 1, 0,
35-
// CHECK-NEXT: /* 4 */ OPC_CheckField, 5, 3, 0,
36-
// CHECK-NEXT: /* 8 */ OPC_Scope, 8, 0, // end scope at 19
37-
// CHECK-NEXT: /* 11 */ OPC_CheckField, 0, 2, 3,
38-
// CHECK-NEXT: /* 15 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0,
39-
// CHECK-NEXT: /* 19 */ OPC_CheckField, 3, 2, 0,
40-
// CHECK-NEXT: /* 23 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1,
33+
// CHECK-LABEL: static const uint8_t DecoderTable8[26] = {
34+
// CHECK-NEXT: OPC_CheckField, 2, 1, 0, // 0: check Inst[2] == 0x0
35+
// CHECK-NEXT: OPC_CheckField, 5, 3, 0, // 4: check Inst[7:5] == 0x0
36+
// CHECK-NEXT: OPC_Scope, 8, // 8: try {
37+
// CHECK-NEXT: OPC_CheckField, 0, 2, 3, // 10: check Inst[1:0] == 0x3
38+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 0, // 14: decode to InstB using decoder 0
39+
// CHECK-NEXT: // 14: } else try {
40+
// CHECK-NEXT: OPC_CheckField, 3, 2, 0, // 18: check Inst[4:3] == 0x0
41+
// CHECK-NEXT: OPC_Decode, {{[0-9, ]+}}, 1, // 22: decode to InstA using decoder 1
42+
// CHECK-NEXT: // 22: }
43+
// CHECK-NEXT: };
4144

4245
// CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
4346
// CHECK: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
44-
45-
// CHECK-LARGE: /* 0 */ OPC_CheckField, 2, 1, 0,
46-
// CHECK-LARGE-NEXT: /* 4 */ OPC_CheckField, 5, 3, 0,
47-
// CHECK-LARGE-NEXT: /* 8 */ OPC_Scope, 8, 0, 0, // end scope at 20
48-
// CHECK-LARGE-NEXT: /* 12 */ OPC_CheckField, 0, 2, 3,
49-
// CHECK-LARGE-NEXT: /* 16 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0,
50-
// CHECK-LARGE-NEXT: /* 20 */ OPC_CheckField, 3, 2, 0,
51-
// CHECK-LARGE-NEXT: /* 24 */ OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1,
52-
// CHECK-LARGE-NEXT: };
53-
54-
// CHECK-LARGE: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
55-
// CHECK-LARGE: if (!Check(S, DecodeInstA(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }

0 commit comments

Comments
 (0)