[llvm] [TableGen] Pool duplicate code-emitter base encodings (PR #202619)

David Zbarsky via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 2 09:24:20 PDT 2026


https://github.com/dzbarsky updated https://github.com/llvm/llvm-project/pull/202619

>From d6ae88633d1f096fea7d46ae8b8817dd1fa0d72e Mon Sep 17 00:00:00 2001
From: David Zbarsky <dzbarsky at gmail.com>
Date: Tue, 9 Jun 2026 06:38:43 -0400
Subject: [PATCH] [TableGen] Pool duplicate code-emitter base encodings

Code emitters with multiword instruction encodings currently emit one complete base encoding for every instruction. AMDGPU repeats many rows, so the constant table retains substantially more data than the encoder needs.

Build a DenseMap-backed pool of unique APInt base encodings across the default encoding table and all HwMode encoding tables. Emit fixed-width uint64_t rows and one opcode-to-row index table per mode using the smallest uint8_t, uint16_t, or uint32_t index type that can address the rows. Use the pooled representation only when the combined values and indices are smaller than the original tables. A generated static assertion verifies that the row count fits the selected index type.

In a Release build, the AMDGPU base-encoding payload shrinks from 708,032 to 267,144 bytes (-440,888). __TEXT,__const shrinks by 440,880 bytes in both llvm-mc and llc; __DATA_CONST,__const and __DATA,__data are unchanged. Linked chained fixups are unchanged, and neither linked binary has static relocations. The resulting binary sizes change as follows:

  llvm-mc:       26,133,864 -> 25,688,232 bytes (-445,632)
  llc:          136,637,088 -> 136,191,456 bytes (-445,632)
  LLVM driver:  103,106,872 -> 102,677,752 bytes (-429,120)

Thirty alternating CPU-time pairs measured common AMDGPU assembly at +0.67%, a mixed-instruction assembly workload at -0.56%, and bf16.ll code generation at -0.07%. A downstream composition with the existing low-word compaction measured common GFX9 assembly at +0.50% (95% paired bootstrap CI -1.56% to +2.86%) and rare GFX12.5 assembly at -0.01% (CI -2.52% to +2.50%).

All 421 TableGen tests passed. All 760 AMDGPU MC tests passed with one expected failure. Output was byte-identical for 22 llc and 7 llvm-mc cases.
---
 .../TableGen/CodeEmitterBaseEncodingPool.td   |  45 +++++
 llvm/test/TableGen/HwModeEncodeAPInt.td       |  78 ++++----
 llvm/utils/TableGen/CodeEmitterGen.cpp        | 185 ++++++++++++++----
 3 files changed, 232 insertions(+), 76 deletions(-)
 create mode 100644 llvm/test/TableGen/CodeEmitterBaseEncodingPool.td

diff --git a/llvm/test/TableGen/CodeEmitterBaseEncodingPool.td b/llvm/test/TableGen/CodeEmitterBaseEncodingPool.td
new file mode 100644
index 0000000000000..5bda9d2d4eb7f
--- /dev/null
+++ b/llvm/test/TableGen/CodeEmitterBaseEncodingPool.td
@@ -0,0 +1,45 @@
+// RUN: llvm-tblgen -gen-emitter -I %p/../../include %s | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+def TestInstrInfo : InstrInfo;
+
+def Test : Target {
+  let InstructionSet = TestInstrInfo;
+}
+
+class TestInst<bits<8> LowEncoding, bit HighEncoding> : Instruction {
+  bits<128> Inst;
+  let Inst{7...0} = LowEncoding;
+  let Inst{64} = HighEncoding;
+  let OutOperandList = (outs);
+  let InOperandList = (ins);
+}
+
+def A0 : TestInst<1, 0>;
+def A1 : TestInst<1, 0>;
+def A2 : TestInst<1, 0>;
+def A3 : TestInst<1, 0>;
+def B0 : TestInst<1, 1>;
+def B1 : TestInst<1, 1>;
+def B2 : TestInst<1, 1>;
+def B3 : TestInst<1, 1>;
+
+// CHECK: static const uint64_t InstBits[][2] = {
+// CHECK-NEXT: {UINT64_C(1), UINT64_C(0)},
+// CHECK-NEXT: {UINT64_C(1), UINT64_C(1)},
+// CHECK-NEXT: };
+// CHECK: static const uint8_t InstBitsIndices[] = {
+// CHECK-NEXT: 0,
+// CHECK-NEXT: 0,
+// CHECK-NEXT: 0,
+// CHECK-NEXT: 0,
+// CHECK-NEXT: 1,
+// CHECK-NEXT: 1,
+// CHECK-NEXT: 1,
+// CHECK-NEXT: 1,
+// CHECK-NEXT: };
+// CHECK: static_assert(sizeof(InstBits) / sizeof(InstBits[0]) <=
+// CHECK-NEXT: (UINT64_C(1) << (sizeof(InstBitsIndices[0]) * 8)));
+// CHECK: unsigned InstBitsIndex = InstBitsIndices[TableIndex];
+// CHECK: Inst = APInt(128, ArrayRef(InstBits[InstBitsIndex]));
diff --git a/llvm/test/TableGen/HwModeEncodeAPInt.td b/llvm/test/TableGen/HwModeEncodeAPInt.td
index 5056259de6494..aac5e433f92db 100644
--- a/llvm/test/TableGen/HwModeEncodeAPInt.td
+++ b/llvm/test/TableGen/HwModeEncodeAPInt.td
@@ -107,45 +107,51 @@ def unrelated: Instruction {
   let AsmString = "unrelated  $factor";
 }
 
-// For 'bar' and 'unrelated', we didn't assign any HwModes for them,
-// they should keep the same in the following four tables.
-// For 'foo' we assigned four HwModes( includes 'DefaultMode' ),
-// it's encodings should be different in the following four tables.
-// For 'baz' we only assigned ModeB for it, so it will be presented
-// as '0' in the tables of ModeA, ModeC and Default Mode.
-// ENCODER-LABEL:   static const uint64_t InstBits[] = {
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // bar
-// ENCODER-NEXT:    UINT64_C(0), UINT64_C(0),       // baz
-// ENCODER-NEXT:    UINT64_C(8), UINT64_C(0),       // foo
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // unrelated
+// InstBits contains the unique base encodings from all four HwModes.
+// Each InstBitsIndices table maps opcodes for one hardware mode into InstBits.
+// ENCODER-LABEL:   static const uint64_t InstBits[][2] = {
+// ENCODER-NEXT:    {UINT64_C(2), UINT64_C(0)},
+// ENCODER-NEXT:    {UINT64_C(0), UINT64_C(0)},
+// ENCODER-NEXT:    {UINT64_C(8), UINT64_C(0)},
+// ENCODER-NEXT:    {UINT64_C(12), UINT64_C(0)},
+// ENCODER-NEXT:    {UINT64_C(0), UINT64_C(211106232532992)},
+// ENCODER-NEXT:    {UINT64_C(12582915), UINT64_C(0)},
 // ENCODER-NEXT:    };
-// ENCODER-LABEL:   static const uint64_t InstBits_ModeA[] = {
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // bar
-// ENCODER-NEXT:    UINT64_C(0), UINT64_C(0),       // baz
-// ENCODER-NEXT:    UINT64_C(12), UINT64_C(0),      // foo
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // unrelated
+// ENCODER-LABEL:   static const uint8_t InstBitsIndices[] = {
+// ENCODER-NEXT:    0,
+// ENCODER-NEXT:    1,
+// ENCODER-NEXT:    2,
+// ENCODER-NEXT:    0,
 // ENCODER-NEXT:    };
-// ENCODER-LABEL:   static const uint64_t InstBits_ModeB[] = {
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // bar
-// ENCODER-NEXT:    UINT64_C(12), UINT64_C(0),      // baz
-// ENCODER-NEXT:    UINT64_C(0), UINT64_C(211106232532992),  // foo
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),       // unrelated
+// ENCODER-LABEL:   static const uint8_t InstBitsIndices_ModeA[] = {
+// ENCODER-NEXT:    0,
+// ENCODER-NEXT:    1,
+// ENCODER-NEXT:    3,
+// ENCODER-NEXT:    0,
 // ENCODER-NEXT:    };
-// ENCODER-LABEL:   static const uint64_t InstBits_ModeC[] = {
-// ENCODER-NEXT:    UINT64_C(2), UINT64_C(0),      // bar
-// ENCODER-NEXT:    UINT64_C(0), UINT64_C(0),      // baz
-// ENCODER-NEXT:    UINT64_C(12582915),  UINT64_C(0),  // foo
-// ENCODER-NEXT:    UINT64_C(2),  UINT64_C(0),     // unrelated
+// ENCODER-LABEL:   static const uint8_t InstBitsIndices_ModeB[] = {
+// ENCODER-NEXT:    0,
+// ENCODER-NEXT:    3,
+// ENCODER-NEXT:    4,
+// ENCODER-NEXT:    0,
 // ENCODER-NEXT:    };
+// ENCODER-LABEL:   static const uint8_t InstBitsIndices_ModeC[] = {
+// ENCODER-NEXT:    0,
+// ENCODER-NEXT:    1,
+// ENCODER-NEXT:    5,
+// ENCODER-NEXT:    0,
+// ENCODER-NEXT:    };
+
+// ENCODER: const uint8_t *InstBitsIndicesByHw;
 
-// ENCODER: const uint64_t *InstBitsByHw;
 // ENCODER: constexpr unsigned FirstSupportedOpcode
 // ENCODER: const unsigned opcode = MI.getOpcode();
 // ENCODER: if (opcode < FirstSupportedOpcode)
 // ENCODER: unsigned TableIndex = opcode - FirstSupportedOpcode
 // ENCODER: if (Scratch.getBitWidth() != 128)
 // ENCODER:   Scratch = Scratch.zext(128);
-// ENCODER: Inst = APInt(128, ArrayRef(InstBits + TableIndex * 2, 2));
+// ENCODER: unsigned InstBitsIndex = InstBitsIndices[TableIndex];
+// ENCODER: Inst = APInt(128, ArrayRef(InstBits[InstBitsIndex]));
 // ENCODER: APInt &Value = Inst;
 // ENCODER: APInt &op = Scratch;
 // ENCODER: switch (opcode) {
@@ -156,12 +162,13 @@ def unrelated: Instruction {
 // ENCODER: unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);
 // ENCODER: switch (HwMode) {
 // ENCODER: default: llvm_unreachable("Unknown hardware mode!"); break;
-// ENCODER: case 0: InstBitsByHw = InstBits; break;
-// ENCODER: case 1: InstBitsByHw = InstBits_ModeA; break;
-// ENCODER: case 2: InstBitsByHw = InstBits_ModeB; break;
-// ENCODER: case 3: InstBitsByHw = InstBits_ModeC; break;
+// ENCODER: case 0: InstBitsIndicesByHw = InstBitsIndices; break;
+// ENCODER: case 1: InstBitsIndicesByHw = InstBitsIndices_ModeA; break;
+// ENCODER: case 2: InstBitsIndicesByHw = InstBitsIndices_ModeB; break;
+// ENCODER: case 3: InstBitsIndicesByHw = InstBitsIndices_ModeC; break;
 // ENCODER: };
-// ENCODER: Inst = APInt(128, ArrayRef(InstBitsByHw + TableIndex * 2, 2));
+// ENCODER: InstBitsIndex = InstBitsIndicesByHw[TableIndex];
+// ENCODER: Inst = APInt(128, ArrayRef(InstBits[InstBitsIndex]));
 // ENCODER: Value = Inst;
 // ENCODER: switch (HwMode) {
 // ENCODER: default: llvm_unreachable("Unhandled HwMode");
@@ -188,9 +195,10 @@ def unrelated: Instruction {
 // ENCODER: unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);
 // ENCODER: switch (HwMode) {
 // ENCODER: default: llvm_unreachable("Unknown hardware mode!"); break;
-// ENCODER: case 2: InstBitsByHw = InstBits_ModeB; break;
+// ENCODER: case 2: InstBitsIndicesByHw = InstBitsIndices_ModeB; break;
 // ENCODER: };
-// ENCODER: Inst = APInt(128, ArrayRef(InstBitsByHw + TableIndex * 2, 2));
+// ENCODER: InstBitsIndex = InstBitsIndicesByHw[TableIndex];
+// ENCODER: Inst = APInt(128, ArrayRef(InstBits[InstBitsIndex]));
 // ENCODER: Value = Inst;
 // ENCODER: switch (HwMode) {
 // ENCODER: default: llvm_unreachable("Unhandled HwMode");
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
index fadb4ee1142b6..891f68386ad51 100644
--- a/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -29,10 +29,12 @@
 #include "Common/VarLenCodeEmitterGen.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/CodeGenHelpers.h"
 #include "llvm/TableGen/Error.h"
@@ -53,6 +55,14 @@ namespace {
 // and the value is a list of cases which share the same body.
 using CaseMapT = std::map<std::string, std::vector<unsigned>>;
 
+struct BaseEncodingPool {
+  std::vector<APInt> Values;
+  std::map<unsigned, std::vector<unsigned>> IndicesByHwMode;
+  unsigned IndexBitWidth = 0;
+
+  bool empty() const { return Values.empty(); }
+};
+
 class CodeEmitterGen {
   const RecordKeeper &RK;
   CodeGenTarget Target;
@@ -74,9 +84,15 @@ class CodeEmitterGen {
                                const std::string &VarName, std::string &Case,
                                std::string &BitOffsetCase);
 
+  APInt getInstructionBaseValue(const CodeGenInstruction *CGI, unsigned HwMode);
+  void buildBaseEncodingPool(
+      ArrayRef<const CodeGenInstruction *> NumberedInstructions,
+      const std::set<unsigned> &HwModes);
+  void emitBaseEncodingPool(raw_ostream &O);
   void emitInstructionBaseValues(
       raw_ostream &O, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
       unsigned HwMode = DefaultMode);
+  BaseEncodingPool BaseEncodings;
   unsigned BitWidth = 0u;
   bool UseAPInt = false;
 };
@@ -256,25 +272,34 @@ CodeEmitterGen::getInstructionCases(const Record *R) {
     Case += "      switch (HwMode) {\n";
     Case += "      default: llvm_unreachable(\"Unknown hardware mode!\"); "
             "break;\n";
+    StringRef InstBitsTableName =
+        BaseEncodings.empty() ? "InstBits" : "InstBitsIndices";
     for (auto &[ModeId, Encoding] : EBM) {
       if (ModeId == DefaultMode) {
-        Case +=
-            "      case " + itostr(DefaultMode) + ": InstBitsByHw = InstBits";
+        Case += "      case " + itostr(DefaultMode) + ": " +
+                InstBitsTableName.str() + "ByHw = " + InstBitsTableName.str();
       } else {
-        Case += "      case " + itostr(ModeId) + ": InstBitsByHw = InstBits_" +
-                CGH.getMode(ModeId).Name.str();
+        Case += "      case " + itostr(ModeId) + ": " +
+                InstBitsTableName.str() + "ByHw = " + InstBitsTableName.str() +
+                "_" + CGH.getModeName(ModeId).str();
       }
       Case += "; break;\n";
     }
     Case += "      };\n";
 
-    // We need to remodify the 'Inst' value from the table we found above.
+    // Reload Inst from the selected HwMode table.
     if (UseAPInt) {
-      int NumWords = APInt::getNumWords(BitWidth);
-      Case += "      Inst = APInt(" + itostr(BitWidth);
-      Case += ", ArrayRef(InstBitsByHw + TableIndex * " + itostr(NumWords) +
-              ", " + itostr(NumWords);
-      Case += "));\n";
+      if (BaseEncodings.empty()) {
+        int NumWords = APInt::getNumWords(BitWidth);
+        Case += "      Inst = APInt(" + itostr(BitWidth);
+        Case += ", ArrayRef(InstBitsByHw + TableIndex * " + itostr(NumWords) +
+                ", " + itostr(NumWords);
+        Case += "));\n";
+      } else {
+        Case += "      InstBitsIndex = InstBitsIndicesByHw[TableIndex];\n";
+        Case += "      Inst = APInt(" + itostr(BitWidth) +
+                ", ArrayRef(InstBits[InstBitsIndex]));\n";
+      }
       Case += "      Value = Inst;\n";
     } else {
       Case += "      Value = InstBitsByHw[TableIndex];\n";
@@ -361,6 +386,90 @@ static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
     OS << ((I > 0) ? ", " : "") << "UINT64_C(" << Bits.getRawData()[I] << ")";
 }
 
+APInt CodeEmitterGen::getInstructionBaseValue(const CodeGenInstruction *CGI,
+                                              unsigned HwMode) {
+  const Record *R = CGI->TheDef;
+  const Record *EncodingDef = R;
+  if (const Record *RV = R->getValueAsOptionalDef("EncodingInfos")) {
+    EncodingInfoByHwMode EBM(RV, CGH);
+    if (!EBM.hasMode(HwMode))
+      return APInt(BitWidth, 0);
+    EncodingDef = EBM.get(HwMode);
+  }
+
+  const BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
+  APInt Value(BitWidth, 0);
+  for (unsigned I = 0, E = BI->getNumBits(); I != E; ++I) {
+    if (const auto *B = dyn_cast<BitInit>(BI->getBit(I)); B && B->getValue())
+      Value.setBit(I);
+  }
+  return Value;
+}
+
+void CodeEmitterGen::buildBaseEncodingPool(
+    ArrayRef<const CodeGenInstruction *> NumberedInstructions,
+    const std::set<unsigned> &HwModes) {
+  assert(UseAPInt && "pooling is only used for multiword encodings");
+
+  const unsigned NumWords = APInt::getNumWords(BitWidth);
+  DenseMap<APInt, unsigned> ValueToIndex;
+  BaseEncodings.IndicesByHwMode.try_emplace(DefaultMode);
+  for (unsigned HwMode : HwModes)
+    BaseEncodings.IndicesByHwMode.try_emplace(HwMode);
+
+  for (auto &[HwMode, Indices] : BaseEncodings.IndicesByHwMode) {
+    for (const CodeGenInstruction *CGI : NumberedInstructions) {
+      APInt Value = getInstructionBaseValue(CGI, HwMode);
+      auto [It, Inserted] =
+          ValueToIndex.try_emplace(Value, BaseEncodings.Values.size());
+      if (Inserted)
+        BaseEncodings.Values.push_back(std::move(Value));
+      Indices.push_back(It->second);
+    }
+  }
+
+  const uint64_t NumValues = BaseEncodings.Values.size();
+  BaseEncodings.IndexBitWidth =
+      std::max<uint64_t>(8, PowerOf2Ceil(Log2_64_Ceil(NumValues)));
+  if (BaseEncodings.IndexBitWidth > 32) {
+    BaseEncodings = {};
+    return;
+  }
+
+  const uint64_t NumTables = BaseEncodings.IndicesByHwMode.size();
+  const uint64_t RawSize =
+      NumTables * NumberedInstructions.size() * NumWords * sizeof(uint64_t);
+  const uint64_t PooledSize = NumValues * NumWords * sizeof(uint64_t) +
+                              NumTables * NumberedInstructions.size() *
+                                  (BaseEncodings.IndexBitWidth / 8);
+  if (PooledSize >= RawSize)
+    BaseEncodings = {};
+}
+
+void CodeEmitterGen::emitBaseEncodingPool(raw_ostream &O) {
+  const unsigned NumWords = APInt::getNumWords(BitWidth);
+  O << "  static const uint64_t InstBits[][" << NumWords << "] = {\n";
+  for (const APInt &Value : BaseEncodings.Values) {
+    O << "    {";
+    emitInstBits(O, Value);
+    O << "},\n";
+  }
+  O << "  };\n";
+
+  for (const auto &[HwMode, Indices] : BaseEncodings.IndicesByHwMode) {
+    O << formatv("  static const uint{0}_t InstBitsIndices",
+                 BaseEncodings.IndexBitWidth);
+    if (HwMode != DefaultMode)
+      O << "_" << CGH.getModeName(HwMode);
+    O << "[] = {\n";
+    for (unsigned Index : Indices)
+      O << "    " << Index << ",\n";
+    O << "  };\n";
+  }
+  O << "  static_assert(sizeof(InstBits) / sizeof(InstBits[0]) <=\n"
+       "                (UINT64_C(1) << (sizeof(InstBitsIndices[0]) * 8)));\n";
+}
+
 void CodeEmitterGen::emitInstructionBaseValues(
     raw_ostream &O, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
     unsigned HwMode) {
@@ -372,29 +481,7 @@ void CodeEmitterGen::emitInstructionBaseValues(
 
   for (const CodeGenInstruction *CGI : NumberedInstructions) {
     const Record *R = CGI->TheDef;
-    const Record *EncodingDef = R;
-    if (const Record *RV = R->getValueAsOptionalDef("EncodingInfos")) {
-      EncodingInfoByHwMode EBM(RV, CGH);
-      if (EBM.hasMode(HwMode)) {
-        EncodingDef = EBM.get(HwMode);
-      } else {
-        // If the HwMode does not match, then Encoding '0'
-        // should be generated.
-        APInt Value(BitWidth, 0);
-        O << "    ";
-        emitInstBits(O, Value);
-        O << "," << '\t' << "// " << R->getName() << "\n";
-        continue;
-      }
-    }
-    const BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
-
-    // Start by filling in fixed values.
-    APInt Value(BitWidth, 0);
-    for (unsigned I = 0, E = BI->getNumBits(); I != E; ++I) {
-      if (const auto *B = dyn_cast<BitInit>(BI->getBit(I)); B && B->getValue())
-        Value.setBit(I);
-    }
+    APInt Value = getInstructionBaseValue(CGI, HwMode);
     O << "    ";
     emitInstBits(O, Value);
     O << "," << '\t' << "// " << R->getName() << "\n";
@@ -436,6 +523,8 @@ void CodeEmitterGen::run(raw_ostream &O) {
     BitWidth = std::max(BitWidth, BI->getNumBits());
   }
   UseAPInt = BitWidth > 64;
+  if (UseAPInt)
+    buildBaseEncodingPool(EncodedInstructions, HwModes);
 
   // Emit function declaration
   if (UseAPInt) {
@@ -453,17 +542,24 @@ void CodeEmitterGen::run(raw_ostream &O) {
   }
 
   // Emit instruction base values
-  emitInstructionBaseValues(O, EncodedInstructions, DefaultMode);
-  if (!HwModes.empty()) {
-    // Emit table for instrs whose encodings are controlled by HwModes.
+  if (BaseEncodings.empty()) {
+    emitInstructionBaseValues(O, EncodedInstructions, DefaultMode);
     for (unsigned HwMode : HwModes) {
       if (HwMode == DefaultMode)
         continue;
       emitInstructionBaseValues(O, EncodedInstructions, HwMode);
     }
+  } else {
+    emitBaseEncodingPool(O);
+  }
 
+  if (!HwModes.empty()) {
     // This pointer will be assigned to the HwMode table later.
-    O << "  const uint64_t *InstBitsByHw;\n";
+    if (BaseEncodings.empty())
+      O << "  const uint64_t *InstBitsByHw;\n";
+    else
+      O << formatv("  const uint{0}_t *InstBitsIndicesByHw;\n",
+                   BaseEncodings.IndexBitWidth);
   }
 
   // Map to accumulate all the cases.
@@ -498,10 +594,17 @@ void CodeEmitterGen::run(raw_ostream &O) {
   if (UseAPInt) {
     int NumWords = APInt::getNumWords(BitWidth);
     O << "  if (Scratch.getBitWidth() != " << BitWidth << ")\n"
-      << "    Scratch = Scratch.zext(" << BitWidth << ");\n"
-      << "  Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + TableIndex * "
-      << NumWords << ", " << NumWords << "));\n"
-      << "  APInt &Value = Inst;\n"
+      << "    Scratch = Scratch.zext(" << BitWidth << ");\n";
+    if (BaseEncodings.empty()) {
+      O << "  Inst = APInt(" << BitWidth
+        << ", ArrayRef(InstBits + TableIndex * " << NumWords << ", " << NumWords
+        << "));\n";
+    } else {
+      O << "  unsigned InstBitsIndex = InstBitsIndices[TableIndex];\n"
+        << "  Inst = APInt(" << BitWidth
+        << ", ArrayRef(InstBits[InstBitsIndex]));\n";
+    }
+    O << "  APInt &Value = Inst;\n"
       << "  APInt &op = Scratch;\n"
       << "  switch (opcode) {\n";
   } else {



More information about the llvm-commits mailing list