Skip to content

Conversation

jurahul
Copy link
Contributor

@jurahul jurahul commented Sep 4, 2025

  • Replace manual code to convert a BitsInit to a uint64_t by using convertInitializerToInt where applicable.
  • Add BitsInit::convertKnownBitsToInt to handle existing patterns in DFAEmitter.cpp and RegisterInfoEmitter.cpp.
  • Consolidate 3 copies of the same function in X86 emitters into a single function.

@jurahul jurahul force-pushed the nfc_use_bitsinit_convertInitializerToInt branch 2 times, most recently from 4b7b39f to f6b5bda Compare September 4, 2025 22:29
Replace manual code to convert a `BitsInit` to a uint64_t by using
`convertInitializerToInt`.
@jurahul jurahul force-pushed the nfc_use_bitsinit_convertInitializerToInt branch from f6b5bda to a09eb70 Compare September 5, 2025 00:02
@jurahul jurahul marked this pull request as ready for review September 5, 2025 01:58
@jurahul jurahul requested a review from s-barannikov September 5, 2025 01:59
@llvmbot
Copy link
Member

llvmbot commented Sep 5, 2025

@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-tablegen

Author: Rahul Joshi (jurahul)

Changes
  • Replace manual code to convert a BitsInit to a uint64_t by using convertInitializerToInt where applicable.
  • Add BitsInit::convertKnownBitsToInt to handle existing patterns in DFAEmitter.cpp and RegisterInfoEmitter.cpp.
  • Consolidate 3 copies of the same function in X86 emitters into a single function.

Full diff: https://github.com/llvm/llvm-project/pull/156973.diff

9 Files Affected:

  • (modified) llvm/include/llvm/TableGen/Record.h (+3)
  • (modified) llvm/lib/TableGen/Record.cpp (+8)
  • (modified) llvm/utils/TableGen/DFAEmitter.cpp (+1-8)
  • (modified) llvm/utils/TableGen/InstrInfoEmitter.cpp (+5-9)
  • (modified) llvm/utils/TableGen/RegisterInfoEmitter.cpp (+1-5)
  • (modified) llvm/utils/TableGen/X86FoldTablesEmitter.cpp (-12)
  • (modified) llvm/utils/TableGen/X86InstrMappingEmitter.cpp (-12)
  • (modified) llvm/utils/TableGen/X86RecognizableInstr.cpp (+1-25)
  • (modified) llvm/utils/TableGen/X86RecognizableInstr.h (+12)
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 9d67d8b3b9293..d4fa1e5d65749 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -616,6 +616,9 @@ class BitsInit final : public TypedInit,
   convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
   std::optional<int64_t> convertInitializerToInt() const;
 
+  // Returns the set of known bits as a 64-bit integer.
+  uint64_t convertKnownBitsToInt() const;
+
   bool isComplete() const override;
   bool allInComplete() const;
   bool isConcrete() const override;
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 3657a15ab1989..051a896cfd1b4 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -525,6 +525,14 @@ std::optional<int64_t> BitsInit::convertInitializerToInt() const {
   return Result;
 }
 
+uint64_t BitsInit::convertKnownBitsToInt() const {
+  uint64_t Result = 0;
+  for (auto [Idx, InitV] : enumerate(getBits()))
+    if (auto *Bit = dyn_cast<BitInit>(InitV))
+      Result |= static_cast<int64_t>(Bit->getValue()) << Idx;
+  return Result;
+}
+
 const Init *
 BitsInit::convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
   SmallVector<const Init *, 16> NewBits(Bits.size());
diff --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp
index 0b90af2ea99fc..65052e7881e1b 100644
--- a/llvm/utils/TableGen/DFAEmitter.cpp
+++ b/llvm/utils/TableGen/DFAEmitter.cpp
@@ -303,16 +303,9 @@ StringRef Automaton::getActionSymbolType(StringRef A) {
 
 Transition::Transition(const Record *R, Automaton *Parent) {
   const BitsInit *NewStateInit = R->getValueAsBitsInit("NewState");
-  NewState = 0;
   assert(NewStateInit->getNumBits() <= sizeof(uint64_t) * 8 &&
          "State cannot be represented in 64 bits!");
-  for (unsigned I = 0; I < NewStateInit->getNumBits(); ++I) {
-    if (auto *Bit = dyn_cast<BitInit>(NewStateInit->getBit(I))) {
-      if (Bit->getValue())
-        NewState |= 1ULL << I;
-    }
-  }
-
+  NewState = NewStateInit->convertKnownBitsToInt();
   for (StringRef A : Parent->getActionSymbolFields()) {
     const RecordVal *SymbolV = R->getValue(A);
     if (const auto *Ty = dyn_cast<RecordRecTy>(SymbolV->getType())) {
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 0fc421682c897..9e03e28a26d8d 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -1273,16 +1273,12 @@ void InstrInfoEmitter::emitRecord(
   const BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
   if (!TSF)
     PrintFatalError(Inst.TheDef->getLoc(), "no TSFlags?");
-  uint64_t Value = 0;
-  for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
-    if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
-      Value |= uint64_t(Bit->getValue()) << i;
-    else
-      PrintFatalError(Inst.TheDef->getLoc(),
-                      "Invalid TSFlags bit in " + Inst.getName());
-  }
+  std::optional<uint64_t> Value = TSF->convertInitializerToInt();
+  if (!Value)
+    PrintFatalError(Inst.TheDef, "Invalid TSFlags bit in " + Inst.getName());
+
   OS << ", 0x";
-  OS.write_hex(Value);
+  OS.write_hex(*Value);
   OS << "ULL";
 
   OS << " },  // " << Inst.getName() << '\n';
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 2a311b7ff96b8..c4b1c5f5a6d9d 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1107,11 +1107,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) {
   for (const auto &RE : Regs) {
     const Record *Reg = RE.TheDef;
     const BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding");
-    uint64_t Value = 0;
-    for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) {
-      if (const BitInit *B = dyn_cast<BitInit>(BI->getBit(b)))
-        Value |= (uint64_t)B->getValue() << b;
-    }
+    uint64_t Value = BI->convertKnownBitsToInt();
     OS << "  " << Value << ",\n";
   }
   OS << "};\n"; // End of HW encoding table
diff --git a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp
index 762fae608bd19..b1f7b9a6b4ad9 100644
--- a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp
+++ b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp
@@ -245,18 +245,6 @@ static bool hasPtrTailcallRegClass(const CodeGenInstruction *Inst) {
   });
 }
 
-static uint8_t byteFromBitsInit(const BitsInit *B) {
-  unsigned N = B->getNumBits();
-  assert(N <= 8 && "Field is too large for uint8_t!");
-
-  uint8_t Value = 0;
-  for (unsigned I = 0; I != N; ++I) {
-    const BitInit *Bit = cast<BitInit>(B->getBit(I));
-    Value |= Bit->getValue() << I;
-  }
-  return Value;
-}
-
 static bool mayFoldFromForm(uint8_t Form) {
   switch (Form) {
   default:
diff --git a/llvm/utils/TableGen/X86InstrMappingEmitter.cpp b/llvm/utils/TableGen/X86InstrMappingEmitter.cpp
index 9f7e679edeeaa..be5e2a73e8d43 100644
--- a/llvm/utils/TableGen/X86InstrMappingEmitter.cpp
+++ b/llvm/utils/TableGen/X86InstrMappingEmitter.cpp
@@ -106,18 +106,6 @@ void X86InstrMappingEmitter::printTable(ArrayRef<Entry> Table, StringRef Name,
   printMacroEnd(Macro, OS);
 }
 
-static uint8_t byteFromBitsInit(const BitsInit *B) {
-  unsigned N = B->getNumBits();
-  assert(N <= 8 && "Field is too large for uint8_t!");
-
-  uint8_t Value = 0;
-  for (unsigned I = 0; I != N; ++I) {
-    const BitInit *Bit = cast<BitInit>(B->getBit(I));
-    Value |= Bit->getValue() << I;
-  }
-  return Value;
-}
-
 class IsMatch {
   const CodeGenInstruction *OldInst;
 
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index a56e07a8939e7..e87a1c9aa928e 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -72,30 +72,6 @@ unsigned X86Disassembler::getMemOperandSize(const Record *MemRec) {
   llvm_unreachable("Memory operand's size not known!");
 }
 
-/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
-///   Useful for switch statements and the like.
-///
-/// @param init - A reference to the BitsInit to be decoded.
-/// @return     - The field, with the first bit in the BitsInit as the lowest
-///               order bit.
-static uint8_t byteFromBitsInit(const BitsInit &init) {
-  int width = init.getNumBits();
-
-  assert(width <= 8 && "Field is too large for uint8_t!");
-
-  uint8_t mask = 0x01;
-  uint8_t ret = 0;
-
-  for (int index = 0; index < width; index++) {
-    if (cast<BitInit>(init.getBit(index))->getValue())
-      ret |= mask;
-
-    mask <<= 1;
-  }
-
-  return ret;
-}
-
 /// byteFromRec - Extract a value at most 8 bits in with from a Record given the
 ///   name of the field.
 ///
@@ -104,7 +80,7 @@ static uint8_t byteFromBitsInit(const BitsInit &init) {
 /// @return     - The field, as translated by byteFromBitsInit().
 static uint8_t byteFromRec(const Record *rec, StringRef name) {
   const BitsInit *bits = rec->getValueAsBitsInit(name);
-  return byteFromBitsInit(*bits);
+  return byteFromBitsInit(bits);
 }
 
 RecognizableInstrBase::RecognizableInstrBase(const CodeGenInstruction &insn) {
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h
index 2f60b99154796..b74e74dd3f6e7 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -383,6 +383,18 @@ bool isMemoryOperand(const Record *Rec);
 bool isImmediateOperand(const Record *Rec);
 unsigned getRegOperandSize(const Record *RegRec);
 unsigned getMemOperandSize(const Record *MemRec);
+
+/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
+///   Useful for switch statements and the like.
+///
+/// @param B - A pointer to the BitsInit to be decoded.
+/// @return  - The field, with the first bit in the BitsInit as the lowest
+///            order bit.
+inline uint8_t byteFromBitsInit(const BitsInit *B) {
+  assert(B->getNumBits() <= 8 && "Field is too large for uint8_t!");
+  return static_cast<uint8_t>(*B->convertInitializerToInt());
+}
+
 } // namespace X86Disassembler
 } // namespace llvm
 #endif

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jurahul jurahul merged commit ca6ac74 into llvm:main Sep 5, 2025
13 checks passed
@jurahul jurahul deleted the nfc_use_bitsinit_convertInitializerToInt branch September 5, 2025 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants