[llvm] [TableGen][DecoderEmitter] Add option to emit type-specialized code (PR #146593)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 19 04:52:56 PDT 2025


================
@@ -2574,52 +2776,140 @@ namespace {
     }
   }
 
+  bool GenerateTemplated =
+      Target.getInstructionSet()->getValueAsBit("GenerateTemplatedDecoder");
+
+  // For variable instruction, we emit a instruction length table to let the
+  // decoder know how long the instructions are. You can see example usage in
+  // M68k's disassembler.
+  if (IsVarLenInst) {
+    if (GenerateTemplated)
+      PrintFatalError(
+          "Templated decoder not needed for variable length instruction");
+    emitInstrLenTable(OS, InstrLen);
+  }
+
   DecoderTableInfo TableInfo;
+  bool HasCheckPredicate = false;
   unsigned OpcodeMask = 0;
-  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, Operands, BitWidth, this);
-
-    // 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();
-    TableInfo.pushScope();
-    FC.emitTableEntries(TableInfo);
-    // Any NumToSkip fixups in the top level scope can resolve to the
-    // OPC_Fail at the end of the table.
-    assert(TableInfo.isOutermostScope() && "fixup stack phasing error!");
-    TableInfo.popScope();
 
-    TableInfo.Table.push_back(MCD::OPC_Fail);
+  // Helper lambda to emit the decoder code for a given instruction Bitwidth
+  // and associated C++ type. If `Bitwidth` is 0 (and CPPType is empty) it will
+  // generate templated decoder code.
+  auto emitDecoder = [&](const CPPType &Type, StringRef Suffix) {
+    // Reset the Decoders for each non-templated type.
+    TableInfo.Decoders.clear();
+
+    const bool IsTemplate = Type.Kind == CPPType::TemplateTy;
+    if (!IsTemplate) {
+      OS << "// ------------------------------------------------------------\n";
+      OS << "// Decoder tables for " << Type.Bitwidth << "-bit instructions.\n";
+      OS << "// Using C++ type `" << Type.getName() << "` for payload.\n\n";
+    }
 
-    // Print the table to the output stream.
-    OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,
-                            BitWidth, EncodingIDs);
-  }
+    for (const auto &[Key, EncodingIDs] : EncMap) {
+      auto [DecoderNamespace, HwModeID, Size] = Key;
+      const unsigned Bitwidth = IsVarLenInst ? MaxInstLen : 8 * Size;
 
-  // For variable instruction, we emit a instruction length table
-  // to let the decoder know how long the instructions are.
-  // You can see example usage in M68k's disassembler.
-  if (IsVarLenInst)
-    emitInstrLenTable(OS, InstrLen);
+      if (!IsTemplate && Bitwidth != Type.Bitwidth)
+        continue;
 
-  const bool HasCheckPredicate =
-      OpcodeMask &
-      ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+      // Emit the decoder table for this (namespace, hwmode, width) combination.
+      FilterChooser FC(Encodings, EncodingIDs, Operands, Bitwidth, this);
+
+      // The decode table is cleared for each top level decoder table generated.
+      //
+      // The decoders themselves are shared across all decoder tables for a
+      // given instuction bitwidth, to give more opporuninity for uniqueing.
----------------
s-barannikov wrote:

Typos "instuction" and "opporuninity"

https://github.com/llvm/llvm-project/pull/146593


More information about the llvm-commits mailing list