[llvm] [LLVM][MC][DecoderEmitter] Encode BitWidth at the start of the table (PR #156734)

Rahul Joshi via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 3 11:57:58 PDT 2025


https://github.com/jurahul created https://github.com/llvm/llvm-project/pull/156734

Testing if the llvm_unreachable ever fires.

>From 759c69f5bcabf1e48ec6a7c093d45acfee90daf4 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Wed, 3 Sep 2025 11:56:11 -0700
Subject: [PATCH] [LLVM][MC][DecoderEmitter] Encode BitWidth at the start of
 the table

---
 llvm/utils/TableGen/DecoderEmitter.cpp | 33 +++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index fcaf433918092..a364df96be2c6 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -611,7 +611,12 @@ class DecoderTableBuilder {
                       DecoderTableInfo &TableInfo)
       : Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
 
-  void buildTable(const FilterChooser &FC) const {
+  void buildTable(const FilterChooser &FC, unsigned BitWidth) const {
+    // When specializing decoders per bit width, each decoder table will begin
+    // with a the bitwidth for that table. This will be used to early out from
+    // the generated `decodeInstruction`.
+    if (SpecializeDecodersPerBitwidth)
+      TableInfo.Table.insertULEB128(BitWidth);
     emitTableEntries(FC);
     assert(TableInfo.FixupStack.empty() && "Fixup stack phasing error!");
   }
@@ -774,6 +779,15 @@ unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
     OS << "Skip to: " << Index;
   };
 
+  // The first entry when specializing decoders per bitwidth will be the
+  // bitwidth. This will be used for early return in `decodeInstruction`.
+  if (SpecializeDecodersPerBitwidth) {
+    OS << "/* 0  */";
+    OS.PadToColumn(14);
+    emitULEB128(I, OS);
+    OS << " // Bitwidth " << BitWidth << '\n';
+  }
+
   unsigned OpcodeMask = 0;
 
   while (I != E) {
@@ -2108,9 +2122,22 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
   if (HasCheckPredicate)
     OS << "  const FeatureBitset &Bits = STI.getFeatureBits();\n";
   OS << "  using namespace llvm::MCD;\n";
+  OS << "  const uint8_t *Ptr = DecodeTable;\n";
+
+  if (SpecializeDecodersPerBitwidth) {
+    // Insert early out checks if the decoder table's bitwidth does not match
+    // `InsnType`'s bitwidth.
+    // Decode the ULEB128 bitwidth stored at the start of the decoder table.
+    OS << "  uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);\n";
+    OS << "  if (InsnBitWidth<InsnType> != BitWidth) {\n";
+    OS << "     dbgs() << \"Mismatch size: Table bitwidth = \" << BitWidth << "
+          "\", InsnBitWidth = \" << InsnBitWidth<InsnType> << \"\\n\";\n";
+    OS << "     llvm_unreachable(\"Bitwidth mismatch\");\n";
+    OS << "     return MCDisassembler::Fail;\n";
+    OS << "  }\n";
+  }
 
   OS << R"(
-  const uint8_t *Ptr = DecodeTable;
   uint64_t CurFieldValue = 0;
   DecodeStatus S = MCDisassembler::Success;
   while (true) {
@@ -2554,7 +2581,7 @@ template <typename T> constexpr uint32_t InsnBitWidth = 0;
       //    across all decoder tables.
       //  - predicates are shared across all decoder tables.
       TableInfo.Table.clear();
-      TableBuilder.buildTable(FC);
+      TableBuilder.buildTable(FC, BitWidth);
 
       // Print the table to the output stream.
       OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,



More information about the llvm-commits mailing list