[llvm] [TableGen][DecoderEmitter] Add OPC_Scope opcode (PR #155580)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 02:15:27 PDT 2025


https://github.com/s-barannikov created https://github.com/llvm/llvm-project/pull/155580

This change introduces OPC_Scope opcode, whose only purpose is to record a continuation point to resume at if a subsequent opcode fails.

Each OPC_Scope pushes an entry onto the scope stack; an entry is popped if an opcode in the scope fails.

Previously, we had this information on several opcodes, it has been removed. A series of such opcodes often referred to the same continuation point; this information is now recorded in one place, reducing table sizes in most cases. Average reduction is 1.1%, some table observe up to 7% reduction in size.

The new behavior of those opcodes is "check or leave scope". If we're in the outermost scope (scope stack is empty), they act as "check or fail".

There is one opcode, OPC_FilterValueOrSkip that behaves like the old OPC_FilterValue. It is special because it acts as a case of a switch statement and has nothing to do with scopes. (If a case fails, we should try the next case instead of leaving the current scope.)


>From e33c52148840a26b19fc951795f2aa9ed58932a5 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 24 Aug 2025 11:57:23 +0300
Subject: [PATCH] [TableGen][DecoderEmitter] Add OPC_Scope opcode

---
 llvm/include/llvm/MC/MCDecoderOps.h           |  24 +-
 .../additional-encoding.td                    |  39 +--
 .../FixedLenDecoderEmitter/big-filter.td      |  14 +-
 .../var-len-conflict-1.td                     |  25 +-
 llvm/test/TableGen/VarLenDecoder.td           |  11 +-
 llvm/test/TableGen/trydecode-emission.td      |  18 +-
 llvm/test/TableGen/trydecode-emission2.td     |  27 +-
 llvm/test/TableGen/trydecode-emission3.td     |  18 +-
 llvm/test/TableGen/trydecode-emission4.td     |  18 +-
 llvm/utils/TableGen/DecoderEmitter.cpp        | 255 +++++++-----------
 10 files changed, 201 insertions(+), 248 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDecoderOps.h b/llvm/include/llvm/MC/MCDecoderOps.h
index d2e7cbf27b04b..790ff3eb4f333 100644
--- a/llvm/include/llvm/MC/MCDecoderOps.h
+++ b/llvm/include/llvm/MC/MCDecoderOps.h
@@ -16,20 +16,16 @@ namespace llvm::MCD {
 // 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, 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_Scope = 1,         // OPC_Scope(nts_t NumToSkip)
+  OPC_ExtractField,      // OPC_ExtractField(uleb128 Start, uint8_t Len)
+  OPC_FilterValueOrSkip, // OPC_FilterValueOrSkip(uleb128 Val, nts_t NumToSkip)
+  OPC_FilterValue,       // OPC_FilterValue(uleb128 Val)
+  OPC_CheckField,        // OPC_CheckField(uleb128 Start, uint8_t Len,
+                         //                uleb128 Val)
+  OPC_CheckPredicate,    // OPC_CheckPredicate(uleb128 PIdx)
+  OPC_Decode,            // OPC_Decode(uleb128 Opcode, uleb128 DIdx)
+  OPC_TryDecode,         // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx)
+  OPC_SoftFail,          // OPC_SoftFail(uleb128 PMask, uleb128 NMask)
 };
 
 } // namespace llvm::MCD
diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/additional-encoding.td b/llvm/test/TableGen/FixedLenDecoderEmitter/additional-encoding.td
index 503822c37371e..ec7e35e1ecac7 100644
--- a/llvm/test/TableGen/FixedLenDecoderEmitter/additional-encoding.td
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/additional-encoding.td
@@ -30,23 +30,28 @@ class I<dag out_ops, dag in_ops> : Instruction {
   let OutOperandList = out_ops;
 }
 
-// CHECK:      /* 0 */  MCD::OPC_ExtractField, 12, 4,                // Inst{15-12} ...
-// CHECK-NEXT: /* 3 */  MCD::OPC_FilterValue, 0, 14, 0,              // Skip to: 21
-// CHECK-NEXT: /* 7 */  MCD::OPC_CheckField, 6, 6, 0, 4, 0,          // Skip to: 17
-// CHECK-NEXT: /* 13 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,           // Opcode: {{.*}}:NOP
-// CHECK-NEXT: /* 17 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, 2, 1,
-// CHECK-NEXT: /* 21 */ MCD::OPC_FilterValue, 1, 14, 0,              // Skip to: 39
-// CHECK-NEXT: /* 25 */ MCD::OPC_CheckField, 6, 6, 0, 4, 0,          // Skip to: 35
-// CHECK-NEXT: /* 31 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,           // Opcode: {{.*}}:NOP
-// CHECK-NEXT: /* 35 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, 2, 1,
-// CHECK-NEXT: /* 39 */ MCD::OPC_FilterValue, 2, 14, 0,              // Skip to: 57
-// CHECK-NEXT: /* 43 */ MCD::OPC_CheckField, 6, 6, 0, 4, 0,          // Skip to: 53
-// CHECK-NEXT: /* 49 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,           // Opcode: {{.*}}:NOP
-// CHECK-NEXT: /* 53 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, 2, 1,
-// CHECK-NEXT: /* 57 */ MCD::OPC_FilterValueOrFail, 3,
-// CHECK-NEXT: /* 59 */ MCD::OPC_CheckField, 6, 6, 0, 4, 0,          // Skip to: 69
-// CHECK-NEXT: /* 65 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,           // Opcode: {{.*}}:NOP
-// CHECK-NEXT: /* 69 */ MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, 2, 1,
+// CHECK:      /* 0 */  MCD::OPC_ExtractField, 12, 4,  // Inst{15-12} ...
+// CHECK-NEXT: /* 3 */  MCD::OPC_FilterValueOrSkip, 0, 15, 0, // Skip to: 22
+// CHECK-NEXT: /* 7 */  MCD::OPC_Scope, 8, 0, // Skip to: 18
+// CHECK-NEXT: /* 10 */ MCD::OPC_CheckField, 6, 6, 0,
+// CHECK-NEXT: /* 14 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
+// CHECK-NEXT: /* 18 */ MCD::OPC_TryDecode, 187, 2, 1,
+// CHECK-NEXT: /* 22 */ MCD::OPC_FilterValueOrSkip, 1, 15, 0, // Skip to: 41
+// CHECK-NEXT: /* 26 */ MCD::OPC_Scope, 8, 0, // Skip to: 37
+// CHECK-NEXT: /* 29 */ MCD::OPC_CheckField, 6, 6, 0,
+// CHECK-NEXT: /* 33 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
+// CHECK-NEXT: /* 37 */ MCD::OPC_TryDecode, 188, 2, 1,
+// CHECK-NEXT: /* 41 */ MCD::OPC_FilterValueOrSkip, 2, 15, 0, // Skip to: 60
+// CHECK-NEXT: /* 45 */ MCD::OPC_Scope, 8, 0, // Skip to: 56
+// CHECK-NEXT: /* 48 */ MCD::OPC_CheckField, 6, 6, 0,
+// CHECK-NEXT: /* 52 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
+// CHECK-NEXT: /* 56 */ MCD::OPC_TryDecode, 189, 2, 1,
+// CHECK-NEXT: /* 60 */ MCD::OPC_FilterValue, 3,
+// CHECK-NEXT: /* 62 */ MCD::OPC_Scope, 8, 0, // Skip to: 73
+// CHECK-NEXT: /* 65 */ MCD::OPC_CheckField, 6, 6, 0,
+// CHECK-NEXT: /* 69 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: {{.*}}:NOP, DecodeIdx: 0
+// CHECK-NEXT: /* 73 */ MCD::OPC_TryDecode, 190, 2, 1,
+
 
 class SHIFT<bits<2> opc> : I<(outs), (ins ShAmtOp:$shamt)>, EncSHIFT<opc>;
 def SHIFT0 : SHIFT<0>;
diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/big-filter.td b/llvm/test/TableGen/FixedLenDecoderEmitter/big-filter.td
index 7e2cda1bae9ed..28762bfa1ec24 100644
--- a/llvm/test/TableGen/FixedLenDecoderEmitter/big-filter.td
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/big-filter.td
@@ -12,13 +12,13 @@ class I : Instruction {
 // Check that a 64-bit filter with all bits set does not confuse DecoderEmitter.
 //
 // CHECK-LABEL: static const uint8_t DecoderTable128[34] = {
-// CHECK-NEXT:    MCD::OPC_ExtractField, 0, 64,
-// CHECK-NEXT:    MCD::OPC_FilterValue, 1, 8, 0,
-// CHECK-NEXT:    MCD::OPC_CheckFieldOrFail, 127, 1, 1,
-// CHECK-NEXT:    MCD::OPC_Decode, 187, 2, 0,
-// CHECK-NEXT:    MCD::OPC_FilterValueOrFail, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1,
-// CHECK-NEXT:    MCD::OPC_CheckFieldOrFail, 127, 1, 0,
-// CHECK-NEXT:    MCD::OPC_Decode, 186, 2, 0,
+// CHECK-NEXT:  /* 0 */  MCD::OPC_ExtractField, 0, 64,  // Inst{63-0} ...
+// CHECK-NEXT:  /* 3 */  MCD::OPC_FilterValueOrSkip, 1, 8, 0, // Skip to: 15
+// CHECK-NEXT:  /* 7 */  MCD::OPC_CheckField, 127, 1, 1,
+// CHECK-NEXT:  /* 11 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I2, DecodeIdx: 0
+// CHECK-NEXT:  /* 15 */ MCD::OPC_FilterValue, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1,
+// CHECK-NEXT:  /* 26 */ MCD::OPC_CheckField, 127, 1, 0,
+// CHECK-NEXT:  /* 30 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I1, DecodeIdx: 0
 // CHECK-NEXT:  };
 
 def I1 : I {
diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-1.td b/llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-1.td
index eda714eef1048..8afcf786f9c73 100644
--- a/llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-1.td
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/var-len-conflict-1.td
@@ -18,18 +18,19 @@ class I : Instruction {
 // 00000001 ________  I16_1
 // 00000010 ________  I16_2
 
-// CHECK:      MCD::OPC_ExtractField, 0, 1,       // Inst{0} ...
-// CHECK-NEXT: MCD::OPC_FilterValue, 0, 4, 0,     // Skip to: 11
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I8_0, DecodeIdx: 0
-// CHECK-NEXT: MCD::OPC_FilterValue, 1, 4, 0,     // Skip to: 19
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, 2, 0, // Opcode: I8_1, DecodeIdx: 0
-// CHECK-NEXT: MCD::OPC_ExtractField, 8, 8,       // Inst{15-8} ...
-// CHECK-NEXT: MCD::OPC_FilterValue, 0, 4, 0,     // Skip to: 30
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: I16_0, DecodeIdx: 1
-// CHECK-NEXT: MCD::OPC_FilterValue, 1, 4, 0,     // Skip to: 38
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: I16_1, DecodeIdx: 1
-// CHECK-NEXT: MCD::OPC_FilterValueOrFail, 2,
-// CHECK-NEXT: MCD::OPC_Decode, {{[0-9]+}}, 2, 1, // Opcode: I16_2, DecodeIdx: 1
+// CHECK:      /* 0 */  MCD::OPC_Scope, 17, 0,               // Skip to: 20
+// CHECK-NEXT: /* 3 */  MCD::OPC_ExtractField, 0, 1,         // Inst{0} ...
+// CHECK-NEXT: /* 6 */  MCD::OPC_FilterValueOrSkip, 0, 4, 0, // Skip to: 14
+// CHECK-NEXT: /* 10 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,   // Opcode: I8_0, DecodeIdx: 0
+// CHECK-NEXT: /* 14 */ MCD::OPC_FilterValue, 1,
+// CHECK-NEXT: /* 16 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 0,   // Opcode: I8_1, DecodeIdx: 0
+// CHECK-NEXT: /* 20 */ MCD::OPC_ExtractField, 8, 8,         // Inst{15-8} ...
+// CHECK-NEXT: /* 23 */ MCD::OPC_FilterValueOrSkip, 0, 4, 0, // Skip to: 31
+// CHECK-NEXT: /* 27 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 1,   // Opcode: I16_0, DecodeIdx: 1
+// CHECK-NEXT: /* 31 */ MCD::OPC_FilterValueOrSkip, 1, 4, 0, // Skip to: 39
+// CHECK-NEXT: /* 35 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 1,   // Opcode: I16_1, DecodeIdx: 1
+// CHECK-NEXT: /* 39 */ MCD::OPC_FilterValue, 2,
+// CHECK-NEXT: /* 41 */ MCD::OPC_Decode, {{[0-9]+}}, 2, 1,   // Opcode: I16_2, DecodeIdx: 1
 
 def I8_0  : I { dag Inst = (descend (operand "$op", 7), 0b0); }
 def I8_1  : I { dag Inst = (descend (operand "$op", 7), 0b1); }
diff --git a/llvm/test/TableGen/VarLenDecoder.td b/llvm/test/TableGen/VarLenDecoder.td
index 769c5895ec3c1..74eaa9d5ba631 100644
--- a/llvm/test/TableGen/VarLenDecoder.td
+++ b/llvm/test/TableGen/VarLenDecoder.td
@@ -48,16 +48,16 @@ def FOO32 : MyVarInst<MemOp32> {
 }
 
 // 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: /* 3 */       MCD::OPC_FilterValueOrSkip, 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: /* 11 */      MCD::OPC_FilterValue, 9,
 // CHECK-SMALL-NEXT: /* 13 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
 // CHECK-SMALL-NEXT: };
 
 // 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: /* 3 */       MCD::OPC_FilterValueOrSkip, 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_FilterValueOrFail, 9,
+// CHECK-LARGE-NEXT: /* 12 */      MCD::OPC_FilterValue, 9,
 // CHECK-LARGE-NEXT: /* 14 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: FOO32
 // CHECK-LARGE-NEXT: };
 
@@ -88,8 +88,7 @@ def FOO32 : MyVarInst<MemOp32> {
 // CHECK-LABEL: case MCD::OPC_ExtractField: {
 // CHECK: makeUp(insn, Start + Len);
 
-// CHECK-LABEL: case MCD::OPC_CheckField:
-// CHECK-NEXT:  case MCD::OPC_CheckFieldOrFail: {
+// CHECK-LABEL: case MCD::OPC_CheckField: {
 // 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 5d1c18fe65d0e..d1cf4bf541835 100644
--- a/llvm/test/TableGen/trydecode-emission.td
+++ b/llvm/test/TableGen/trydecode-emission.td
@@ -34,10 +34,11 @@ def InstB : TestInstruction {
   let hasCompleteDecoder = 0;
 }
 
-// CHECK:      /* 0 */       MCD::OPC_CheckFieldOrFail, 4, 4, 0,
-// CHECK-NEXT: /* 4 */       MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
-// CHECK-NEXT: /* 10 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
-// CHECK-NEXT: /* 16 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK:      /* 0 */       MCD::OPC_CheckField, 4, 4, 0,
+// CHECK-NEXT: /* 4 */       MCD::OPC_Scope, 8, 0, // Skip to: 15
+// CHECK-NEXT: /* 7 */       MCD::OPC_CheckField, 2, 2, 0,
+// CHECK-NEXT: /* 11 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-NEXT: /* 15 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-NEXT: };
 
 // CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
@@ -46,10 +47,11 @@ def InstB : TestInstruction {
 // CHECK-NEXT:  NumToSkip |= (*Ptr++) << 8;
 // CHECK-NEXT:  return NumToSkip;
 
-// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckFieldOrFail, 4, 4, 0,
-// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
-// CHECK-LARGE-NEXT: /* 11 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
-// CHECK-LARGE-NEXT: /* 18 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckField, 4, 4, 0,
+// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_Scope, 8, 0, 0, // Skip to: 16
+// CHECK-LARGE-NEXT: /* 8 */       MCD::OPC_CheckField, 2, 2, 0,
+// CHECK-LARGE-NEXT: /* 12 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-LARGE-NEXT: /* 16 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-LARGE-NEXT: };
 
 // 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 375be9ad13d19..d7a87eb4b8691 100644
--- a/llvm/test/TableGen/trydecode-emission2.td
+++ b/llvm/test/TableGen/trydecode-emission2.td
@@ -31,23 +31,24 @@ def InstB : TestInstruction {
   let hasCompleteDecoder = 0;
 }
 
-// CHECK:      /* 0 */       MCD::OPC_CheckFieldOrFail, 2, 1, 0,
-// CHECK-NEXT: /* 4 */       MCD::OPC_CheckFieldOrFail, 5, 3, 0,
-// CHECK-NEXT: /* 8 */       MCD::OPC_CheckField, 0, 2, 3, 6, 0, // Skip to: 20
-// CHECK-NEXT: /* 14 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
-// CHECK-NEXT: /* 20 */      MCD::OPC_CheckFieldOrFail, 3, 2, 0,
-// CHECK-NEXT: /* 24 */      MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
-// CHECK-NEXT: };
+// CHECK:      /* 0 */       MCD::OPC_CheckField, 2, 1, 0,
+// CHECK-NEXT: /* 4 */       MCD::OPC_CheckField, 5, 3, 0,
+// CHECK-NEXT: /* 8 */       MCD::OPC_Scope, 8, 0, // Skip to: 19
+// CHECK-NEXT: /* 11 */      MCD::OPC_CheckField, 0, 2, 3,
+// CHECK-NEXT: /* 15 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-NEXT: /* 19 */      MCD::OPC_CheckField, 3, 2, 0,
+// CHECK-NEXT: /* 23 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1,
 
 // 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_CheckFieldOrFail, 2, 1, 0,
-// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_CheckFieldOrFail, 5, 3, 0,
-// CHECK-LARGE-NEXT: /* 8 */       MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 22
-// CHECK-LARGE-NEXT: /* 15 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 22
-// CHECK-LARGE-NEXT: /* 22 */      MCD::OPC_CheckFieldOrFail, 3, 2, 0,
-// CHECK-LARGE-NEXT: /* 26 */      MCD::OPC_TryDecodeOrFail, {{[0-9]+}}, {{[0-9]+}}, 1,
+// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckField, 2, 1, 0,
+// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_CheckField, 5, 3, 0,
+// CHECK-LARGE-NEXT: /* 8 */       MCD::OPC_Scope, 8, 0, 0, // Skip to: 20
+// CHECK-LARGE-NEXT: /* 12 */      MCD::OPC_CheckField, 0, 2, 3,
+// CHECK-LARGE-NEXT: /* 16 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-LARGE-NEXT: /* 20 */      MCD::OPC_CheckField, 3, 2, 0,
+// CHECK-LARGE-NEXT: /* 24 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 1,
 // CHECK-LARGE-NEXT: };
 
 // CHECK-LARGE: if (!Check(S, DecodeInstB(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 9696724ce2836..b7d1b8ddc1b6c 100644
--- a/llvm/test/TableGen/trydecode-emission3.td
+++ b/llvm/test/TableGen/trydecode-emission3.td
@@ -35,18 +35,20 @@ def InstB : TestInstruction {
   let AsmString = "InstB";
 }
 
-// CHECK:      /* 0 */       MCD::OPC_CheckFieldOrFail, 4, 4, 0,
-// CHECK-NEXT: /* 4 */       MCD::OPC_CheckField, 2, 2, 0, 6, 0, // Skip to: 16
-// CHECK-NEXT: /* 10 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 16
-// CHECK-NEXT: /* 16 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA
+// CHECK:      /* 0 */       MCD::OPC_CheckField, 4, 4, 0,
+// CHECK-NEXT: /* 4 */       MCD::OPC_Scope, 8, 0, // Skip to: 15
+// CHECK-NEXT: /* 7 */       MCD::OPC_CheckField, 2, 2, 0,
+// CHECK-NEXT: /* 11 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-NEXT: /* 15 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-NEXT: };
 
 // CHECK: if (!Check(S, DecodeInstBOp(MI, tmp, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
 
-// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckFieldOrFail, 4, 4, 0,
-// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 18
-// CHECK-LARGE-NEXT: /* 11 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
-// CHECK-LARGE-NEXT: /* 18 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckField, 4, 4, 0,
+// CHECK-LARGE-NEXT: /* 4 */       MCD::OPC_Scope, 8, 0, 0, // Skip to: 16
+// CHECK-LARGE-NEXT: /* 8 */       MCD::OPC_CheckField, 2, 2, 0,
+// CHECK-LARGE-NEXT: /* 12 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-LARGE-NEXT: /* 16 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-LARGE-NEXT: };
 
 // 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 03cb635dbcaad..439bd9d4ff369 100644
--- a/llvm/test/TableGen/trydecode-emission4.td
+++ b/llvm/test/TableGen/trydecode-emission4.td
@@ -33,19 +33,21 @@ def InstB : TestInstruction {
   let hasCompleteDecoder = 0;
 }
 
-// CHECK:      /* 0 */       MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
-// CHECK-NEXT: /* 5 */       MCD::OPC_CheckField, 248, 3, 2, 0, 6, 0, // Skip to: 18
-// CHECK-NEXT: /* 12 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 18
-// CHECK-NEXT: /* 18 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK:      /* 0 */       MCD::OPC_CheckField, 250, 3, 4, 0,
+// CHECK-NEXT: /* 5 */       MCD::OPC_Scope, 9, 0, // Skip to: 17
+// CHECK-NEXT: /* 8 */       MCD::OPC_CheckField, 248, 3, 2, 0,
+// CHECK-NEXT: /* 13 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-NEXT: /* 17 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-NEXT: };
 
 // CHECK: if (!Check(S, DecodeInstB(MI, insn, Address, Decoder))) { DecodeComplete = false; return MCDisassembler::Fail; }
 
 
-// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckFieldOrFail, 250, 3, 4, 0,
-// CHECK-LARGE-NEXT: /* 5 */       MCD::OPC_CheckField, 248, 3, 2, 0, 7, 0, 0, // Skip to: 20
-// CHECK-LARGE-NEXT: /* 13 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, DecodeIdx: {{[0-9]+}}, Skip to: 20
-// CHECK-LARGE-NEXT: /* 20 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: {{[0-9]+}}
+// CHECK-LARGE:      /* 0 */       MCD::OPC_CheckField, 250, 3, 4, 0,
+// CHECK-LARGE-NEXT: /* 5 */       MCD::OPC_Scope, 9, 0, 0, // Skip to: 18
+// CHECK-LARGE-NEXT: /* 9 */       MCD::OPC_CheckField, 248, 3, 2, 0,
+// CHECK-LARGE-NEXT: /* 14 */      MCD::OPC_TryDecode, {{[0-9]+}}, {{[0-9]+}}, 0,
+// CHECK-LARGE-NEXT: /* 18 */      MCD::OPC_Decode, {{[0-9]+}}, {{[0-9]+}}, 1, // Opcode: InstA, DecodeIdx: 1
 // CHECK-LARGE-NEXT: };
 
 // 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 ecdc48775c9c1..0b9142a6de43a 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -242,8 +242,6 @@ class LessEncodingIDByWidth {
   }
 };
 
-typedef std::vector<uint32_t> FixupList;
-typedef std::vector<FixupList> FixupScopeList;
 typedef SmallSetVector<CachedHashString, 16> PredicateSet;
 typedef SmallSetVector<CachedHashString, 16> DecoderSet;
 
@@ -308,21 +306,17 @@ class DecoderTable {
 
 struct DecoderTableInfo {
   DecoderTable Table;
-  FixupScopeList FixupStack;
+  SmallVector<unsigned, 8> FixupStack;
   PredicateSet Predicates;
   DecoderSet Decoders;
 
-  bool isOutermostScope() const { return FixupStack.empty(); }
-
-  void pushScope() { FixupStack.emplace_back(); }
+  void pushScope() {
+    Table.insertOpcode(MCD::OPC_Scope);
+    FixupStack.push_back(Table.insertNumToSkip());
+  }
 
   void popScope() {
-    // Resolve any remaining fixups in the current scope before popping it.
-    // All fixups resolve to the current location.
-    uint32_t DestIdx = Table.size();
-    for (uint32_t FixupIdx : FixupStack.back())
-      Table.patchNumToSkip(FixupIdx, DestIdx);
-    FixupStack.pop_back();
+    Table.patchNumToSkip(FixupStack.pop_back_val(), Table.size());
   }
 };
 
@@ -771,6 +765,13 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
     default:
       PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
                       " at index " + Twine(Pos));
+    case MCD::OPC_Scope: {
+      OS << "  MCD::OPC_Scope, ";
+      uint32_t NumToSkip = emitNumToSkip(I, OS);
+      emitNumToSkipComment(NumToSkip);
+      OS << '\n';
+      break;
+    }
     case MCD::OPC_ExtractField: {
       OS << "  MCD::OPC_ExtractField, ";
 
@@ -787,24 +788,24 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
       OS << Start << "} ...\n";
       break;
     }
-    case MCD::OPC_FilterValue:
-    case MCD::OPC_FilterValueOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
-      OS << "  MCD::OPC_FilterValue" << (IsFail ? "OrFail, " : ", ");
+    case MCD::OPC_FilterValueOrSkip: {
+      OS << "  MCD::OPC_FilterValueOrSkip, ";
+      // The filter value is ULEB128 encoded.
+      emitULEB128(I, OS);
+      uint32_t NumToSkip = emitNumToSkip(I, OS);
+      emitNumToSkipComment(NumToSkip);
+      OS << '\n';
+      break;
+    }
+    case MCD::OPC_FilterValue: {
+      OS << "  MCD::OPC_FilterValue, ";
       // The filter value is ULEB128 encoded.
       emitULEB128(I, OS);
-
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
-      }
       OS << '\n';
       break;
     }
-    case MCD::OPC_CheckField:
-    case MCD::OPC_CheckFieldOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
-      OS << "  MCD::OPC_CheckField" << (IsFail ? "OrFail, " : ", ");
+    case MCD::OPC_CheckField: {
+      OS << "  MCD::OPC_CheckField, ";
       // ULEB128 encoded start value.
       emitULEB128(I, OS);
       // 8-bit length.
@@ -812,40 +813,24 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
       OS << Len << ", ";
       // ULEB128 encoded field value.
       emitULEB128(I, OS);
-
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
-      }
       OS << '\n';
       break;
     }
-    case MCD::OPC_CheckPredicate:
-    case MCD::OPC_CheckPredicateOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
-
-      OS << "  MCD::OPC_CheckPredicate" << (IsFail ? "OrFail, " : ", ");
+    case MCD::OPC_CheckPredicate: {
+      OS << "  MCD::OPC_CheckPredicate, ";
       emitULEB128(I, OS);
-
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
-      }
       OS << '\n';
       break;
     }
     case MCD::OPC_Decode:
-    case MCD::OPC_TryDecode:
-    case MCD::OPC_TryDecodeOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
-      bool IsTry = DecoderOp == MCD::OPC_TryDecode || IsFail;
+    case MCD::OPC_TryDecode: {
+      bool IsTry = DecoderOp == MCD::OPC_TryDecode;
       // Decode the Opcode value.
       const char *ErrMsg = nullptr;
       unsigned Opc = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
       assert(ErrMsg == nullptr && "ULEB128 value too large!");
 
-      OS << "  MCD::OPC_" << (IsTry ? "Try" : "") << "Decode"
-         << (IsFail ? "OrFail, " : ", ");
+      OS << "  MCD::OPC_" << (IsTry ? "Try" : "") << "Decode, ";
       emitULEB128(I, OS);
 
       // Decoder index.
@@ -862,14 +847,6 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
            << ", DecodeIdx: " << DecodeIdx << '\n';
         break;
       }
-
-      // Fallthrough for OPC_TryDecode.
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        OS << "// Opcode: " << Encodings[EncodingID].getName()
-           << ", DecodeIdx: " << DecodeIdx;
-        emitNumToSkipComment(NumToSkip, /*InComment=*/true);
-      }
       OS << '\n';
       break;
     }
@@ -1228,16 +1205,8 @@ void DecoderTableBuilder::emitPredicateTableEntry(unsigned EncodingID) const {
   // computed.
   unsigned PIdx = getPredicateIndex(PS.str());
 
-  const MCD::DecoderOps DecoderOp = TableInfo.isOutermostScope()
-                                        ? MCD::OPC_CheckPredicateOrFail
-                                        : MCD::OPC_CheckPredicate;
-  TableInfo.Table.insertOpcode(DecoderOp);
+  TableInfo.Table.insertOpcode(MCD::OPC_CheckPredicate);
   TableInfo.Table.insertULEB128(PIdx);
-
-  if (DecoderOp == MCD::OPC_CheckPredicate) {
-    // Push location for NumToSkip backpatching.
-    TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
-  }
 }
 
 void DecoderTableBuilder::emitSoftFailTableEntry(unsigned EncodingID) const {
@@ -1290,21 +1259,10 @@ void DecoderTableBuilder::emitSingletonTableEntry(
 
   // Check any additional encoding fields needed.
   for (const FilterChooser::Island &Ilnd : reverse(Islands)) {
-    const MCD::DecoderOps DecoderOp = TableInfo.isOutermostScope()
-                                          ? MCD::OPC_CheckFieldOrFail
-                                          : MCD::OPC_CheckField;
-    TableInfo.Table.insertOpcode(DecoderOp);
+    TableInfo.Table.insertOpcode(MCD::OPC_CheckField);
     TableInfo.Table.insertULEB128(Ilnd.StartBit);
     TableInfo.Table.insertUInt8(Ilnd.NumBits);
     TableInfo.Table.insertULEB128(Ilnd.FieldVal);
-
-    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());
-    }
   }
 
   // Check for soft failure of the match.
@@ -1322,18 +1280,11 @@ void DecoderTableBuilder::emitSingletonTableEntry(
   // if there is any other instruction that also matches the bitpattern and
   // can decode it.
   const MCD::DecoderOps DecoderOp =
-      Encoding.hasCompleteDecoder()  ? MCD::OPC_Decode
-      : TableInfo.isOutermostScope() ? MCD::OPC_TryDecodeOrFail
-                                     : MCD::OPC_TryDecode;
+      Encoding.hasCompleteDecoder() ? MCD::OPC_Decode : MCD::OPC_TryDecode;
   TableInfo.Table.insertOpcode(DecoderOp);
   const Record *InstDef = Encodings[EncodingID].getInstruction()->TheDef;
   TableInfo.Table.insertULEB128(Target.getInstrIntValue(InstDef));
   TableInfo.Table.insertULEB128(DIdx);
-
-  if (DecoderOp == MCD::OPC_TryDecode) {
-    // Push location for NumToSkip backpatching.
-    TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
-  }
 }
 
 // reportRegion is a helper function for filterProcessor to mark a region as
@@ -1646,14 +1597,10 @@ void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
     // If there is only one possible field value, emit a combined OPC_CheckField
     // instead of OPC_ExtractField + OPC_FilterValue.
     const auto &[FilterVal, Delegate] = *FC.FilterChooserMap.begin();
-    Table.insertOpcode(!TableInfo.isOutermostScope()
-                           ? MCD::OPC_CheckField
-                           : MCD::OPC_CheckFieldOrFail);
+    Table.insertOpcode(MCD::OPC_CheckField);
     Table.insertULEB128(FC.StartBit);
     Table.insertUInt8(FC.NumBits);
     Table.insertULEB128(FilterVal);
-    if (!TableInfo.isOutermostScope())
-      TableInfo.FixupStack.back().push_back(TableInfo.Table.insertNumToSkip());
 
     // Emit table entries for the only case.
     emitTableEntries(*Delegate);
@@ -1665,26 +1612,22 @@ void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
 
     // Emit switch cases for all but the last element.
     for (const auto &[FilterVal, Delegate] : drop_end(FC.FilterChooserMap)) {
-      Table.insertOpcode(MCD::OPC_FilterValue);
+      Table.insertOpcode(MCD::OPC_FilterValueOrSkip);
       Table.insertULEB128(FilterVal);
       size_t FixupPos = Table.insertNumToSkip();
 
       // Emit table entries for this case.
       emitTableEntries(*Delegate);
 
-      // Patch the previous OPC_FilterValue to fall through to the next case.
+      // Patch the previous FilterValueOrSkip to fall through to the next case.
       Table.patchNumToSkip(FixupPos, Table.size());
     }
 
     // Emit a switch case for the last element. It never falls through;
     // if it doesn't match, we leave the current scope.
     const auto &[FilterVal, Delegate] = *FC.FilterChooserMap.rbegin();
-    Table.insertOpcode(!TableInfo.isOutermostScope()
-                           ? MCD::OPC_FilterValue
-                           : MCD::OPC_FilterValueOrFail);
+    Table.insertOpcode(MCD::OPC_FilterValue);
     Table.insertULEB128(FilterVal);
-    if (!TableInfo.isOutermostScope())
-      TableInfo.FixupStack.back().push_back(Table.insertNumToSkip());
 
     // Emit table entries for the last case.
     emitTableEntries(*Delegate);
@@ -2108,11 +2051,8 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
 // decodeInstruction().
 static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst,
                                   unsigned OpcodeMask) {
-  const bool HasTryDecode = OpcodeMask & ((1 << MCD::OPC_TryDecode) |
-                                          (1 << MCD::OPC_TryDecodeOrFail));
-  const bool HasCheckPredicate =
-      OpcodeMask &
-      ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+  const bool HasTryDecode = OpcodeMask & (1 << MCD::OPC_TryDecode);
+  const bool HasCheckPredicate = OpcodeMask & (1 << MCD::OPC_CheckPredicate);
   const bool HasSoftFail = OpcodeMask & (1 << MCD::OPC_SoftFail);
 
   OS << R"(
@@ -2140,6 +2080,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
   OS << "  using namespace llvm::MCD;\n";
 
   OS << R"(
+  SmallVector<const uint8_t *, 8> ScopeStack;
   const uint8_t *Ptr = DecodeTable;
   uint64_t CurFieldValue = 0;
   DecodeStatus S = MCDisassembler::Success;
@@ -2151,6 +2092,14 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
       errs() << Loc << ": Unexpected decode table opcode: "
              << (int)DecoderOp << '\n';
       return MCDisassembler::Fail;
+    case MCD::OPC_Scope: {
+      unsigned NumToSkip = decodeNumToSkip(Ptr);
+      const uint8_t *SkipTo = Ptr + NumToSkip;
+      ScopeStack.push_back(SkipTo);
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_Scope(" << SkipTo - DecodeTable
+                        << ")\n");
+      break;
+    }
     case MCD::OPC_ExtractField: {
       // Decode the start value.
       unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
@@ -2163,34 +2112,42 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
                    << Len << "): " << CurFieldValue << "\n");
       break;
     }
-    case MCD::OPC_FilterValue:
-    case MCD::OPC_FilterValueOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
+    case MCD::OPC_FilterValueOrSkip: {
+      // Decode the field value.
+      uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
+      bool Failed = Val != CurFieldValue;
+      unsigned NumToSkip = decodeNumToSkip(Ptr);
+      const uint8_t *SkipTo = Ptr + NumToSkip;
+
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValueOrSkip(" << Val << ", "
+                        << SkipTo - DecodeTable << ") "
+                        << (Failed ? "FAIL, " : "PASS\n"));
+
+      if (Failed) {
+        Ptr = SkipTo;
+        LLVM_DEBUG(dbgs() << "continuing at " << Ptr - DecodeTable << '\n');
+      }
+      break;
+    }
+    case MCD::OPC_FilterValue: {
       // Decode the field value.
       uint64_t Val = decodeULEB128AndIncUnsafe(Ptr);
       bool Failed = Val != CurFieldValue;
-      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.
+
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ") "
+                        << (Failed ? "FAIL, " : "PASS\n"));
+
       if (Failed) {
-        if (IsFail)
+        if (ScopeStack.empty()) {
+          LLVM_DEBUG(dbgs() << "returning Fail\n");
           return MCDisassembler::Fail;
-        Ptr += NumToSkip;
+        }
+        Ptr = ScopeStack.pop_back_val();
+        LLVM_DEBUG(dbgs() << "continuing at " << Ptr - DecodeTable << '\n');
       }
       break;
     }
-    case MCD::OPC_CheckField:
-    case MCD::OPC_CheckFieldOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
+    case MCD::OPC_CheckField: {
       // Decode the start value.
       unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
       unsigned Len = *Ptr;)";
@@ -2203,45 +2160,39 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
       uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);
       Ptr += PtrLen;
       bool Failed = ExpectedValue != FieldValue;
-      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.
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", " << Len
+                        << ", " << ExpectedValue << "): FieldValue = "
+                        << FieldValue << ", ExpectedValue = " << ExpectedValue
+                        << ": " << (Failed ? "FAIL, " : "PASS\n"););
       if (Failed) {
-        if (IsFail)
+        if (ScopeStack.empty()) {
+          LLVM_DEBUG(dbgs() << "returning Fail\n");
           return MCDisassembler::Fail;
-        Ptr += NumToSkip;
+        }
+        Ptr = ScopeStack.pop_back_val();
+        LLVM_DEBUG(dbgs() << "continuing at " << Ptr - DecodeTable << '\n');
       }
       break;
     })";
   if (HasCheckPredicate) {
     OS << R"(
-    case MCD::OPC_CheckPredicate:
-    case MCD::OPC_CheckPredicateOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
+    case MCD::OPC_CheckPredicate: {
       // Decode the Predicate Index value.
       unsigned PIdx = decodeULEB128AndIncUnsafe(Ptr);
-      unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
       // Check the predicate.
       bool Failed = !checkDecoderPredicate(PIdx, Bits);
 
-      LLVM_DEBUG({
-        StringRef OpName = IsFail ? "OPC_CheckPredicateOrFail" : "OPC_CheckPredicate";
-        dbgs() << Loc << ": " << OpName << '(' << PIdx << ", " << NumToSkip
-               << "): " << (Failed ? "FAIL\n" : "PASS\n");
-      });
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): "
+                        << (Failed ? "FAIL, " : "PASS\n"););
 
       if (Failed) {
-        if (IsFail)
+        if (ScopeStack.empty()) {
+          LLVM_DEBUG(dbgs() << "returning Fail\n");
           return MCDisassembler::Fail;
-        Ptr += NumToSkip;
+        }
+        Ptr = ScopeStack.pop_back_val();
+        LLVM_DEBUG(dbgs() << "continuing at " << Ptr - DecodeTable << '\n');
       }
       break;
     })";
@@ -2270,13 +2221,10 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
     })";
   if (HasTryDecode) {
     OS << R"(
-    case MCD::OPC_TryDecode:
-    case MCD::OPC_TryDecodeOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
+    case MCD::OPC_TryDecode: {
       // Decode the Opcode value.
       unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
       unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
-      unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
 
       // Perform the decode operation.
       MCInst TmpMI;
@@ -2293,13 +2241,12 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
         return S;
       }
       assert(S == MCDisassembler::Fail);
-      if (IsFail) {
-        LLVM_DEBUG(dbgs() << "FAIL: returning FAIL\n");
+      if (ScopeStack.empty()) {
+        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");
+      Ptr = ScopeStack.pop_back_val();
+      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;
@@ -2567,9 +2514,7 @@ namespace {
   if (IsVarLenInst)
     emitInstrLenTable(OS, InstrLen);
 
-  const bool HasCheckPredicate =
-      OpcodeMask &
-      ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+  const bool HasCheckPredicate = OpcodeMask & (1 << MCD::OPC_CheckPredicate);
 
   // Emit the predicate function.
   if (HasCheckPredicate)



More information about the llvm-commits mailing list