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

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 12 03:48:58 PDT 2025


================
@@ -2176,45 +2252,99 @@ populateInstruction(const CodeGenTarget &Target, const Record &EncodingDef,
 
 // emitFieldFromInstruction - Emit the templated helper function
 // fieldFromInstruction().
-// On Windows we make sure that this function is not inlined when
-// using the VS compiler. It has a bug which causes the function
-// to be optimized out in some circumstances. See llvm.org/pr38292
-static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
-  OS << R"(
-// Helper functions for extracting fields from encoded instructions.
-// InsnType must either be integral or an APInt-like object that must:
-// * be default-constructible and copy-constructible
-// * Support extractBitsAsZExtValue(numBits, startBit)
-// * Support the ~, &, ==, and != operators with other objects of the same type
-// * Support the != and bitwise & with uint64_t
-template <typename InsnType>
+//
+// On Windows we make sure that this function is not inlined when using the VS
+// compiler. It has a bug which causes the function to be optimized out in some
+// circumstances. See llvm.org/pr38292
+//
+// There are 4 variants of this function that can be generated under different
+// conditions:
+//
+// 1. Integer types (for non-templated code when using integer types and when
+//                   generating templated code).
+// 2. bitset types (for non-templated code with bitset type).
+// 3. APInt type (for variable length instructions).
+// 4. Non-Integer `InsnType` (when generating templated code)
+
+static void emitFieldFromInstruction(formatted_raw_ostream &OS,
+                                     bool GenerateIntType,
+                                     bool GenerateBitsetType,
+                                     bool GenerateAPIntType,
+                                     bool GenerateTemplateType) {
+  if (GenerateIntType) {
+    OS << R"(
+// Helper macro to disable inlining of `fieldFromInstruction` for integer types.
 #if defined(_MSC_VER) && !defined(__clang__)
-__declspec(noinline)
+#define DEC_EMIT_NO_INLINE __declspec(noinline)
+#else
+#define DEC_EMIT_NO_INLINE
 #endif
-static std::enable_if_t<std::is_integral<InsnType>::value, InsnType>
-fieldFromInstruction(const InsnType &insn, unsigned startBit,
-                     unsigned numBits) {
-  assert(startBit + numBits <= 64 && "Cannot support >64-bit extractions!");
-  assert(startBit + numBits <= (sizeof(InsnType) * 8) &&
+
+template <typename IntType>
+DEC_EMIT_NO_INLINE static 
+std::enable_if_t<std::is_integral_v<IntType>, IntType>
+fieldFromInstruction(const IntType &Insn, unsigned StartBit, unsigned Size) {
+  assert(StartBit + Size <= 64 && "Cannot support >64-bit extractions!");
+  assert(StartBit + Size <= (sizeof(IntType) * 8) &&
          "Instruction field out of bounds!");
-  InsnType fieldMask;
-  if (numBits == sizeof(InsnType) * 8)
-    fieldMask = (InsnType)(-1LL);
+  IntType fieldMask;
+  if (Size == sizeof(IntType) * 8)
+    fieldMask = (IntType)(-1LL);
   else
-    fieldMask = (((InsnType)1 << numBits) - 1) << startBit;
-  return (insn & fieldMask) >> startBit;
+    fieldMask = (((IntType)1 << Size) - 1) << StartBit;
+  return (Insn & fieldMask) >> StartBit;
+}
+#undef DEC_EMIT_NO_INLINE
+
+)";
+  }
+
+  if (GenerateBitsetType) {
+    // Emit a version that will work with a std::bitset.
+    OS << R"(
+template <size_t N>
+uint64_t fieldFromInstruction(const std::bitset<N>& Insn, unsigned StartBit,
+                              unsigned Size) {
+  assert(StartBit + Size <= N && "Instruction field out of bounds!");
+  assert(Size <= 64 && "Cannot support >64-bit extractions!");
+  if (Size == N)
+    return Insn.to_ullong();
+  const std::bitset<N> Mask((1ULL << Size) - 1);
+  return ((Insn >> StartBit) & Mask).to_ullong();
----------------
s-barannikov wrote:

This should work in `Size == N` case as well.


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


More information about the llvm-commits mailing list