[llvm] [LLVM][MC] Add support to cull inactive decoders in decoder emitter (PR #154865)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 25 23:25:19 PDT 2025


================
@@ -2528,45 +2535,80 @@ namespace {
 )";
 
   // Do extra bookkeeping for variable-length encodings.
-  std::vector<unsigned> InstrLen;
   bool IsVarLenInst = Target.hasVariableLengthEncodings();
   unsigned MaxInstLen = 0;
   if (IsVarLenInst) {
-    InstrLen.resize(Target.getInstructions().size(), 0);
+    std::vector<unsigned> InstrLen(Target.getInstructions().size(), 0);
     for (const InstructionEncoding &Encoding : Encodings) {
       MaxInstLen = std::max(MaxInstLen, Encoding.getBitWidth());
       InstrLen[Target.getInstrIntValue(Encoding.getInstruction()->TheDef)] =
           Encoding.getBitWidth();
     }
+
+    // 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.
+    emitInstrLenTable(OS, InstrLen);
   }
 
-  // Map of (namespace, hwmode, size) tuple to encoding IDs.
-  std::map<std::tuple<StringRef, unsigned, unsigned>, std::vector<unsigned>>
+  // Map of (bitwidth, namespace, hwmode) tuple to encoding IDs.
+  std::map<std::tuple<unsigned, StringRef, unsigned>, std::vector<unsigned>>
----------------
s-barannikov wrote:

I tried a map of maps and this is how it looks like (didn't check that it generates correct code):

<details>
<summary>looks much cleaner to me</summary>

```C++
  for (const auto &[BitWidth, BWMap] : EncMap) {
    for (const auto &[Key, EncodingIDs] : BWMap) {
      auto [DecoderNamespace, HwModeID] = Key;

      // Emit the decoder for this (namespace, hwmode, width) combination.
      FilterChooser FC(Encodings, EncodingIDs, BitWidth, Target);

      // The decode table is cleared for each top level decoder function. The
      // predicates and decoders themselves, however, are shared across
      // different decoders to give more opportunities for uniqueing.
      //  - If `SpecializeDecodersPerBitwidth` is enabled, decoders are shared
      //    across all decoder tables for a given bitwidth, else they are shared
      //    across all decoder tables.
      //  - predicates are shared across all decoder tables.
      TableInfo.Table.clear();
      TableBuilder.buildTable(FC);

      // Print the table to the output stream.
      OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,
                              BitWidth, EncodingIDs);
    }

    if (SpecializeDecodersPerBitwidth) {
      emitDecoderFunction(OS, TableInfo.Decoders, BitWidth);
      // Each BitWidth get's its own decoders and decoder function.
      TableInfo.Decoders.clear();
    }
  }

  // Emit the decoder function for the last bucket. This will also emit the
  // single decoder function if SpecializeDecodersPerBitwidth = false.
  if (!SpecializeDecodersPerBitwidth)
    emitDecoderFunction(OS, TableInfo.Decoders, 0);
```

</details>

WDYT?

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


More information about the llvm-commits mailing list