diff options
author | Rahul Joshi <rjoshi@nvidia.com> | 2025-06-05 06:17:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-05 06:17:50 -0700 |
commit | e53ccb78e46c6d923fee914b31d13d930021a954 (patch) | |
tree | e1d6f872bf3162ec860d52f7be9b03fca41869e4 | |
parent | 43bc5ea7fd9603e24e6830788cf1a8c6ab464b46 (diff) | |
download | llvm-e53ccb78e46c6d923fee914b31d13d930021a954.zip llvm-e53ccb78e46c6d923fee914b31d13d930021a954.tar.gz llvm-e53ccb78e46c6d923fee914b31d13d930021a954.tar.bz2 |
[LLVM][MC] Introduce `OrFail` variants of MCD ops (#138614)
Introduce `OrFail` variants for all MCD Decoder Ops that have
`NumToSKip` encoded with them. This is intended to capture the common
case of jumps to the end of the decoder table which has a `OP_Fail` at
the end. Using the `OrFail` variants of these ops avoid encoding the
`NumToSkip` jump offset for these cases, resulting in a reduction in the
size of the decoder tables (from 5 - 17%). Additionally, for the AArch64
target, the table size reduces enough to switch to using 2-byte
`NumToSkip` encoding instead of existing 3-bytes, resulting in a net 30%
reduction in the size of the decoder table.
The total reduction in the size of the decoder tables for different
targets is as follows (computed using the following command: `for i in
*.inc; do echo -n ``basename $i: ``; grep "MCD::OPC_Fail," $i | awk
'{sum += $2} END { print sum}'; done`)
```
Target Old Size New Size % Reduction
================================================
AArch64 153268 106987 30.20
AMDGPU 412056 340856 17.28
ARC 5061 4605 9.01
ARM 73831 60847 17.59
AVR 1306 1158 11.33
BPF 1927 1795 6.85
CSKY 8692 6922 20.36
Hexagon 41965 34759 17.17
Lanai 982 924 5.91
LoongArch 21629 20035 7.37
M68k 13461 11689 13.16
MSP430 3716 3384 8.93
Mips 31415 25771 17.97
PPC 28931 24771 14.38
RISCV 34800 28352 18.53
Sparc 7432 6236 16.09
SystemZ 32248 29716 7.85
VE 42873 36923 13.88
XCore 2316 2196 5.18
Xtensa 3443 2793 18.88
```
-rw-r--r-- | llvm/include/llvm/MC/MCDecoderOps.h | 33 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/CMakeLists.txt | 3 | ||||
-rw-r--r-- | llvm/test/TableGen/VarLenDecoder.td | 21 | ||||
-rw-r--r-- | llvm/test/TableGen/trydecode-emission.td | 20 | ||||
-rw-r--r-- | llvm/test/TableGen/trydecode-emission2.td | 32 | ||||
-rw-r--r-- | llvm/test/TableGen/trydecode-emission3.td | 20 | ||||
-rw-r--r-- | llvm/test/TableGen/trydecode-emission4.td | 20 | ||||
-rw-r--r-- | llvm/utils/TableGen/DecoderEmitter.cpp | 253 | ||||
-rw-r--r-- | utils/bazel/llvm-project-overlay/llvm/BUILD.bazel | 1 |
9 files changed, 249 insertions, 154 deletions
diff --git a/llvm/include/llvm/MC/MCDecoderOps.h b/llvm/include/llvm/MC/MCDecoderOps.h index 3c0b681..50fcf2a 100644 --- a/llvm/include/llvm/MC/MCDecoderOps.h +++ b/llvm/include/llvm/MC/MCDecoderOps.h @@ -10,24 +10,29 @@ #ifndef LLVM_MC_MCDECODEROPS_H #define LLVM_MC_MCDECODEROPS_H -namespace llvm { +namespace llvm::MCD { -namespace MCD { // Disassembler state machine opcodes. +// nts_t is either uint16_t or uint24_t based on whether large decoder table is +// enabled. enum DecoderOps { - OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len) - OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip) - OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len, - // uleb128 Val, uint16_t NumToSkip) - OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip) - OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) - OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx, - // uint16_t NumToSkip) - OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) - OPC_Fail // OPC_Fail() + OPC_ExtractField = 1, // OPC_ExtractField(uleb128 Start, uint8_t Len) + OPC_FilterValue, // OPC_FilterValue(uleb128 Val, nts_t NumToSkip) + OPC_FilterValueOrFail, // OPC_FilterValueOrFail(uleb128 Val) + OPC_CheckField, // OPC_CheckField(uleb128 Start, uint8_t Len, + // uleb128 Val, nts_t NumToSkip) + OPC_CheckFieldOrFail, // OPC_CheckFieldOrFail(uleb128 Start, uint8_t Len, + // uleb128 Val) + OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, nts_t NumToSkip) + OPC_CheckPredicateOrFail, // OPC_CheckPredicateOrFail(uleb128 PIdx) + OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) + OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx, + // nts_t NumToSkip) + OPC_TryDecodeOrFail, // OPC_TryDecodeOrFail(uleb128 Opcode, uleb128 DIdx) + OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) + OPC_Fail // OPC_Fail() }; -} // namespace MCD -} // namespace llvm +} // namespace llvm::MCD #endif diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index 9cf6f8a8..66136a4 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -7,8 +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 - --large-decoder-table) +tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler) 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 db7a5205..06ff622 100644 --- a/llvm/test/TableGen/VarLenDecoder.td +++ b/llvm/test/TableGen/VarLenDecoder.td @@ -47,19 +47,19 @@ def FOO32 : MyVarInst<MemOp32> { ); } -// 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-SMALL: /* 0 */ MCD::OPC_ExtractField, 3, 5, // Inst{7-3} ... +// CHECK-SMALL-NEXT: /* 3 */ MCD::OPC_FilterValue, 8, 4, 0, // Skip to: 11 +// CHECK-SMALL-NEXT: /* 7 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16 +// CHECK-SMALL-NEXT: /* 11 */ MCD::OPC_FilterValueOrFail, 9, +// CHECK-SMALL-NEXT: /* 13 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32 +// CHECK-SMALL-NEXT: /* 17 */ 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, {{[0-9]+}}, {{[0-9]+}}, 0, // Opcode: FOO16 -// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21 -// CHECK-LARGE-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32 -// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Fail, +// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_FilterValueOrFail, 9, +// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32 +// CHECK-LARGE-NEXT: /* 18 */ MCD::OPC_Fail, // Instruction length table // CHECK: 27, @@ -88,7 +88,8 @@ def FOO32 : MyVarInst<MemOp32> { // CHECK-LABEL: case MCD::OPC_ExtractField: { // CHECK: makeUp(insn, Start + Len); -// CHECK-LABEL: case MCD::OPC_CheckField: { +// CHECK-LABEL: case MCD::OPC_CheckField: +// CHECK-NEXT: case MCD::OPC_CheckFieldOrFail: { // CHECK: makeUp(insn, Start + Len); // CHECK-LABEL: case MCD::OPC_Decode: { diff --git a/llvm/test/TableGen/trydecode-emission.td b/llvm/test/TableGen/trydecode-emission.td index db77d94..47d47c9 100644 --- a/llvm/test/TableGen/trydecode-emission.td +++ b/llvm/test/TableGen/trydecode-emission.td @@ -35,11 +35,11 @@ def InstB : TestInstruction { } // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ... -// 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-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17 +// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17 +// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA +// CHECK-NEXT: /* 21 */ MCD::OPC_Fail, // CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; } @@ -48,11 +48,11 @@ def InstB : TestInstruction { // 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, {{[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-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19 +// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19 +// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA +// CHECK-LARGE-NEXT: /* 23 */ MCD::OPC_Fail, // CHECK-LARGE: 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 914e17c..593da63 100644 --- a/llvm/test/TableGen/trydecode-emission2.td +++ b/llvm/test/TableGen/trydecode-emission2.td @@ -32,27 +32,27 @@ def InstB : TestInstruction { } // CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ... -// 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-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ... +// CHECK-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0 +// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 22 +// CHECK-NEXT: /* 16 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 22 +// CHECK-NEXT: /* 22 */ MCD::OPC_CheckFieldOrFail, 3, 2, 0, +// CHECK-NEXT: /* 26 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1, +// CHECK-NEXT: /* 30 */ 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; } // 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, {{[0-9]+}}, {{[0-9]+}}, 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, {{[0-9]+}}, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 44 -// CHECK-LARGE-NEXT: /* 44 */ MCD::OPC_Fail, +// CHECK-LARGE-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ... +// CHECK-LARGE-NEXT: /* 8 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-LARGE-NEXT: /* 10 */ MCD::OPC_CheckField, 0, 2, 3, 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_CheckFieldOrFail, 3, 2, 0, +// CHECK-LARGE-NEXT: /* 28 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1, +// CHECK-LARGE-NEXT: /* 32 */ 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 141dc54..e2b739d 100644 --- a/llvm/test/TableGen/trydecode-emission3.td +++ b/llvm/test/TableGen/trydecode-emission3.td @@ -36,19 +36,19 @@ def InstB : TestInstruction { } // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ... -// 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-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 17 +// CHECK-NEXT: /* 11 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, Skip to: 17 +// CHECK-NEXT: /* 17 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA +// CHECK-NEXT: /* 21 */ 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-NEXT: /* 3 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-LARGE-NEXT: /* 5 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 19 +// CHECK-LARGE-NEXT: /* 12 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 19 +// CHECK-LARGE-NEXT: /* 19 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA +// CHECK-LARGE-NEXT: /* 23 */ 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 bb44876..39a3187 100644 --- a/llvm/test/TableGen/trydecode-emission4.td +++ b/llvm/test/TableGen/trydecode-emission4.td @@ -34,21 +34,21 @@ def InstB : TestInstruction { } // CHECK: /* 0 */ MCD::OPC_ExtractField, 250, 3, 4, // Inst{509-506} ... -// 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, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, skip to: 21 -// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA -// CHECK-NEXT: /* 25 */ MCD::OPC_Fail, +// CHECK-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 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; } // 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-NEXT: /* 4 */ MCD::OPC_FilterValueOrFail, 0, +// CHECK-LARGE-NEXT: /* 6 */ MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 21 +// CHECK-LARGE-NEXT: /* 14 */ MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, Skip to: 21 +// CHECK-LARGE-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA +// CHECK-LARGE-NEXT: /* 25 */ 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 82ba935..3990836 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -90,9 +90,9 @@ STATISTIC(NumInstructions, "Number of instructions considered"); STATISTIC(NumEncodingsSupported, "Number of encodings supported"); STATISTIC(NumEncodingsOmitted, "Number of encodings omitted"); -namespace { +static unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; } -unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; } +namespace { struct EncodingField { unsigned Base, Width, Offset; @@ -182,6 +182,8 @@ struct DecoderTableInfo { FixupScopeList FixupStack; PredicateSet Predicates; DecoderSet Decoders; + + bool isOutermostScope() const { return FixupStack.size() == 1; } }; struct EncodingAndInst { @@ -777,11 +779,21 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { PrevFilter = 0; // Don't re-process the filter's fallthrough. } else { - Table.push_back(MCD::OPC_FilterValue); + // The last filtervalue emitted can be OPC_FilterValue if we are at + // outermost scope. + const uint8_t DecoderOp = + FilterVal == LastFilter && TableInfo.isOutermostScope() + ? MCD::OPC_FilterValueOrFail + : MCD::OPC_FilterValue; + Table.push_back(DecoderOp); Table.insertULEB128(FilterVal); - // Reserve space for the NumToSkip entry. We'll backpatch the value - // later. - PrevFilter = Table.insertNumToSkip(); + if (DecoderOp == MCD::OPC_FilterValue) { + // Reserve space for the NumToSkip entry. We'll backpatch the value + // later. + PrevFilter = Table.insertNumToSkip(); + } else { + PrevFilter = 0; + } } // We arrive at a category of instructions with the same segment value. @@ -796,9 +808,10 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { Table.patchNumToSkip(PrevFilter, Table.size()); } - // If there is no fallthrough, then the final filter should get fixed - // up according to the enclosing scope rather than the current position. - if (!HasFallthrough) + // If there is no fallthrough and the final filter was not in the outermost + // scope, then it must be fixed up according to the enclosing scope rather + // than the current position. + if (PrevFilter) TableInfo.FixupStack.back().push_back(PrevFilter); } @@ -863,6 +876,15 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, DecoderTable::const_iterator I = Table.begin(); DecoderTable::const_iterator E = Table.end(); const uint8_t *const EndPtr = Table.data() + Table.size(); + + auto emitNumToSkipComment = [&](uint32_t NumToSkip, bool InComment = false) { + uint32_t Index = ((I - Table.begin()) + NumToSkip); + OS << (InComment ? ", " : "// "); + OS << "Skip to: " << Index; + if (*(I + NumToSkip) == MCD::OPC_Fail) + OS << " (Fail)"; + }; + while (I != E) { assert(I < E && "incomplete decode table entry!"); @@ -873,7 +895,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, const uint8_t DecoderOp = *I++; switch (DecoderOp) { default: - PrintFatalError("Invalid decode table opcode: " + Twine(DecoderOp)); + PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) + + " at index " + Twine(Pos)); case MCD::OPC_ExtractField: { OS << Indent << "MCD::OPC_ExtractField, "; @@ -890,17 +913,24 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, OS << Start << "} ...\n"; break; } - case MCD::OPC_FilterValue: { - OS << Indent << "MCD::OPC_FilterValue, "; + case MCD::OPC_FilterValue: + case MCD::OPC_FilterValueOrFail: { + bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail; + OS << Indent << "MCD::OPC_FilterValue" << (IsFail ? "OrFail, " : ", "); // The filter value is ULEB128 encoded. emitULEB128(I, OS); - uint32_t NumToSkip = emitNumToSkip(I, OS); - OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + if (!IsFail) { + uint32_t NumToSkip = emitNumToSkip(I, OS); + emitNumToSkipComment(NumToSkip); + } + OS << '\n'; break; } - case MCD::OPC_CheckField: { - OS << Indent << "MCD::OPC_CheckField, "; + case MCD::OPC_CheckField: + case MCD::OPC_CheckFieldOrFail: { + bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail; + OS << Indent << "MCD::OPC_CheckField" << (IsFail ? "OrFail, " : ", "); // ULEB128 encoded start value. emitULEB128(I, OS); // 8-bit length. @@ -909,27 +939,39 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // ULEB128 encoded field value. emitULEB128(I, OS); - uint32_t NumToSkip = emitNumToSkip(I, OS); - OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + if (!IsFail) { + uint32_t NumToSkip = emitNumToSkip(I, OS); + emitNumToSkipComment(NumToSkip); + } + OS << '\n'; break; } - case MCD::OPC_CheckPredicate: { - OS << Indent << "MCD::OPC_CheckPredicate, "; + case MCD::OPC_CheckPredicate: + case MCD::OPC_CheckPredicateOrFail: { + bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail; + + OS << Indent << "MCD::OPC_CheckPredicate" << (IsFail ? "OrFail, " : ", "); emitULEB128(I, OS); - uint32_t NumToSkip = emitNumToSkip(I, OS); - OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + if (!IsFail) { + uint32_t NumToSkip = emitNumToSkip(I, OS); + emitNumToSkipComment(NumToSkip); + } + OS << '\n'; break; } case MCD::OPC_Decode: - case MCD::OPC_TryDecode: { - bool IsTry = DecoderOp == MCD::OPC_TryDecode; + case MCD::OPC_TryDecode: + case MCD::OPC_TryDecodeOrFail: { + bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail; + bool IsTry = DecoderOp == MCD::OPC_TryDecode || IsFail; // Decode the Opcode value. const char *ErrMsg = nullptr; unsigned Opc = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg); assert(ErrMsg == nullptr && "ULEB128 value too large!"); - OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode, "; + OS << Indent << "MCD::OPC_" << (IsTry ? "Try" : "") << "Decode" + << (IsFail ? "OrFail, " : ", "); emitULEB128(I, OS); // Decoder index. @@ -946,10 +988,14 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // Fallthrough for OPC_TryDecode. - uint32_t NumToSkip = emitNumToSkip(I, OS); - - OS << "// Opcode: " << NumberedEncodings[EncodingID] - << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + if (!IsFail) { + uint32_t NumToSkip = emitNumToSkip(I, OS); + OS << "// Opcode: " << NumberedEncodings[EncodingID]; + emitNumToSkipComment(NumToSkip, /*InComment=*/true); + } else { + OS << "// Opcode: " << NumberedEncodings[EncodingID]; + } + OS << '\n'; break; } case MCD::OPC_SoftFail: { @@ -971,11 +1017,10 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, OS << '\n'; break; } - case MCD::OPC_Fail: { + case MCD::OPC_Fail: OS << Indent << "MCD::OPC_Fail,\n"; break; } - } } OS << Indent << "0\n"; @@ -1337,11 +1382,16 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, // computed. unsigned PIdx = getPredicateIndex(TableInfo, PS.str()); - TableInfo.Table.push_back(MCD::OPC_CheckPredicate); + const uint8_t DecoderOp = TableInfo.isOutermostScope() + ? MCD::OPC_CheckPredicateOrFail + : MCD::OPC_CheckPredicate; + TableInfo.Table.push_back(DecoderOp); TableInfo.Table.insertULEB128(PIdx); - // Push location for NumToSkip backpatching. - TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip()); + if (DecoderOp == MCD::OPC_CheckPredicate) { + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip()); + } } void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, @@ -1411,17 +1461,22 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, for (const Island &Ilnd : reverse(Islands)) { unsigned NumBits = Ilnd.NumBits; assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!"); - TableInfo.Table.push_back(MCD::OPC_CheckField); + const uint8_t DecoderOp = TableInfo.isOutermostScope() + ? MCD::OPC_CheckFieldOrFail + : MCD::OPC_CheckField; + TableInfo.Table.push_back(DecoderOp); TableInfo.Table.insertULEB128(Ilnd.StartBit); TableInfo.Table.push_back(NumBits); TableInfo.Table.insertULEB128(Ilnd.FieldVal); - // Allocate space in the table for fixup so all our relative position - // calculations work OK even before we fully resolve the real value here. + if (DecoderOp == MCD::OPC_CheckField) { + // 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()); + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip()); + } } // Check for soft failure of the match. @@ -1439,13 +1494,16 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // decoder method indicates that additional processing should be done to see // if there is any other instruction that also matches the bitpattern and // can decode it. - TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode - : MCD::OPC_TryDecode); + const uint8_t DecoderOp = HasCompleteDecoder ? MCD::OPC_Decode + : (TableInfo.isOutermostScope() + ? MCD::OPC_TryDecodeOrFail + : MCD::OPC_TryDecode); + TableInfo.Table.push_back(DecoderOp); NumEncodingsSupported++; TableInfo.Table.insertULEB128(Opc.Opcode); TableInfo.Table.insertULEB128(DIdx); - if (!HasCompleteDecoder) { + if (DecoderOp == MCD::OPC_TryDecode) { // Push location for NumToSkip backpatching. TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip()); } @@ -2188,7 +2246,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, DecodeStatus S = MCDisassembler::Success; while (true) { ptrdiff_t Loc = Ptr - DecodeTable; - switch (*Ptr++) { + const uint8_t DecoderOp = *Ptr++; + switch (DecoderOp) { default: errs() << Loc << ": Unexpected decode table opcode!\n"; return MCDisassembler::Fail; @@ -2204,22 +2263,34 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, << Len << "): " << CurFieldValue << "\n"); break; } - case MCD::OPC_FilterValue: { + case MCD::OPC_FilterValue: + case MCD::OPC_FilterValueOrFail: { + bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail; // Decode the field value. uint64_t Val = decodeULEB128AndIncUnsafe(Ptr); bool Failed = Val != CurFieldValue; - unsigned NumToSkip = decodeNumToSkip(Ptr); + unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr); + + // Note: Print NumToSkip even for OPC_FilterValueOrFail to simplify debug + // prints. + LLVM_DEBUG({ + StringRef OpName = IsFail ? "OPC_FilterValueOrFail" : "OPC_FilterValue"; + dbgs() << Loc << ": " << OpName << '(' << Val << ", " << NumToSkip + << ") " << (Failed ? "FAIL:" : "PASS:") + << " continuing at " << (Ptr - DecodeTable) << '\n'; + }); // Perform the filter operation. - if (Failed) + if (Failed) { + if (IsFail) + return MCDisassembler::Fail; Ptr += NumToSkip; - LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ", " << NumToSkip - << "): " << (Failed ? "FAIL:" : "PASS:") - << " continuing at " << (Ptr - DecodeTable) << "\n"); - + } break; } - case MCD::OPC_CheckField: { + case MCD::OPC_CheckField: + case MCD::OPC_CheckFieldOrFail: { + bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail; // Decode the start value. unsigned Start = decodeULEB128AndIncUnsafe(Ptr); unsigned Len = *Ptr;)"; @@ -2232,29 +2303,44 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen); Ptr += PtrLen; bool Failed = ExpectedValue != FieldValue; - unsigned NumToSkip = decodeNumToSkip(Ptr); - - // If the actual and expected values don't match, skip. - if (Failed) + unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr); + + LLVM_DEBUG({ + StringRef OpName = IsFail ? "OPC_CheckFieldOrFail" : "OPC_CheckField"; + dbgs() << Loc << ": " << OpName << '(' << Start << ", " << Len << ", " + << ExpectedValue << ", " << NumToSkip << "): FieldValue = " + << FieldValue << ", ExpectedValue = " << ExpectedValue << ": " + << (Failed ? "FAIL\n" : "PASS\n"); + }); + + // If the actual and expected values don't match, skip or fail. + if (Failed) { + if (IsFail) + return MCDisassembler::Fail; Ptr += NumToSkip; - LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", " - << Len << ", " << ExpectedValue << ", " << NumToSkip - << "): FieldValue = " << FieldValue << ", ExpectedValue = " - << ExpectedValue << ": " - << (Failed ? "FAIL\n" : "PASS\n")); + } break; } - case MCD::OPC_CheckPredicate: { + case MCD::OPC_CheckPredicate: + case MCD::OPC_CheckPredicateOrFail: { + bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail; // Decode the Predicate Index value. unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr); - unsigned NumToSkip = decodeNumToSkip(Ptr); + unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr); // Check the predicate. bool Failed = !checkDecoderPredicate(PIdx, Bits); - if (Failed) - Ptr += NumToSkip; - LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): " - << (Failed ? "FAIL\n" : "PASS\n")); + LLVM_DEBUG({ + StringRef OpName = IsFail ? "OPC_CheckPredicateOrFail" : "OPC_CheckPredicate"; + dbgs() << Loc << ": " << OpName << '(' << PIdx << ", " << NumToSkip + << "): " << (Failed ? "FAIL\n" : "PASS\n"); + }); + + if (Failed) { + if (IsFail) + return MCDisassembler::Fail; + Ptr += NumToSkip; + } break; } case MCD::OPC_Decode: { @@ -2275,14 +2361,16 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc << ", using decoder " << DecodeIdx << ": " - << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n")); return S; } - case MCD::OPC_TryDecode: { + case MCD::OPC_TryDecode: + case MCD::OPC_TryDecodeOrFail: { + bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail; // Decode the Opcode value. unsigned Opc = decodeULEB128AndIncUnsafe(Ptr); unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr); - unsigned NumToSkip = decodeNumToSkip(Ptr); + unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr); // Perform the decode operation. MCInst TmpMI; @@ -2294,28 +2382,31 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, if (DecodeComplete) { // Decoding complete. - LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n")); MI = TmpMI; return S; - } else { - assert(S == MCDisassembler::Fail); - // If the decoding was incomplete, skip. - Ptr += NumToSkip; - LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n"); - // Reset decode status. This also drops a SoftFail status that could be - // set before the decode attempt. - S = MCDisassembler::Success; } + assert(S == MCDisassembler::Fail); + if (IsFail) { + LLVM_DEBUG(dbgs() << "FAIL: returning FAIL\n"); + return MCDisassembler::Fail; + } + // If the decoding was incomplete, skip. + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n"); + // Reset decode status. This also drops a SoftFail status that could be + // set before the decode attempt. + S = MCDisassembler::Success; break; } case MCD::OPC_SoftFail: { // Decode the mask values. uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr); uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr); - bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0; - if (Fail) + bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0; + if (Failed) S = MCDisassembler::SoftFail; - LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Fail ? "FAIL\n" : "PASS\n")); + LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n")); break; } case MCD::OPC_Fail: { diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index 5628a22..40d7fb7 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -2116,7 +2116,6 @@ llvm_target_lib_list = [lib for lib in [ "lib/Target/AArch64/AArch64GenSubtargetInfo.inc": ["-gen-subtarget"], "lib/Target/AArch64/AArch64GenDisassemblerTables.inc": [ "-gen-disassembler", - "--large-decoder-table", ], "lib/Target/AArch64/AArch64GenSystemOperands.inc": ["-gen-searchable-tables"], "lib/Target/AArch64/AArch64GenExegesis.inc": ["-gen-exegesis"], |