[llvm] [TableGen][DecoderEmitter] Rework table construction/emission (PR #155889)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 10:14:46 PDT 2025


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

None

>From 6b00a34d78b2cabeafa6ca3e2d637e405a89dc47 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Tue, 26 Aug 2025 11:46:30 +0300
Subject: [PATCH] [TableGen][DecoderEmitter] Completely rework table emission

---
 llvm/include/llvm/MC/MCDecoderOps.h           |   24 +-
 .../Disassembler/AMDGPUDisassembler.cpp       |    1 +
 .../BPF/Disassembler/BPFDisassembler.cpp      |    1 +
 .../CSKY/Disassembler/CSKYDisassembler.cpp    |    1 +
 .../Disassembler/HexagonDisassembler.cpp      |    1 +
 .../Lanai/Disassembler/LanaiDisassembler.cpp  |    1 +
 .../Disassembler/LoongArchDisassembler.cpp    |    1 +
 .../PowerPC/Disassembler/PPCDisassembler.cpp  |    1 +
 .../Disassembler/SystemZDisassembler.cpp      |    1 +
 .../Disassembler/XtensaDisassembler.cpp       |    1 +
 llvm/utils/TableGen/DecoderEmitter.cpp        | 1456 ++++++++---------
 11 files changed, 686 insertions(+), 803 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDecoderOps.h b/llvm/include/llvm/MC/MCDecoderOps.h
index d2e7cbf27b04b..4e06deb0eacee 100644
--- a/llvm/include/llvm/MC/MCDecoderOps.h
+++ b/llvm/include/llvm/MC/MCDecoderOps.h
@@ -13,23 +13,15 @@
 namespace llvm::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, 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(uleb128 Size)
+  OPC_SwitchField,    // OPC_SwitchField(uleb128 Start, uint8_t Len,
+                      //                 [uleb128 Val, uleb128 Size]...)
+  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/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 6a2beeed41dfd..aebabab1a0cf5 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -38,6 +38,7 @@
 #include "llvm/Support/Compiler.h"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "amdgpu-disassembler"
 
diff --git a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
index b5bb1c08c5644..90974f3f79e91 100644
--- a/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
+++ b/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
@@ -26,6 +26,7 @@
 #include <cstdint>
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "bpf-disassembler"
 
diff --git a/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp b/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
index 749127f4ddc8a..e3f802d8bd47a 100644
--- a/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
+++ b/llvm/lib/Target/CSKY/Disassembler/CSKYDisassembler.cpp
@@ -26,6 +26,7 @@
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "csky-disassembler"
 
diff --git a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
index de10092cbe3c8..dca3dde5e9948 100644
--- a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
+++ b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp
@@ -34,6 +34,7 @@
 #define DEBUG_TYPE "hexagon-disassembler"
 
 using namespace llvm;
+using namespace llvm::MCD;
 using namespace Hexagon;
 
 using DecodeStatus = MCDisassembler::DecodeStatus;
diff --git a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
index 9cd0636306b16..96feaf28d0a0f 100644
--- a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
+++ b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
@@ -28,6 +28,7 @@
 #define DEBUG_TYPE "lanai-disassembler"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 typedef MCDisassembler::DecodeStatus DecodeStatus;
 
diff --git a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
index 735f798afde24..d4058fac4304a 100644
--- a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
+++ b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
@@ -24,6 +24,7 @@
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "loongarch-disassembler"
 
diff --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
index 5e27f06c94f06..47586c417cfe3 100644
--- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
+++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 DEFINE_PPC_REGCLASSES
 
diff --git a/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp b/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
index 0b91aba67694f..a724c5a7f97c8 100644
--- a/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
+++ b/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp
@@ -20,6 +20,7 @@
 #include <cstdint>
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "systemz-disassembler"
 
diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index 396b00f7b8628..7d22a0489a951 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -25,6 +25,7 @@
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
+using namespace llvm::MCD;
 
 #define DEBUG_TYPE "Xtensa-disassembler"
 
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index a32f5f2d68171..392c06dd15be4 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -27,11 +27,11 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCDecoderOps.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/KnownBits.h"
@@ -79,12 +79,6 @@ static cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates(
             "significantly reducing Table Duplications")),
     cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat));
 
-static cl::opt<bool> LargeTable(
-    "large-decoder-table",
-    cl::desc("Use large decoder table format. This uses 24 bits for offset\n"
-             "in the table instead of the default 16 bits."),
-    cl::init(false), cl::cat(DisassemblerEmitterCat));
-
 static cl::opt<bool> UseFnTableInDecodeToMCInst(
     "use-fn-table-in-decode-to-mcinst",
     cl::desc(
@@ -100,8 +94,6 @@ STATISTIC(NumInstructions, "Number of instructions considered");
 STATISTIC(NumEncodingsSupported, "Number of encodings supported");
 STATISTIC(NumEncodingsOmitted, "Number of encodings omitted");
 
-static unsigned getNumToSkipInBytes() { return LargeTable ? 3 : 2; }
-
 /// Similar to KnownBits::print(), but allows you to specify a character to use
 /// to print unknown bits.
 static void printKnownBits(raw_ostream &OS, const KnownBits &Bits,
@@ -242,88 +234,142 @@ class LessEncodingIDByWidth {
   }
 };
 
-typedef std::vector<uint32_t> FixupList;
-typedef std::vector<FixupList> FixupScopeList;
-typedef SmallSetVector<CachedHashString, 16> PredicateSet;
-typedef SmallSetVector<CachedHashString, 16> DecoderSet;
+class DecoderTreeNode {
+public:
+  virtual ~DecoderTreeNode() = default;
+
+  enum KindTy {
+    AnyOf,
+    AllOf,
+    CheckField,
+    SwitchField,
+    CheckPredicate,
+    SoftFail,
+    Decode,
+  };
+
+  KindTy getKind() const { return Kind; }
+
+protected:
+  explicit DecoderTreeNode(KindTy Kind) : Kind(Kind) {}
+
+private:
+  KindTy Kind;
+};
+
+class AllOfNode : public DecoderTreeNode {
+  SmallVector<std::unique_ptr<DecoderTreeNode>, 0> Children;
 
-class DecoderTable {
 public:
-  DecoderTable() { Data.reserve(16384); }
+  AllOfNode() : DecoderTreeNode(AllOf) {}
 
-  void clear() { Data.clear(); }
-  size_t size() const { return Data.size(); }
-  const uint8_t *data() const { return Data.data(); }
+  void addChild(std::unique_ptr<DecoderTreeNode> N) {
+    Children.push_back(std::move(N));
+  }
+
+  // TODO: Provide an iterator that unwraps unique_ptr.
+  ArrayRef<std::unique_ptr<DecoderTreeNode>> getChildren() const {
+    return Children;
+  }
+};
 
-  using const_iterator = std::vector<uint8_t>::const_iterator;
-  const_iterator begin() const { return Data.begin(); }
-  const_iterator end() const { return Data.end(); }
+class AnyOfNode : public DecoderTreeNode {
+  SmallVector<std::unique_ptr<DecoderTreeNode>, 0> Children;
 
-  /// Inserts a state machine opcode into the table.
-  void insertOpcode(MCD::DecoderOps Opcode) { Data.push_back(Opcode); }
+public:
+  AnyOfNode() : DecoderTreeNode(AnyOf) {}
 
-  /// Inserts a uint8 encoded value into the table.
-  void insertUInt8(unsigned Value) {
-    assert(isUInt<8>(Value));
-    Data.push_back(Value);
+  void addChild(std::unique_ptr<DecoderTreeNode> N) {
+    Children.push_back(std::move(N));
   }
 
-  /// Inserts a ULEB128 encoded value into the table.
-  void insertULEB128(uint64_t Value) {
-    // Encode and emit the value to filter against.
-    uint8_t Buffer[16];
-    unsigned Len = encodeULEB128(Value, Buffer);
-    Data.insert(Data.end(), Buffer, Buffer + Len);
+  // TODO: Provide an iterator that unwraps unique_ptr.
+  ArrayRef<std::unique_ptr<DecoderTreeNode>> getChildren() const {
+    return Children;
   }
+};
 
-  // Insert space for `NumToSkip` and return the position
-  // in the table for patching.
-  size_t insertNumToSkip() {
-    size_t Size = Data.size();
-    Data.insert(Data.end(), getNumToSkipInBytes(), 0);
-    return Size;
+class SwitchFieldNode : public DecoderTreeNode {
+  unsigned StartBit;
+  unsigned NumBits;
+  std::map<uint64_t, std::unique_ptr<DecoderTreeNode>> Cases;
+
+public:
+  SwitchFieldNode(unsigned StartBit, unsigned NumBits)
+      : DecoderTreeNode(SwitchField), StartBit(StartBit), NumBits(NumBits) {}
+
+  void addCase(uint64_t Value, std::unique_ptr<DecoderTreeNode> N) {
+    Cases.try_emplace(Value, std::move(N));
   }
 
-  void patchNumToSkip(size_t FixupIdx, uint32_t DestIdx) {
-    // Calculate the distance from the byte following the fixup entry byte
-    // to the destination. The Target is calculated from after the
-    // `getNumToSkipInBytes()`-byte NumToSkip entry itself, so subtract
-    // `getNumToSkipInBytes()` from the displacement here to account for that.
-    assert(DestIdx >= FixupIdx + getNumToSkipInBytes() &&
-           "Expecting a forward jump in the decoding table");
-    uint32_t Delta = DestIdx - FixupIdx - getNumToSkipInBytes();
-    if (!isUIntN(8 * getNumToSkipInBytes(), Delta))
-      PrintFatalError(
-          "disassembler decoding table too large, try --large-decoder-table");
+  unsigned getStartBit() const { return StartBit; }
+
+  unsigned getNumBits() const { return NumBits; }
 
-    Data[FixupIdx] = static_cast<uint8_t>(Delta);
-    Data[FixupIdx + 1] = static_cast<uint8_t>(Delta >> 8);
-    if (getNumToSkipInBytes() == 3)
-      Data[FixupIdx + 2] = static_cast<uint8_t>(Delta >> 16);
+  // TODO: Provide an iterator that unwraps unique_ptr.
+  const std::map<uint64_t, std::unique_ptr<DecoderTreeNode>> &getCases() const {
+    return Cases;
   }
+};
 
-private:
-  std::vector<uint8_t> Data;
+class CheckFieldNode : public DecoderTreeNode {
+  unsigned StartBit;
+  unsigned NumBits;
+  uint64_t Value;
+
+public:
+  CheckFieldNode(unsigned StartBit, unsigned NumBits, uint64_t Value)
+      : DecoderTreeNode(CheckField), StartBit(StartBit), NumBits(NumBits),
+        Value(Value) {}
+
+  unsigned getStartBit() const { return StartBit; }
+
+  unsigned getNumBits() const { return NumBits; }
+
+  uint64_t getValue() const { return Value; }
 };
 
-struct DecoderTableInfo {
-  DecoderTable Table;
-  FixupScopeList FixupStack;
-  PredicateSet Predicates;
-  DecoderSet Decoders;
+class CheckPredicateNode : public DecoderTreeNode {
+  unsigned Index;
 
-  bool isOutermostScope() const { return FixupStack.empty(); }
+public:
+  explicit CheckPredicateNode(unsigned Index)
+      : DecoderTreeNode(CheckPredicate), Index(Index) {}
 
-  void pushScope() { FixupStack.emplace_back(); }
+  unsigned getPredicateIndex() const { return Index; }
+};
 
-  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();
-  }
+class SoftFailNode : public DecoderTreeNode {
+  uint64_t PositiveMask, NegativeMask;
+
+public:
+  explicit SoftFailNode(uint64_t PositiveMask, uint64_t NegativeMask)
+      : DecoderTreeNode(SoftFail), PositiveMask(PositiveMask),
+        NegativeMask(NegativeMask) {}
+
+  uint64_t getPositiveMask() const { return PositiveMask; }
+  uint64_t getNegativeMask() const { return NegativeMask; }
+};
+
+class DecodeNode : public DecoderTreeNode {
+  unsigned EncodingID;
+  unsigned Index;
+
+public:
+  DecodeNode(unsigned EncodingID, unsigned Index)
+      : DecoderTreeNode(Decode), EncodingID(EncodingID), Index(Index) {}
+
+  unsigned getEncodingID() const { return EncodingID; }
+
+  unsigned getDecoderIndex() const { return Index; }
+};
+
+typedef SmallSetVector<CachedHashString, 16> PredicateSet;
+typedef SmallSetVector<CachedHashString, 16> DecoderSet;
+
+struct DecoderTableInfo {
+  PredicateSet Predicates;
+  DecoderSet Decoders;
 };
 
 using NamespacesHwModesMap = std::map<std::string, std::set<unsigned>>;
@@ -344,11 +390,10 @@ class DecoderEmitter {
 
   const CodeGenTarget &getTarget() const { return Target; }
 
-  // Emit the decoder state machine table. Returns a mask of MCD decoder ops
-  // that were emitted.
-  unsigned emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
-                     StringRef Namespace, unsigned HwModeID, unsigned BitWidth,
-                     ArrayRef<unsigned> EncodingIDs) const;
+  // Emit the decoder state machine table.
+  void emitDecoderTable(formatted_raw_ostream &OS, const DecoderTreeNode *Tree,
+                        StringRef Namespace, unsigned HwModeID,
+                        unsigned BitWidth) const;
   void emitInstrLenTable(formatted_raw_ostream &OS,
                          ArrayRef<unsigned> InstrLen) const;
   void emitPredicateFunction(formatted_raw_ostream &OS,
@@ -456,47 +501,10 @@ enum bitAttr_t {
 /// decoding tree.  And each case is delegated to an inferior FilterChooser to
 /// decide what further remaining bits to look at.
 
-class FilterChooser {
-  // TODO: Unfriend by providing the necessary accessors.
-  friend class DecoderTableBuilder;
-
-  // Vector of encodings to choose our filter.
+class DecoderTreeBuilder {
+  const CodeGenTarget &Target;
   ArrayRef<InstructionEncoding> Encodings;
-
-  /// Encoding IDs for this filter chooser to work on.
-  /// Sorted by non-decreasing encoding width.
-  SmallVector<unsigned, 0> EncodingIDs;
-
-  // Array of bit values passed down from our parent.
-  // Set to all unknown for Parent == nullptr.
-  KnownBits FilterBits;
-
-  // Links to the FilterChooser above us in the decoding tree.
-  const FilterChooser *Parent;
-
-  /// If the selected filter matches multiple encodings, then this is the
-  /// starting position and the width of the filtered range.
-  unsigned StartBit;
-  unsigned NumBits;
-
-  /// If the selected filter matches multiple encodings, and there is
-  /// *exactly one* encoding in which all bits are known in the filtered range,
-  /// then this is the ID of that encoding.
-  /// Also used when there is only one encoding.
-  std::optional<unsigned> SingletonEncodingID;
-
-  /// If the selected filter matches multiple encodings, and there is
-  /// *at least one* encoding in which all bits are known in the filtered range,
-  /// then this is the FilterChooser created for the subset of encodings that
-  /// contain some unknown bits in the filtered range.
-  std::unique_ptr<const FilterChooser> VariableFC;
-
-  /// If the selected filter matches multiple encodings, and there is
-  /// *more than one* encoding in which all bits are known in the filtered
-  /// range, then this is a map of field values to FilterChoosers created for
-  /// the subset of encodings sharing that field value.
-  /// The "field value" here refers to the encoding bits in the filtered range.
-  std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
+  DecoderTableInfo &TableInfo;
 
   struct Island {
     unsigned StartBit;
@@ -504,124 +512,153 @@ class FilterChooser {
     uint64_t FieldVal;
   };
 
+  // Calculates the island(s) needed to decode the instruction.
+  // This returns a list of undecoded bits of an instructions, for example,
+  // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+  // decoded bits in order to verify that the instruction matches the Opcode.
+  static std::vector<Island> getIslands(const KnownBits &EncodingBits,
+                                        const KnownBits &FilterBits);
+
 public:
-  /// Constructs a top-level filter chooser.
-  FilterChooser(ArrayRef<InstructionEncoding> Encodings,
-                ArrayRef<unsigned> EncodingIDs)
-      : Encodings(Encodings), EncodingIDs(EncodingIDs), Parent(nullptr) {
-    // Sort encoding IDs once.
-    stable_sort(this->EncodingIDs, LessEncodingIDByWidth(Encodings));
-    // Filter width is the width of the smallest encoding.
-    unsigned FilterWidth = Encodings[this->EncodingIDs.front()].getBitWidth();
-    FilterBits = KnownBits(FilterWidth);
-    doFilter();
-  }
-
-  /// Constructs an inferior filter chooser.
-  FilterChooser(ArrayRef<InstructionEncoding> Encodings,
-                ArrayRef<unsigned> EncodingIDs, const KnownBits &FilterBits,
-                const FilterChooser &Parent)
-      : Encodings(Encodings), EncodingIDs(EncodingIDs), Parent(&Parent) {
-    // Inferior filter choosers are created from sorted array of encoding IDs.
-    assert(is_sorted(EncodingIDs, LessEncodingIDByWidth(Encodings)));
-    assert(!FilterBits.hasConflict() && "Broken filter");
-    // Filter width is the width of the smallest encoding.
-    unsigned FilterWidth = Encodings[EncodingIDs.front()].getBitWidth();
-    this->FilterBits = FilterBits.anyext(FilterWidth);
-    doFilter();
-  }
+  DecoderTreeBuilder(const CodeGenTarget &Target,
+                     ArrayRef<InstructionEncoding> Encodings,
+                     DecoderTableInfo &TableInfo)
+      : Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
 
-  FilterChooser(const FilterChooser &) = delete;
-  void operator=(const FilterChooser &) = delete;
+  std::unique_ptr<DecoderTreeNode>
+  buildTree(ArrayRef<unsigned> AllEncodingIDs,
+            KnownBits FilterBits = KnownBits());
 
-  /// Returns the width of the largest encoding.
-  unsigned getMaxEncodingWidth() const {
-    // The last encoding ID is the ID of an encoding with the largest width.
-    return Encodings[EncodingIDs.back()].getBitWidth();
-  }
+  DecoderTreeBuilder(const DecoderTreeBuilder &) = delete;
+  void operator=(const DecoderTreeBuilder &) = delete;
 
 private:
-  /// Applies the given filter to the set of encodings this FilterChooser
-  /// works with, creating inferior FilterChoosers as necessary.
-  void applyFilter(const Filter &F);
+  static void emitBinaryParser(raw_ostream &OS, indent Indent,
+                               const OperandInfo &OpInfo);
+  static void emitDecoder(raw_ostream &OS, indent Indent,
+                          const InstructionEncoding &Encoding);
+  unsigned getDecoderIndex(const InstructionEncoding &Encoding);
+
+  static bool emitPredicateMatchAux(StringRef PredicateNamespace,
+                                    const Init &Val, bool ParenIfBinOp,
+                                    raw_ostream &OS);
+  static bool emitPredicateMatch(StringRef PredicateNamespace, raw_ostream &OS,
+                                 const InstructionEncoding &Encoding);
+  unsigned getPredicateIndex(const InstructionEncoding &Encoding) const;
 
   /// dumpStack - dumpStack traverses the filter chooser chain and calls
   /// dumpFilterArray on each filter chooser up to the top level one.
-  void dumpStack(raw_ostream &OS, indent Indent, unsigned PadToWidth) const;
-
-  bool isPositionFiltered(unsigned Idx) const {
-    return FilterBits.Zero[Idx] || FilterBits.One[Idx];
-  }
-
-  // Calculates the island(s) needed to decode the instruction.
-  // This returns a list of undecoded bits of an instructions, for example,
-  // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
-  // decoded bits in order to verify that the instruction matches the Opcode.
-  std::vector<Island> getIslands(const KnownBits &EncodingBits) const;
+  void dumpStack(raw_ostream &OS, indent Indent, unsigned PadToWidth,
+                 const KnownBits &FilterBits) const;
 
   // reportRegion is a helper function for filterProcessor to mark a region as
   // eligible for use as a filter region.
-  void reportRegion(std::vector<std::unique_ptr<Filter>> &Filters, bitAttr_t RA,
+  void reportRegion(ArrayRef<unsigned> EncodingIDs,
+                    std::vector<std::unique_ptr<Filter>> &Filters, bitAttr_t RA,
                     unsigned StartBit, unsigned BitIndex,
                     bool AllowMixed) const;
 
   /// Scans the well-known encoding bits of the encodings and, builds up a list
   /// of candidate filters, and then returns the best one, if any.
-  std::unique_ptr<Filter> findBestFilter(ArrayRef<bitAttr_t> BitAttrs,
+  std::unique_ptr<Filter> findBestFilter(ArrayRef<unsigned> EncodingIDs,
+                                         const KnownBits &FilterBits,
+                                         ArrayRef<bitAttr_t> BitAttrs,
                                          bool AllowMixed,
                                          bool Greedy = true) const;
 
-  std::unique_ptr<Filter> findBestFilter() const;
-
-  // Decides on the best configuration of filter(s) to use in order to decode
-  // the instructions.  A conflict of instructions may occur, in which case we
-  // dump the conflict set to the standard error.
-  void doFilter();
+  std::unique_ptr<Filter> findBestFilter(ArrayRef<unsigned> EncodingIDs,
+                                         const KnownBits &FilterBits) const;
 
 public:
-  void dump() const;
+  void dump(ArrayRef<unsigned> EncodingIDs, const KnownBits &FilterBits) const;
 };
 
-class DecoderTableBuilder {
+class DecoderTableEmitter {
   const CodeGenTarget &Target;
   ArrayRef<InstructionEncoding> Encodings;
-  DecoderTableInfo &TableInfo;
+  formatted_raw_ostream OS;
+  unsigned IndexWidth;
+  unsigned CurrentIndex;
+  unsigned CommentIndex;
 
 public:
-  DecoderTableBuilder(const CodeGenTarget &Target,
-                      ArrayRef<InstructionEncoding> Encodings,
-                      DecoderTableInfo &TableInfo)
-      : Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
+  DecoderTableEmitter(const CodeGenTarget &Target,
+                      ArrayRef<InstructionEncoding> Encodings, raw_ostream &OS)
+      : Target(Target), Encodings(Encodings), OS(OS) {}
 
-  void buildTable(const FilterChooser &FC) const {
-    emitTableEntries(FC);
-    assert(TableInfo.FixupStack.empty() && "Fixup stack phasing error!");
-  }
+  void emitTable(StringRef TableName, const DecoderTreeNode *Root) {
+    unsigned TableSize = computeNodeSize(Root);
+    OS << "static const uint8_t " << TableName << "[" << TableSize << "] = {\n";
 
-private:
-  void emitBinaryParser(raw_ostream &OS, indent Indent,
-                        const OperandInfo &OpInfo) const;
+    // Calculate the number of decimal places for table indices
+    // as log10 of the table size.
+    IndexWidth = 1;
+    for (unsigned S = TableSize; S /= 10;)
+      ++IndexWidth;
 
-  void emitDecoder(raw_ostream &OS, indent Indent, unsigned EncodingID) const;
+    CurrentIndex = 0;
+    emitNode(Root, indent(0));
+    assert(CurrentIndex == TableSize &&
+           "The size of the emitted table differs from the calculated one");
 
-  unsigned getDecoderIndex(unsigned EncodingID) const;
+    OS << "};\n";
+  }
 
-  unsigned getPredicateIndex(StringRef P) const;
+private:
+  unsigned computeNodeSize(const DecoderTreeNode *N) const;
 
-  bool emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp,
-                             raw_ostream &OS) const;
+  void emitStartLine() {
+    CommentIndex = CurrentIndex;
+    OS.indent(2);
+  }
 
-  bool emitPredicateMatch(raw_ostream &OS, unsigned EncodingID) const;
+  void emitOpcode(StringRef Name) {
+    emitStartLine();
+    OS << Name << ", ";
+    ++CurrentIndex;
+  }
 
-  bool doesOpcodeNeedPredicate(unsigned EncodingID) const;
+  void emitByte(uint8_t Val) {
+    OS << static_cast<unsigned>(Val) << ", ";
+    ++CurrentIndex;
+  }
 
-  void emitPredicateTableEntry(unsigned EncodingID) const;
+  void emitUInt8(unsigned Val) {
+    assert(isUInt<8>(Val));
+    emitByte(Val);
+  }
 
-  void emitSoftFailTableEntry(unsigned EncodingID) const;
+  void emitUInt16(unsigned Val) {
+    assert(isUInt<16>(Val));
+    emitByte(Val & 0xFF);
+    emitByte(Val >> 8);
+  }
 
-  void emitSingletonTableEntry(const FilterChooser &FC) const;
+  void emitULEB128(uint64_t Val) {
+    while (Val >= 0x80) {
+      emitByte((Val & 0x7F) | 0x80);
+      Val >>= 7;
+    }
+    emitByte(Val);
+  }
 
-  void emitTableEntries(const FilterChooser &FC) const;
+  formatted_raw_ostream &emitComment(indent Indent) {
+    constexpr unsigned CommentColumn = 40;
+    if (OS.getColumn() > CommentColumn)
+      OS << '\n';
+    OS.PadToColumn(CommentColumn);
+    OS << "// " << format_decimal(CommentIndex, IndexWidth) << ": " << Indent;
+    return OS;
+  }
+
+  void emitAnyOfNode(const AnyOfNode *N, indent Indent);
+  void emitAllOfNode(const AllOfNode *N, indent Indent);
+  void emitSwitchFieldNode(const SwitchFieldNode *N, indent Indent);
+  void emitCheckFieldNode(const CheckFieldNode *N, indent Indent);
+  void emitCheckPredicateNode(const CheckPredicateNode *N, indent Indent);
+  void emitSoftFailNode(const SoftFailNode *N, indent Indent);
+  void emitDecodeNode(const DecodeNode *N, indent Indent);
+  void emitNode(const DecoderTreeNode *N, indent Indent);
 };
 
 } // end anonymous namespace
@@ -658,245 +695,132 @@ Filter::Filter(ArrayRef<InstructionEncoding> Encodings,
          "Filter returns no instruction categories");
 }
 
-void FilterChooser::applyFilter(const Filter &F) {
-  StartBit = F.StartBit;
-  NumBits = F.NumBits;
-  assert(FilterBits.extractBits(NumBits, StartBit).isUnknown());
-
-  if (!F.VariableIDs.empty()) {
-    // Delegates to an inferior filter chooser for further processing on this
-    // group of instructions whose segment values are variable.
-    VariableFC = std::make_unique<FilterChooser>(Encodings, F.VariableIDs,
-                                                 FilterBits, *this);
-  }
-
-  // Otherwise, create sub choosers.
-  for (const auto &[FilterVal, InferiorEncodingIDs] : F.FilteredIDs) {
-    // Create a new filter by inserting the field bits into the parent filter.
-    APInt FieldBits(NumBits, FilterVal);
-    KnownBits InferiorFilterBits = FilterBits;
-    InferiorFilterBits.insertBits(KnownBits::makeConstant(FieldBits), StartBit);
-
-    // Delegates to an inferior filter chooser for further processing on this
-    // category of instructions.
-    FilterChooserMap.try_emplace(FilterVal, std::make_unique<FilterChooser>(
-                                                Encodings, InferiorEncodingIDs,
-                                                InferiorFilterBits, *this));
-  }
-}
-
 // Returns the number of fanout produced by the filter.  More fanout implies
 // the filter distinguishes more categories of instructions.
 unsigned Filter::usefulness() const {
   return FilteredIDs.size() + VariableIDs.empty();
 }
 
-//////////////////////////////////
-//                              //
-// Filterchooser Implementation //
-//                              //
-//////////////////////////////////
-
-// Emit the decoder state machine table. Returns a mask of MCD decoder ops
-// that were emitted.
-unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
-                                   DecoderTable &Table, StringRef Namespace,
-                                   unsigned HwModeID, unsigned BitWidth,
-                                   ArrayRef<unsigned> EncodingIDs) const {
-  // We'll need to be able to map from a decoded opcode into the corresponding
-  // EncodingID for this specific combination of BitWidth and Namespace. This
-  // is used below to index into Encodings.
-  DenseMap<unsigned, unsigned> OpcodeToEncodingID;
-  OpcodeToEncodingID.reserve(EncodingIDs.size());
-  for (unsigned EncodingID : EncodingIDs) {
-    const Record *InstDef = Encodings[EncodingID].getInstruction()->TheDef;
-    OpcodeToEncodingID[Target.getInstrIntValue(InstDef)] = EncodingID;
-  }
+static bool doesOpcodeNeedPredicate(const InstructionEncoding &Encoding);
 
-  OS << "static const uint8_t DecoderTable" << Namespace;
-  if (HwModeID != DefaultMode)
-    OS << '_' << Target.getHwModes().getModeName(HwModeID);
-  OS << BitWidth << "[" << Table.size() << "] = {\n";
-
-  // Emit ULEB128 encoded value to OS, returning the number of bytes emitted.
-  auto emitULEB128 = [](DecoderTable::const_iterator &I,
-                        formatted_raw_ostream &OS) {
-    while (*I >= 128)
-      OS << (unsigned)*I++ << ", ";
-    OS << (unsigned)*I++ << ", ";
-  };
-
-  // Emit `getNumToSkipInBytes()`-byte numtoskip value to OS, returning the
-  // NumToSkip value.
-  auto emitNumToSkip = [](DecoderTable::const_iterator &I,
-                          formatted_raw_ostream &OS) {
-    uint8_t Byte = *I++;
-    uint32_t NumToSkip = Byte;
-    OS << (unsigned)Byte << ", ";
-    Byte = *I++;
-    OS << (unsigned)Byte << ", ";
-    NumToSkip |= Byte << 8;
-    if (getNumToSkipInBytes() == 3) {
-      Byte = *I++;
-      OS << (unsigned)(Byte) << ", ";
-      NumToSkip |= Byte << 16;
-    }
-    return NumToSkip;
-  };
-
-  // FIXME: We may be able to use the NumToSkip values to recover
-  // appropriate indentation levels.
-  DecoderTable::const_iterator I = Table.begin();
-  DecoderTable::const_iterator E = Table.end();
-  const uint8_t *const EndPtr = Table.data() + Table.size();
+std::unique_ptr<DecoderTreeNode>
+DecoderTreeBuilder::buildTree(ArrayRef<unsigned int> AllEncodingIDs,
+                              KnownBits FilterBits) {
+  SmallVector<unsigned, 0> EncodingIDs(AllEncodingIDs);
+  stable_sort(EncodingIDs, LessEncodingIDByWidth(Encodings));
 
-  auto emitNumToSkipComment = [&](uint32_t NumToSkip, bool InComment = false) {
-    uint32_t Index = ((I - Table.begin()) + NumToSkip);
-    OS << (InComment ? ", " : "// ");
-    OS << "Skip to: " << Index;
-  };
+  auto AnyOf = std::make_unique<AnyOfNode>();
+  while (!EncodingIDs.empty()) {
+    // Filter width is the width of the smallest encoding.
+    unsigned FilterWidth = Encodings[EncodingIDs.front()].getBitWidth();
+    FilterBits = FilterBits.anyext(FilterWidth);
 
-  unsigned OpcodeMask = 0;
+    if (EncodingIDs.size() == 1) {
+      unsigned EncodingID = EncodingIDs.front();
+      const InstructionEncoding &Encoding = Encodings[EncodingID];
 
-  while (I != E) {
-    assert(I < E && "incomplete decode table entry!");
+      auto AllOf = std::make_unique<AllOfNode>();
 
-    uint64_t Pos = I - Table.begin();
-    OS << "/* " << Pos << " */";
-    OS.PadToColumn(12);
+      if (doesOpcodeNeedPredicate(Encoding)) {
+        unsigned PredicateIndex = getPredicateIndex(Encoding);
+        auto CheckPredicate =
+            std::make_unique<CheckPredicateNode>(PredicateIndex);
+        AllOf->addChild(std::move(CheckPredicate));
+      }
 
-    const uint8_t DecoderOp = *I++;
-    OpcodeMask |= (1 << DecoderOp);
-    switch (DecoderOp) {
-    default:
-      PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
-                      " at index " + Twine(Pos));
-    case MCD::OPC_ExtractField: {
-      OS << "  MCD::OPC_ExtractField, ";
-
-      // ULEB128 encoded start value.
-      const char *ErrMsg = nullptr;
-      unsigned Start = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
-      assert(ErrMsg == nullptr && "ULEB128 value too large!");
-      emitULEB128(I, OS);
-
-      unsigned Len = *I++;
-      OS << Len << ",  // Inst{";
-      if (Len > 1)
-        OS << (Start + Len - 1) << "-";
-      OS << Start << "} ...\n";
-      break;
-    }
-    case MCD::OPC_FilterValue:
-    case MCD::OPC_FilterValueOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_FilterValueOrFail;
-      OS << "  MCD::OPC_FilterValue" << (IsFail ? "OrFail, " : ", ");
-      // The filter value is ULEB128 encoded.
-      emitULEB128(I, OS);
-
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
+      std::vector<Island> Islands =
+          getIslands(Encoding.getMandatoryBits(), FilterBits);
+      for (const Island &Ilnd : reverse(Islands)) {
+        auto CheckField = std::make_unique<CheckFieldNode>(
+            Ilnd.StartBit, Ilnd.NumBits, Ilnd.FieldVal);
+        AllOf->addChild(std::move(CheckField));
       }
-      OS << '\n';
-      break;
-    }
-    case MCD::OPC_CheckField:
-    case MCD::OPC_CheckFieldOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckFieldOrFail;
-      OS << "  MCD::OPC_CheckField" << (IsFail ? "OrFail, " : ", ");
-      // ULEB128 encoded start value.
-      emitULEB128(I, OS);
-      // 8-bit length.
-      unsigned Len = *I++;
-      OS << Len << ", ";
-      // ULEB128 encoded field value.
-      emitULEB128(I, OS);
-
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
+
+      {
+        const KnownBits &InstBits = Encoding.getInstBits();
+        const APInt &SFMask = Encoding.getSoftFailMask();
+        if (!SFMask.isZero()) {
+          APInt PositiveMask = InstBits.Zero & SFMask;
+          APInt NegativeMask = InstBits.One & SFMask;
+          auto SoftFail = std::make_unique<SoftFailNode>(
+              PositiveMask.getZExtValue(), NegativeMask.getZExtValue());
+          AllOf->addChild(std::move(SoftFail));
+        }
       }
-      OS << '\n';
-      break;
-    }
-    case MCD::OPC_CheckPredicate:
-    case MCD::OPC_CheckPredicateOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
 
-      OS << "  MCD::OPC_CheckPredicate" << (IsFail ? "OrFail, " : ", ");
-      emitULEB128(I, OS);
+      unsigned DecoderIndex = getDecoderIndex(Encoding);
+      auto Decode = std::make_unique<DecodeNode>(EncodingID, DecoderIndex);
+      AllOf->addChild(std::move(Decode));
 
-      if (!IsFail) {
-        uint32_t NumToSkip = emitNumToSkip(I, OS);
-        emitNumToSkipComment(NumToSkip);
-      }
-      OS << '\n';
+      AnyOf->addChild(std::move(AllOf));
       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;
-      // 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, " : ", ");
-      emitULEB128(I, OS);
-
-      // Decoder index.
-      unsigned DecodeIdx = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
-      assert(ErrMsg == nullptr && "ULEB128 value too large!");
-      emitULEB128(I, OS);
-
-      auto EncI = OpcodeToEncodingID.find(Opc);
-      assert(EncI != OpcodeToEncodingID.end() && "no encoding entry");
-      auto EncodingID = EncI->second;
-
-      if (!IsTry) {
-        OS << "// Opcode: " << Encodings[EncodingID].getName()
-           << ", 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;
-    }
-    case MCD::OPC_SoftFail: {
-      OS << "  MCD::OPC_SoftFail, ";
-      // Decode the positive mask.
-      const char *ErrMsg = nullptr;
-      uint64_t PositiveMask = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
-      assert(ErrMsg == nullptr && "ULEB128 value too large!");
-      emitULEB128(I, OS);
-
-      // Decode the negative mask.
-      uint64_t NegativeMask = decodeULEB128(&*I, nullptr, EndPtr, &ErrMsg);
-      assert(ErrMsg == nullptr && "ULEB128 value too large!");
-      emitULEB128(I, OS);
-      OS << "// +ve mask: 0x";
-      OS.write_hex(PositiveMask);
-      OS << ", -ve mask: 0x";
-      OS.write_hex(NegativeMask);
-      OS << '\n';
-      break;
+    std::unique_ptr<Filter> BestFilter =
+        findBestFilter(EncodingIDs, FilterBits);
+    if (!BestFilter) {
+      // Print out useful conflict information for postmortem analysis.
+      errs() << "Decoding Conflict:\n";
+      dump(EncodingIDs, FilterBits);
+      PrintFatalError("Decoding conflict encountered");
+      return nullptr;
     }
+
+    const Filter &F = *BestFilter;
+    assert(FilterBits.extractBits(F.NumBits, F.StartBit).isUnknown());
+
+    std::unique_ptr<DecoderTreeNode> Child;
+    assert(!F.FilteredIDs.empty() && "Useless filter");
+    if (F.FilteredIDs.size() == 1) {
+      const auto &[FilterVal, InferiorEncodingIDs] = *F.FilteredIDs.begin();
+      APInt FieldBits(F.NumBits, FilterVal);
+      KnownBits InferiorFilterBits = FilterBits;
+      InferiorFilterBits.insertBits(KnownBits::makeConstant(FieldBits),
+                                    F.StartBit);
+
+      auto CheckField =
+          std::make_unique<CheckFieldNode>(F.StartBit, F.NumBits, FilterVal);
+      auto AllOf = std::make_unique<AllOfNode>();
+      AllOf->addChild(std::move(CheckField));
+      AllOf->addChild(buildTree(InferiorEncodingIDs, InferiorFilterBits));
+      Child = std::move(AllOf);
+    } else {
+      auto SwitchField =
+          std::make_unique<SwitchFieldNode>(F.StartBit, F.NumBits);
+      for (const auto &[FilterVal, InferiorEncodingIDs] : F.FilteredIDs) {
+        // Create a new filter by inserting the field bits into the parent
+        // filter.
+        APInt FieldBits(F.NumBits, FilterVal);
+        KnownBits InferiorFilterBits = FilterBits;
+        InferiorFilterBits.insertBits(KnownBits::makeConstant(FieldBits),
+                                      F.StartBit);
+        std::unique_ptr<DecoderTreeNode> Case =
+            buildTree(InferiorEncodingIDs, InferiorFilterBits);
+        SwitchField->addCase(FilterVal, std::move(Case));
+      }
+      Child = std::move(SwitchField);
     }
+    AnyOf->addChild(std::move(Child));
+
+    EncodingIDs.assign(F.VariableIDs.begin(), F.VariableIDs.end());
   }
-  OS << "};\n\n";
 
-  return OpcodeMask;
+  return AnyOf;
+}
+
+// Emit the decoder state machine table.
+void DecoderEmitter::emitDecoderTable(formatted_raw_ostream &OS,
+                                      const DecoderTreeNode *Tree,
+                                      StringRef Namespace, unsigned HwModeID,
+                                      unsigned BitWidth) const {
+  SmallString<32> TableName("DecoderTable");
+  TableName.append(Namespace);
+  if (HwModeID != DefaultMode)
+    TableName.append({"_", Target.getHwModes().getModeName(HwModeID)});
+  TableName.append(std::to_string(BitWidth));
+
+  DecoderTableEmitter TableEmitter(Target, Encodings, OS);
+  TableEmitter.emitTable(TableName, Tree);
 }
 
 void DecoderEmitter::emitInstrLenTable(formatted_raw_ostream &OS,
@@ -989,10 +913,9 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS,
 
 /// dumpStack - dumpStack traverses the filter chooser chain and calls
 /// dumpFilterArray on each filter chooser up to the top level one.
-void FilterChooser::dumpStack(raw_ostream &OS, indent Indent,
-                              unsigned PadToWidth) const {
-  if (Parent)
-    Parent->dumpStack(OS, Indent, PadToWidth);
+void DecoderTreeBuilder::dumpStack(raw_ostream &OS, indent Indent,
+                                   unsigned PadToWidth,
+                                   const KnownBits &FilterBits) const {
   assert(PadToWidth >= FilterBits.getBitWidth());
   OS << Indent << indent(PadToWidth - FilterBits.getBitWidth());
   printKnownBits(OS, FilterBits, '.');
@@ -1003,8 +926,9 @@ void FilterChooser::dumpStack(raw_ostream &OS, indent Indent,
 // This returns a list of undecoded bits of an instructions, for example,
 // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
 // decoded bits in order to verify that the instruction matches the Opcode.
-std::vector<FilterChooser::Island>
-FilterChooser::getIslands(const KnownBits &EncodingBits) const {
+std::vector<DecoderTreeBuilder::Island>
+DecoderTreeBuilder::getIslands(const KnownBits &EncodingBits,
+                               const KnownBits &FilterBits) {
   std::vector<Island> Islands;
   uint64_t FieldVal;
   unsigned StartBit;
@@ -1017,7 +941,7 @@ FilterChooser::getIslands(const KnownBits &EncodingBits) const {
   unsigned FilterWidth = FilterBits.getBitWidth();
   for (unsigned i = 0; i != FilterWidth; ++i) {
     bool IsKnown = EncodingBits.Zero[i] || EncodingBits.One[i];
-    bool Filtered = isPositionFiltered(i);
+    bool Filtered = FilterBits.Zero[i] || FilterBits.One[i];
     switch (State) {
     default:
       llvm_unreachable("Unreachable code!");
@@ -1050,8 +974,8 @@ FilterChooser::getIslands(const KnownBits &EncodingBits) const {
   return Islands;
 }
 
-void DecoderTableBuilder::emitBinaryParser(raw_ostream &OS, indent Indent,
-                                           const OperandInfo &OpInfo) const {
+void DecoderTreeBuilder::emitBinaryParser(raw_ostream &OS, indent Indent,
+                                          const OperandInfo &OpInfo) {
   const std::string &Decoder = OpInfo.Decoder;
 
   bool UseInsertBits = OpInfo.numFields() != 1 || OpInfo.InitValue != 0;
@@ -1086,10 +1010,8 @@ void DecoderTableBuilder::emitBinaryParser(raw_ostream &OS, indent Indent,
   }
 }
 
-void DecoderTableBuilder::emitDecoder(raw_ostream &OS, indent Indent,
-                                      unsigned EncodingID) const {
-  const InstructionEncoding &Encoding = Encodings[EncodingID];
-
+void DecoderTreeBuilder::emitDecoder(raw_ostream &OS, indent Indent,
+                                     const InstructionEncoding &Encoding) {
   // If a custom instruction decoder was specified, use that.
   StringRef DecoderMethod = Encoding.getDecoderMethod();
   if (!DecoderMethod.empty()) {
@@ -1105,14 +1027,15 @@ void DecoderTableBuilder::emitDecoder(raw_ostream &OS, indent Indent,
       emitBinaryParser(OS, Indent, Op);
 }
 
-unsigned DecoderTableBuilder::getDecoderIndex(unsigned EncodingID) const {
+unsigned
+DecoderTreeBuilder::getDecoderIndex(const InstructionEncoding &Encoding) {
   // Build up the predicate string.
   SmallString<256> Decoder;
   // FIXME: emitDecoder() function can take a buffer directly rather than
   // a stream.
   raw_svector_ostream S(Decoder);
   indent Indent(UseFnTableInDecodeToMCInst ? 2 : 4);
-  emitDecoder(S, Indent, EncodingID);
+  emitDecoder(S, Indent, Encoding);
 
   // Using the full decoder string as the key value here is a bit
   // heavyweight, but is effective. If the string comparisons become a
@@ -1129,20 +1052,21 @@ unsigned DecoderTableBuilder::getDecoderIndex(unsigned EncodingID) const {
 }
 
 // If ParenIfBinOp is true, print a surrounding () if Val uses && or ||.
-bool DecoderTableBuilder::emitPredicateMatchAux(const Init &Val,
-                                                bool ParenIfBinOp,
-                                                raw_ostream &OS) const {
+bool DecoderTreeBuilder::emitPredicateMatchAux(StringRef PredicateNamespace,
+                                               const Init &Val,
+                                               bool ParenIfBinOp,
+                                               raw_ostream &OS) {
   if (const auto *D = dyn_cast<DefInit>(&Val)) {
     if (!D->getDef()->isSubClassOf("SubtargetFeature"))
       return true;
-    OS << "Bits[" << Target.getName() << "::" << D->getAsString() << "]";
+    OS << "Bits[" << PredicateNamespace << "::" << D->getAsString() << "]";
     return false;
   }
   if (const auto *D = dyn_cast<DagInit>(&Val)) {
     std::string Op = D->getOperator()->getAsString();
     if (Op == "not" && D->getNumArgs() == 1) {
       OS << '!';
-      return emitPredicateMatchAux(*D->getArg(0), true, OS);
+      return emitPredicateMatchAux(PredicateNamespace, *D->getArg(0), true, OS);
     }
     if ((Op == "any_of" || Op == "all_of") && D->getNumArgs() > 0) {
       bool Paren = D->getNumArgs() > 1 && std::exchange(ParenIfBinOp, true);
@@ -1151,7 +1075,7 @@ bool DecoderTableBuilder::emitPredicateMatchAux(const Init &Val,
       ListSeparator LS(Op == "any_of" ? " || " : " && ");
       for (auto *Arg : D->getArgs()) {
         OS << LS;
-        if (emitPredicateMatchAux(*Arg, ParenIfBinOp, OS))
+        if (emitPredicateMatchAux(PredicateNamespace, *Arg, ParenIfBinOp, OS))
           return true;
       }
       if (Paren)
@@ -1162,10 +1086,11 @@ bool DecoderTableBuilder::emitPredicateMatchAux(const Init &Val,
   return true;
 }
 
-bool DecoderTableBuilder::emitPredicateMatch(raw_ostream &OS,
-                                             unsigned EncodingID) const {
+bool DecoderTreeBuilder::emitPredicateMatch(
+    StringRef PredicateNamespace, raw_ostream &OS,
+    const InstructionEncoding &Encoding) {
   const ListInit *Predicates =
-      Encodings[EncodingID].getRecord()->getValueAsListInit("Predicates");
+      Encoding.getRecord()->getValueAsListInit("Predicates");
   bool IsFirstEmission = true;
   for (unsigned i = 0; i < Predicates->size(); ++i) {
     const Record *Pred = Predicates->getElementAsRecord(i);
@@ -1177,7 +1102,8 @@ bool DecoderTableBuilder::emitPredicateMatch(raw_ostream &OS,
 
     if (!IsFirstEmission)
       OS << " && ";
-    if (emitPredicateMatchAux(*Pred->getValueAsDag("AssemblerCondDag"),
+    if (emitPredicateMatchAux(PredicateNamespace,
+                              *Pred->getValueAsDag("AssemblerCondDag"),
                               Predicates->size() > 1, OS))
       PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
     IsFirstEmission = false;
@@ -1185,9 +1111,9 @@ bool DecoderTableBuilder::emitPredicateMatch(raw_ostream &OS,
   return !Predicates->empty();
 }
 
-bool DecoderTableBuilder::doesOpcodeNeedPredicate(unsigned EncodingID) const {
+static bool doesOpcodeNeedPredicate(const InstructionEncoding &Encoding) {
   const ListInit *Predicates =
-      Encodings[EncodingID].getRecord()->getValueAsListInit("Predicates");
+      Encoding.getRecord()->getValueAsListInit("Predicates");
   for (unsigned i = 0; i < Predicates->size(); ++i) {
     const Record *Pred = Predicates->getElementAsRecord(i);
     if (!Pred->getValue("AssemblerMatcherPredicate"))
@@ -1199,7 +1125,15 @@ bool DecoderTableBuilder::doesOpcodeNeedPredicate(unsigned EncodingID) const {
   return false;
 }
 
-unsigned DecoderTableBuilder::getPredicateIndex(StringRef Predicate) const {
+unsigned DecoderTreeBuilder::getPredicateIndex(
+    const InstructionEncoding &Encoding) const {
+  // Build up the predicate string.
+  SmallString<256> Predicate;
+  // FIXME: emitPredicateMatch() functions can take a buffer directly rather
+  // than a stream.
+  raw_svector_ostream PS(Predicate);
+  emitPredicateMatch(Target.getName(), PS, Encoding);
+
   // Using the full predicate string as the key value here is a bit
   // heavyweight, but is effective. If the string comparisons become a
   // performance concern, we can implement a mangling of the predicate
@@ -1207,129 +1141,27 @@ unsigned DecoderTableBuilder::getPredicateIndex(StringRef Predicate) const {
   // overkill for now, though.
 
   // Make sure the predicate is in the table.
-  TableInfo.Predicates.insert(CachedHashString(Predicate));
+  PredicateSet &Predicates = TableInfo.Predicates;
+  Predicates.insert(CachedHashString(Predicate));
   // Now figure out the index for when we write out the table.
-  PredicateSet::const_iterator P = find(TableInfo.Predicates, Predicate);
-  return (unsigned)(P - TableInfo.Predicates.begin());
-}
-
-void DecoderTableBuilder::emitPredicateTableEntry(unsigned EncodingID) const {
-  if (!doesOpcodeNeedPredicate(EncodingID))
-    return;
-
-  // Build up the predicate string.
-  SmallString<256> Predicate;
-  // FIXME: emitPredicateMatch() functions can take a buffer directly rather
-  // than a stream.
-  raw_svector_ostream PS(Predicate);
-  emitPredicateMatch(PS, EncodingID);
-
-  // Figure out the index into the predicate table for the predicate just
-  // computed.
-  unsigned PIdx = getPredicateIndex(PS.str());
-
-  const MCD::DecoderOps DecoderOp = TableInfo.isOutermostScope()
-                                        ? MCD::OPC_CheckPredicateOrFail
-                                        : MCD::OPC_CheckPredicate;
-  TableInfo.Table.insertOpcode(DecoderOp);
-  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 {
-  const InstructionEncoding &Encoding = Encodings[EncodingID];
-  const KnownBits &InstBits = Encoding.getInstBits();
-  const APInt &SoftFailMask = Encoding.getSoftFailMask();
-
-  if (SoftFailMask.isZero())
-    return;
-
-  APInt PositiveMask = InstBits.Zero & SoftFailMask;
-  APInt NegativeMask = InstBits.One & SoftFailMask;
-
-  TableInfo.Table.insertOpcode(MCD::OPC_SoftFail);
-  TableInfo.Table.insertULEB128(PositiveMask.getZExtValue());
-  TableInfo.Table.insertULEB128(NegativeMask.getZExtValue());
-}
-
-// Emits table entries to decode the singleton.
-void DecoderTableBuilder::emitSingletonTableEntry(
-    const FilterChooser &FC) const {
-  unsigned EncodingID = *FC.SingletonEncodingID;
-  const InstructionEncoding &Encoding = Encodings[EncodingID];
-  KnownBits EncodingBits = Encoding.getMandatoryBits();
-
-  // Look for islands of undecoded bits of the singleton.
-  std::vector<FilterChooser::Island> Islands = FC.getIslands(EncodingBits);
-
-  // Emit the predicate table entry if one is needed.
-  emitPredicateTableEntry(EncodingID);
-
-  // 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.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.
-  emitSoftFailTableEntry(EncodingID);
-
-  unsigned DIdx = getDecoderIndex(EncodingID);
-
-  // Produce OPC_Decode or OPC_TryDecode opcode based on the information
-  // whether the instruction decoder is complete or not. If it is complete
-  // then it handles all possible values of remaining variable/unfiltered bits
-  // and for any value can determine if the bitpattern is a valid instruction
-  // or not. This means OPC_Decode will be the final step in the decoding
-  // process. If it is not complete, then the Fail return code from the
-  // 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.
-  const MCD::DecoderOps DecoderOp =
-      Encoding.hasCompleteDecoder()  ? MCD::OPC_Decode
-      : TableInfo.isOutermostScope() ? MCD::OPC_TryDecodeOrFail
-                                     : 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());
-  }
+  PredicateSet::const_iterator P = find(Predicates, Predicate);
+  return std::distance(Predicates.begin(), P);
 }
 
 // reportRegion is a helper function for filterProcessor to mark a region as
 // eligible for use as a filter region.
-void FilterChooser::reportRegion(std::vector<std::unique_ptr<Filter>> &Filters,
-                                 bitAttr_t RA, unsigned StartBit,
-                                 unsigned BitIndex, bool AllowMixed) const {
+void DecoderTreeBuilder::reportRegion(
+    ArrayRef<unsigned> EncodingIDs,
+    std::vector<std::unique_ptr<Filter>> &Filters, bitAttr_t RA,
+    unsigned StartBit, unsigned BitIndex, bool AllowMixed) const {
   if (AllowMixed ? RA == ATTR_MIXED : RA == ATTR_ALL_SET)
     Filters.push_back(std::make_unique<Filter>(Encodings, EncodingIDs, StartBit,
                                                BitIndex - StartBit));
 }
 
-std::unique_ptr<Filter>
-FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
-                              bool Greedy) const {
+std::unique_ptr<Filter> DecoderTreeBuilder::findBestFilter(
+    ArrayRef<unsigned> EncodingIDs, const KnownBits &FilterBits,
+    ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed, bool Greedy) const {
   assert(EncodingIDs.size() >= 2 && "Nothing to filter");
 
   // Heuristics.  See also doFilter()'s "Heuristics" comment when num of
@@ -1342,7 +1174,7 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
       KnownBits EncodingBits = Encoding.getMandatoryBits();
 
       // Look for islands of undecoded bits of any instruction.
-      std::vector<Island> Islands = getIslands(EncodingBits);
+      std::vector<Island> Islands = getIslands(EncodingBits, FilterBits);
       if (!Islands.empty()) {
         // Found an instruction with island(s).  Now just assign a filter.
         return std::make_unique<Filter>(
@@ -1403,17 +1235,17 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
     case ATTR_ALL_SET:
       switch (bitAttr) {
       case ATTR_FILTERED:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         RA = ATTR_NONE;
         break;
       case ATTR_ALL_SET:
         break;
       case ATTR_ALL_UNSET:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         RA = ATTR_NONE;
         break;
       case ATTR_MIXED:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         StartBit = BitIndex;
         RA = ATTR_MIXED;
         break;
@@ -1424,17 +1256,17 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
     case ATTR_MIXED:
       switch (bitAttr) {
       case ATTR_FILTERED:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         StartBit = BitIndex;
         RA = ATTR_NONE;
         break;
       case ATTR_ALL_SET:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         StartBit = BitIndex;
         RA = ATTR_ALL_SET;
         break;
       case ATTR_ALL_UNSET:
-        reportRegion(Filters, RA, StartBit, BitIndex, AllowMixed);
+        reportRegion(EncodingIDs, Filters, RA, StartBit, BitIndex, AllowMixed);
         RA = ATTR_NONE;
         break;
       case ATTR_MIXED:
@@ -1457,12 +1289,12 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
   case ATTR_FILTERED:
     break;
   case ATTR_ALL_SET:
-    reportRegion(Filters, RA, StartBit, FilterWidth, AllowMixed);
+    reportRegion(EncodingIDs, Filters, RA, StartBit, FilterWidth, AllowMixed);
     break;
   case ATTR_ALL_UNSET:
     break;
   case ATTR_MIXED:
-    reportRegion(Filters, RA, StartBit, FilterWidth, AllowMixed);
+    reportRegion(EncodingIDs, Filters, RA, StartBit, FilterWidth, AllowMixed);
     break;
   }
 
@@ -1490,7 +1322,9 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
   return std::move(Filters[BestIndex]);
 }
 
-std::unique_ptr<Filter> FilterChooser::findBestFilter() const {
+std::unique_ptr<Filter>
+DecoderTreeBuilder::findBestFilter(ArrayRef<unsigned> EncodingIDs,
+                                   const KnownBits &FilterBits) const {
   // We maintain BIT_WIDTH copies of the bitAttrs automaton.
   // The automaton consumes the corresponding bit from each
   // instruction.
@@ -1514,7 +1348,7 @@ std::unique_ptr<Filter> FilterChooser::findBestFilter() const {
   // FILTERED bit positions provide no entropy and are not worthy of pursuing.
   // Filter::recurse() set either 1 or 0 for each position.
   for (unsigned BitIndex = 0; BitIndex != FilterWidth; ++BitIndex)
-    if (isPositionFiltered(BitIndex))
+    if (FilterBits.Zero[BitIndex] || FilterBits.One[BitIndex])
       BitAttrs[BitIndex] = ATTR_FILTERED;
 
   for (unsigned EncodingID : EncodingIDs) {
@@ -1546,12 +1380,13 @@ std::unique_ptr<Filter> FilterChooser::findBestFilter() const {
   }
 
   // Try regions of consecutive known bit values first.
-  if (std::unique_ptr<Filter> F =
-          findBestFilter(BitAttrs, /*AllowMixed=*/false))
+  if (std::unique_ptr<Filter> F = findBestFilter(
+          EncodingIDs, FilterBits, BitAttrs, /*AllowMixed=*/false))
     return F;
 
   // Then regions of mixed bits (both known and unitialized bit values allowed).
-  if (std::unique_ptr<Filter> F = findBestFilter(BitAttrs, /*AllowMixed=*/true))
+  if (std::unique_ptr<Filter> F = findBestFilter(EncodingIDs, FilterBits,
+                                                 BitAttrs, /*AllowMixed=*/true))
     return F;
 
   // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
@@ -1560,7 +1395,8 @@ std::unique_ptr<Filter> FilterChooser::findBestFilter() const {
   // the very first consecutive ATTR_ALL_SET region and assign a filter to it.
   if (EncodingIDs.size() == 3) {
     if (std::unique_ptr<Filter> F =
-            findBestFilter(BitAttrs, /*AllowMixed=*/true, /*Greedy=*/false))
+            findBestFilter(EncodingIDs, FilterBits, BitAttrs,
+                           /*AllowMixed=*/true, /*Greedy=*/false))
       return F;
   }
 
@@ -1568,37 +1404,14 @@ std::unique_ptr<Filter> FilterChooser::findBestFilter() const {
   return nullptr;
 }
 
-// Decides on the best configuration of filter(s) to use in order to decode
-// the instructions.  A conflict of instructions may occur, in which case we
-// dump the conflict set to the standard error.
-void FilterChooser::doFilter() {
-  assert(!EncodingIDs.empty() && "FilterChooser created with no instructions");
-
-  // No filter needed.
-  if (EncodingIDs.size() == 1) {
-    SingletonEncodingID = EncodingIDs.front();
-    return;
-  }
-
-  std::unique_ptr<Filter> BestFilter = findBestFilter();
-  if (BestFilter) {
-    applyFilter(*BestFilter);
-    return;
-  }
-
-  // Print out useful conflict information for postmortem analysis.
-  errs() << "Decoding Conflict:\n";
-  dump();
-  PrintFatalError("Decoding conflict encountered");
-}
-
-void FilterChooser::dump() const {
+void DecoderTreeBuilder::dump(ArrayRef<unsigned> EncodingIDs,
+                              const KnownBits &FilterBits) const {
   indent Indent(4);
   // Helps to keep the output right-justified.
-  unsigned PadToWidth = getMaxEncodingWidth();
+  unsigned PadToWidth = Encodings[EncodingIDs.back()].getBitWidth();
 
   // Dump filter stack.
-  dumpStack(errs(), Indent, PadToWidth);
+  dumpStack(errs(), Indent, PadToWidth, FilterBits);
 
   // Dump encodings.
   for (unsigned EncodingID : EncodingIDs) {
@@ -1609,72 +1422,190 @@ void FilterChooser::dump() const {
   }
 }
 
-void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
-  DecoderTable &Table = TableInfo.Table;
-
-  // If there are other encodings that could match if those with all bits
-  // known don't, enter a scope so that they have a chance.
-  if (FC.VariableFC)
-    TableInfo.pushScope();
-
-  if (FC.SingletonEncodingID) {
-    assert(FC.FilterChooserMap.empty());
-    // There is only one encoding in which all bits in the filtered range are
-    // fully defined, but we still need to check if the remaining (unfiltered)
-    // bits are valid for this encoding. We also need to check predicates etc.
-    emitSingletonTableEntry(FC);
-  } else if (FC.FilterChooserMap.size() == 1) {
-    // 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.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);
-  } else {
-    // The general case: emit a switch over the field value.
-    Table.insertOpcode(MCD::OPC_ExtractField);
-    Table.insertULEB128(FC.StartBit);
-    Table.insertUInt8(FC.NumBits);
-
-    // Emit switch cases for all but the last element.
-    for (const auto &[FilterVal, Delegate] : drop_end(FC.FilterChooserMap)) {
-      Table.insertOpcode(MCD::OPC_FilterValue);
-      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.
-      Table.patchNumToSkip(FixupPos, Table.size());
+unsigned DecoderTableEmitter::computeNodeSize(const DecoderTreeNode *N) const {
+  switch (N->getKind()) {
+  case DecoderTreeNode::AnyOf: {
+    const auto *AnyOf = static_cast<const AnyOfNode *>(N);
+    unsigned Size = 0;
+    for (const auto &Child : drop_end(AnyOf->getChildren())) {
+      unsigned ChildSize = computeNodeSize(Child.get());
+      Size += 1 + getULEB128Size(ChildSize) + ChildSize;
+    }
+    return Size + computeNodeSize(AnyOf->getChildren().back().get());
+  }
+  case DecoderTreeNode::AllOf: {
+    const auto *AllOf = static_cast<const AllOfNode *>(N);
+    unsigned Size = 0;
+    for (const auto &Child : AllOf->getChildren())
+      Size += computeNodeSize(Child.get());
+    return Size;
+  }
+  case DecoderTreeNode::CheckField: {
+    const auto *CheckField = static_cast<const CheckFieldNode *>(N);
+    return 1 + getULEB128Size(CheckField->getStartBit()) + 1 +
+           getULEB128Size(CheckField->getValue());
+  }
+  case DecoderTreeNode::SwitchField: {
+    const auto *SwitchN = static_cast<const SwitchFieldNode *>(N);
+    unsigned Size = 1 + getULEB128Size(SwitchN->getStartBit()) + 1;
+
+    for (const auto &[Val, Child] : drop_end(SwitchN->getCases())) {
+      unsigned ChildSize = computeNodeSize(Child.get());
+      Size += getULEB128Size(Val) + getULEB128Size(ChildSize) + ChildSize;
     }
 
-    // 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.insertULEB128(FilterVal);
-    if (!TableInfo.isOutermostScope())
-      TableInfo.FixupStack.back().push_back(Table.insertNumToSkip());
+    const auto &[Val, Child] = *SwitchN->getCases().rbegin();
+    unsigned ChildSize = computeNodeSize(Child.get());
+    Size += getULEB128Size(Val) + getULEB128Size(0) + ChildSize;
+    return Size;
+  }
+  case DecoderTreeNode::CheckPredicate: {
+    const auto *CheckPredicate = static_cast<const CheckPredicateNode *>(N);
+    return 1 + getULEB128Size(CheckPredicate->getPredicateIndex());
+  }
+  case DecoderTreeNode::SoftFail: {
+    const auto *SoftFail = static_cast<const SoftFailNode *>(N);
+    return 1 + getULEB128Size(SoftFail->getPositiveMask()) +
+           getULEB128Size(SoftFail->getNegativeMask());
+  }
+  case DecoderTreeNode::Decode: {
+    const auto *Decode = static_cast<const DecodeNode *>(N);
+    return 1 + 2 + getULEB128Size(Decode->getDecoderIndex());
+  }
+  }
+  llvm_unreachable("Unknown node kind");
+}
 
-    // Emit table entries for the last case.
-    emitTableEntries(*Delegate);
+void DecoderTableEmitter::emitAnyOfNode(const AnyOfNode *N, indent Indent) {
+  for (const auto &Child : drop_end(N->getChildren())) {
+    emitOpcode("OPC_Scope");
+    emitULEB128(computeNodeSize(Child.get()));
+
+    emitComment(Indent) << "{\n";
+    emitNode(Child.get(), Indent + 1);
+    emitComment(Indent) << "}\n";
   }
 
-  if (FC.VariableFC) {
-    TableInfo.popScope();
-    emitTableEntries(*FC.VariableFC);
+  const auto &Child = N->getChildren().back();
+  emitNode(Child.get(), Indent);
+}
+
+void DecoderTableEmitter::emitAllOfNode(const AllOfNode *N, indent Indent) {
+  for (const auto &Child : N->getChildren())
+    emitNode(Child.get(), Indent);
+}
+
+void DecoderTableEmitter::emitSwitchFieldNode(const SwitchFieldNode *N,
+                                              indent Indent) {
+  unsigned LSB = N->getStartBit();
+  unsigned Width = N->getNumBits();
+  unsigned MSB = LSB + Width - 1;
+
+  emitOpcode("OPC_SwitchField");
+  emitULEB128(LSB);
+  emitUInt8(Width);
+
+  emitComment(Indent) << "switch Inst[" << MSB << ':' << LSB << "] {\n";
+
+  for (const auto &[Val, Child] : drop_end(N->getCases())) {
+    emitStartLine();
+    emitULEB128(Val);
+    emitULEB128(computeNodeSize(Child.get()));
+
+    emitComment(Indent) << "case " << format_hex(Val, 0) << ": {\n";
+    emitNode(Child.get(), Indent + 1);
+    emitComment(Indent) << "}\n";
   }
+
+  const auto &[Val, Child] = *N->getCases().rbegin();
+  emitStartLine();
+  emitULEB128(Val);
+  emitULEB128(0);
+
+  emitComment(Indent) << "case " << format_hex(Val, 0) << ": {\n";
+  emitNode(Child.get(), Indent + 1);
+  emitComment(Indent) << "}\n";
+
+  emitComment(Indent) << "} // switch Inst[" << MSB << ':' << LSB << "]\n";
+}
+
+void DecoderTableEmitter::emitCheckFieldNode(const CheckFieldNode *N,
+                                             indent Indent) {
+  unsigned LSB = N->getStartBit();
+  unsigned Width = N->getNumBits();
+  unsigned MSB = LSB + Width - 1;
+  uint64_t Val = N->getValue();
+
+  emitOpcode("OPC_CheckField");
+  emitULEB128(LSB);
+  emitUInt8(Width);
+  emitULEB128(Val);
+
+  emitComment(Indent);
+  OS << "check Inst[" << MSB << ':' << LSB << "] == " << format_hex(Val, 0)
+     << '\n';
+}
+
+void DecoderTableEmitter::emitCheckPredicateNode(const CheckPredicateNode *N,
+                                                 indent Indent) {
+  unsigned PredicateIndex = N->getPredicateIndex();
+
+  emitOpcode("OPC_CheckPredicate");
+  emitULEB128(PredicateIndex);
+
+  emitComment(Indent) << "check predicate " << PredicateIndex << "\n";
+}
+
+void DecoderTableEmitter::emitSoftFailNode(const SoftFailNode *N,
+                                           indent Indent) {
+  uint64_t PositiveMask = N->getPositiveMask();
+  uint64_t NegativeMask = N->getNegativeMask();
+
+  emitOpcode("OPC_SoftFail");
+  emitULEB128(PositiveMask);
+  emitULEB128(NegativeMask);
+
+  emitComment(Indent) << "check softfail";
+  OS << " pos=" << format_hex(PositiveMask, 10);
+  OS << " neg=" << format_hex(NegativeMask, 10) << '\n';
+}
+
+void DecoderTableEmitter::emitDecodeNode(const DecodeNode *N, indent Indent) {
+  const InstructionEncoding &Encoding = Encodings[N->getEncodingID()];
+  const Record *InstDef = Encoding.getInstruction()->TheDef;
+  unsigned InstOpcode = Target.getInstrIntValue(InstDef);
+  unsigned DecoderIndex = N->getDecoderIndex();
+
+  emitOpcode(Encoding.hasCompleteDecoder() ? "OPC_Decode" : "OPC_TryDecode");
+  emitUInt16(InstOpcode);
+  emitULEB128(DecoderIndex);
+
+  emitComment(Indent);
+  if (!Encoding.hasCompleteDecoder())
+    OS << "try ";
+  OS << "decode to " << Encoding.getName() << " using decoder " << DecoderIndex
+     << '\n';
+}
+
+void DecoderTableEmitter::emitNode(const DecoderTreeNode *N, indent Indent) {
+  switch (N->getKind()) {
+  case DecoderTreeNode::AnyOf:
+    return emitAnyOfNode(static_cast<const AnyOfNode *>(N), Indent);
+  case DecoderTreeNode::AllOf:
+    return emitAllOfNode(static_cast<const AllOfNode *>(N), Indent);
+  case DecoderTreeNode::SwitchField:
+    return emitSwitchFieldNode(static_cast<const SwitchFieldNode *>(N), Indent);
+  case DecoderTreeNode::CheckField:
+    return emitCheckFieldNode(static_cast<const CheckFieldNode *>(N), Indent);
+  case DecoderTreeNode::CheckPredicate:
+    return emitCheckPredicateNode(static_cast<const CheckPredicateNode *>(N),
+                                  Indent);
+  case DecoderTreeNode::SoftFail:
+    return emitSoftFailNode(static_cast<const SoftFailNode *>(N), Indent);
+  case DecoderTreeNode::Decode:
+    return emitDecodeNode(static_cast<const DecodeNode *>(N), Indent);
+  }
+  llvm_unreachable("Unknown node kind");
 }
 
 static std::string findOperandDecoderMethod(const Record *Record) {
@@ -2087,25 +2018,9 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
 
 // emitDecodeInstruction - Emit the templated helper function
 // 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 HasSoftFail = OpcodeMask & (1 << MCD::OPC_SoftFail);
-
+static void emitDecodeInstruction(formatted_raw_ostream &OS,
+                                  bool IsVarLenInst) {
   OS << R"(
-static unsigned decodeNumToSkip(const uint8_t *&Ptr) {
-  unsigned NumToSkip = *Ptr++;
-  NumToSkip |= (*Ptr++) << 8;
-)";
-  if (getNumToSkipInBytes() == 3)
-    OS << "  NumToSkip |= (*Ptr++) << 16;\n";
-  OS << R"(  return NumToSkip;
-}
-
 template <typename InsnType>
 static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
                                       InsnType insn, uint64_t Address,
@@ -2115,63 +2030,60 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
     OS << ",\n                                      "
           "llvm::function_ref<void(APInt &, uint64_t)> makeUp";
   }
-  OS << ") {\n";
-  if (HasCheckPredicate)
-    OS << "  const FeatureBitset &Bits = STI.getFeatureBits();\n";
-  OS << "  using namespace llvm::MCD;\n";
+  OS << R"() {
+  const FeatureBitset &Bits = STI.getFeatureBits();
+  using namespace llvm::MCD;
 
-  OS << R"(
+  SmallVector<const uint8_t *, 8> ScopeStack;
   const uint8_t *Ptr = DecodeTable;
-  uint64_t CurFieldValue = 0;
   DecodeStatus S = MCDisassembler::Success;
   while (true) {
     ptrdiff_t Loc = Ptr - DecodeTable;
     const uint8_t DecoderOp = *Ptr++;
     switch (DecoderOp) {
     default:
-      errs() << Loc << ": Unexpected decode table opcode: "
-             << (int)DecoderOp << '\n';
+      errs() << Loc << ": Unexpected decode table opcode: " << (int)DecoderOp
+             << '\n';
       return MCDisassembler::Fail;
-    case MCD::OPC_ExtractField: {
+    case OPC_Scope: {
+      unsigned NumToSkip = decodeULEB128AndIncUnsafe(Ptr);
+      const uint8_t *SkipTo = Ptr + NumToSkip;
+      ScopeStack.push_back(SkipTo);
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_Scope(" << SkipTo - DecodeTable
+                        << ")\n");
+      break;
+    }
+    case OPC_SwitchField: {
       // Decode the start value.
       unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
       unsigned Len = *Ptr++;)";
   if (IsVarLenInst)
     OS << "\n      makeUp(insn, Start + Len);";
   OS << R"(
-      CurFieldValue = fieldFromInstruction(insn, Start, Len);
-      LLVM_DEBUG(dbgs() << Loc << ": OPC_ExtractField(" << Start << ", "
-                   << Len << "): " << CurFieldValue << "\n");
-      break;
-    }
-    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 = 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 (IsFail)
+      uint64_t FieldVal = fieldFromInstruction(insn, Start, Len);
+      uint64_t CaseVal;
+      unsigned CaseSize;
+      while (true) {
+        CaseVal = decodeULEB128AndIncUnsafe(Ptr);
+        CaseSize = decodeULEB128AndIncUnsafe(Ptr);
+        if (CaseVal == FieldVal || !CaseSize)
+          break;
+        Ptr += CaseSize;
+      }
+      if (CaseVal == FieldVal) {
+        LLVM_DEBUG(dbgs() << Loc << ": OPC_SwitchField(" << Start << ", " << Len
+                          << "): " << FieldVal << '\n');
+      } else {
+        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 OPC_CheckField: {
       // Decode the start value.
       unsigned Start = decodeULEB128AndIncUnsafe(Ptr);
       unsigned Len = *Ptr;)";
@@ -2184,53 +2096,44 @@ 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 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;
-    })";
-  }
-  OS << R"(
-    case MCD::OPC_Decode: {
+    }
+    case OPC_Decode: {
       // Decode the Opcode value.
-      unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
+      unsigned Opc = *Ptr++;
+      Opc |= *Ptr++ << 8;
       unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
 
       MI.clear();
@@ -2241,31 +2144,29 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
        << "      makeUp(insn, Len);";
   }
   OS << R"(
-      S = decodeToMCInst(DecodeIdx, S, insn, MI, Address, DisAsm, DecodeComplete);
+      S = decodeToMCInst(DecodeIdx, S, insn, MI, Address, DisAsm,
+                         DecodeComplete);
       assert(DecodeComplete);
 
       LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
-                   << ", using decoder " << DecodeIdx << ": "
-                   << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
+                        << ", using decoder " << DecodeIdx << ": "
+                        << (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
       return S;
-    })";
-  if (HasTryDecode) {
-    OS << R"(
-    case MCD::OPC_TryDecode:
-    case MCD::OPC_TryDecodeOrFail: {
-      bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
+    }
+    case OPC_TryDecode: {
       // Decode the Opcode value.
-      unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
+      unsigned Opc = *Ptr++;
+      Opc |= *Ptr++ << 8;
       unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
-      unsigned NumToSkip = IsFail ? 0 : decodeNumToSkip(Ptr);
 
       // Perform the decode operation.
       MCInst TmpMI;
       TmpMI.setOpcode(Opc);
       bool DecodeComplete;
-      S = decodeToMCInst(DecodeIdx, S, insn, TmpMI, Address, DisAsm, DecodeComplete);
+      S = decodeToMCInst(DecodeIdx, S, insn, TmpMI, Address, DisAsm,
+                         DecodeComplete);
       LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc
-                   << ", using decoder " << DecodeIdx << ": ");
+                        << ", using decoder " << DecodeIdx << ": ");
 
       if (DecodeComplete) {
         // Decoding complete.
@@ -2274,38 +2175,32 @@ 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;
       break;
-    })";
-  }
-  if (HasSoftFail) {
-    OS << R"(
-    case MCD::OPC_SoftFail: {
+    }
+    case OPC_SoftFail: {
       // Decode the mask values.
       uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
       uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
       bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
       if (Failed)
         S = MCDisassembler::SoftFail;
-      LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
+      LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: "
+                        << (Failed ? "FAIL\n" : "PASS\n"));
       break;
-    })";
-  }
-  OS << R"(
+    }
     }
   }
   llvm_unreachable("bogosity detected in disassembler state machine!");
 }
-
 )";
 }
 
@@ -2522,24 +2417,16 @@ namespace {
   }
 
   DecoderTableInfo TableInfo;
-  DecoderTableBuilder TableBuilder(Target, Encodings, TableInfo);
-  unsigned OpcodeMask = 0;
+  DecoderTreeBuilder TreeBuilder(Target, Encodings, TableInfo);
 
   for (const auto &[Key, EncodingIDs] : EncMap) {
     auto [DecoderNamespace, HwModeID, Size] = Key;
     const unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * Size;
     // Emit the decoder for this (namespace, hwmode, width) combination.
-    FilterChooser FC(Encodings, EncodingIDs);
-
-    // The decode table is cleared for each top level decoder function. The
-    // predicates and decoders themselves, however, are shared across all
-    // decoders to give more opportunities for uniqueing.
-    TableInfo.Table.clear();
-    TableBuilder.buildTable(FC);
+    std::unique_ptr<DecoderTreeNode> Root = TreeBuilder.buildTree(EncodingIDs);
 
     // Print the table to the output stream.
-    OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,
-                            BitWidth, EncodingIDs);
+    emitDecoderTable(OS, Root.get(), DecoderNamespace, HwModeID, BitWidth);
   }
 
   // For variable instruction, we emit a instruction length table
@@ -2548,19 +2435,14 @@ namespace {
   if (IsVarLenInst)
     emitInstrLenTable(OS, InstrLen);
 
-  const bool HasCheckPredicate =
-      OpcodeMask &
-      ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
-
   // Emit the predicate function.
-  if (HasCheckPredicate)
-    emitPredicateFunction(OS, TableInfo.Predicates);
+  emitPredicateFunction(OS, TableInfo.Predicates);
 
   // Emit the decoder function.
   emitDecoderFunction(OS, TableInfo.Decoders);
 
   // Emit the main entry point for the decoder, decodeInstruction().
-  emitDecodeInstruction(OS, IsVarLenInst, OpcodeMask);
+  emitDecodeInstruction(OS, IsVarLenInst);
 
   OS << "\n} // namespace\n";
 }



More information about the llvm-commits mailing list