[llvm] [NFC][TableGen] Remove small heap allocations in SearchableTableEmitter (PR #147845)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 9 18:06:07 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-tablegen

Author: Rahul Joshi (jurahul)

<details>
<summary>Changes</summary>

Change `GenericEnum` to not heap allocate its entries. Instead stash them directly in the `Entries` vector. Change `EntryMap` to hold an index as opposed to a pointer to the entry (the original reason why they were unique_ptr).

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


1 Files Affected:

- (modified) llvm/utils/TableGen/SearchableTableEmitter.cpp (+42-30) 


``````````diff
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index 38fc1ee5e4020..4dd651affa874 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -17,6 +17,7 @@
 #include "Common/CodeGenTarget.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/TableGen/Error.h"
@@ -44,13 +45,23 @@ static int64_t getInt(const Record *R, StringRef Field) {
 
 namespace {
 struct GenericEnum {
-  using Entry = std::pair<StringRef, int64_t>;
+  struct Entry {
+    StringRef Name;
+    int64_t Value;
+    Entry(StringRef N, int64_t V) : Name(N), Value(V) {}
+  };
 
   std::string Name;
   const Record *Class = nullptr;
   std::string PreprocessorGuard;
-  std::vector<std::unique_ptr<Entry>> Entries;
-  DenseMap<const Record *, Entry *> EntryMap;
+  MapVector<const Record *, Entry> Entries;
+
+  const Entry *getEntry(const Record *Def) const {
+    auto II = Entries.find(Def);
+    if (II == Entries.end())
+      return nullptr;
+    return &II->second;
+  }
 };
 
 struct GenericField {
@@ -129,11 +140,12 @@ class SearchableTableEmitter {
     else if (Field.IsInstruction)
       return I->getAsString();
     else if (Field.Enum) {
-      auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()];
+      const GenericEnum::Entry *Entry =
+          Field.Enum->getEntry(cast<DefInit>(I)->getDef());
       if (!Entry)
         PrintFatalError(Loc,
                         Twine("Entry for field '") + Field.Name + "' is null");
-      return Entry->first.str();
+      return Entry->Name.str();
     }
     PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
                              "'; expected: bit, bits, string, or code");
@@ -221,7 +233,7 @@ int64_t SearchableTableEmitter::getNumericKey(const SearchIndex &Index,
   }
   if (Field.Enum) {
     const Record *EnumEntry = Rec->getValueAsDef(Field.Name);
-    return Field.Enum->EntryMap[EnumEntry]->second;
+    return Field.Enum->getEntry(EnumEntry)->Value;
   }
   assert(isa<BitsRecTy>(Field.RecType) && "unexpected field type");
 
@@ -272,8 +284,8 @@ bool SearchableTableEmitter::compareBy(const Record *LHS, const Record *RHS,
     } else if (Field.Enum) {
       auto LHSr = cast<DefInit>(LHSI)->getDef();
       auto RHSr = cast<DefInit>(RHSI)->getDef();
-      int64_t LHSv = Field.Enum->EntryMap[LHSr]->second;
-      int64_t RHSv = Field.Enum->EntryMap[RHSr]->second;
+      int64_t LHSv = Field.Enum->getEntry(LHSr)->Value;
+      int64_t RHSv = Field.Enum->getEntry(RHSr)->Value;
       if (LHSv < RHSv)
         return true;
       if (LHSv > RHSv)
@@ -308,8 +320,9 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
   emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
 
   OS << "enum " << Enum.Name << " {\n";
-  for (const auto &Entry : Enum.Entries)
-    OS << "  " << Entry->first << " = " << Entry->second << ",\n";
+  for (const auto &[Name, Value] :
+       make_second_range(Enum.Entries.getArrayRef()))
+    OS << "  " << Name << " = " << Value << ",\n";
   OS << "};\n";
 
   OS << "#endif\n\n";
@@ -625,30 +638,29 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
 void SearchableTableEmitter::collectEnumEntries(
     GenericEnum &Enum, StringRef NameField, StringRef ValueField,
     ArrayRef<const Record *> Items) {
+  Enum.Entries.reserve(Items.size());
   for (const Record *EntryRec : Items) {
-    StringRef Name;
-    if (NameField.empty())
-      Name = EntryRec->getName();
-    else
-      Name = EntryRec->getValueAsString(NameField);
-
-    int64_t Value = 0;
-    if (!ValueField.empty())
-      Value = getInt(EntryRec, ValueField);
-
-    Enum.Entries.push_back(std::make_unique<GenericEnum::Entry>(Name, Value));
-    Enum.EntryMap.try_emplace(EntryRec, Enum.Entries.back().get());
+    StringRef Name = NameField.empty() ? EntryRec->getName()
+                                       : EntryRec->getValueAsString(NameField);
+    int64_t Value = ValueField.empty() ? 0 : getInt(EntryRec, ValueField);
+    Enum.Entries.try_emplace(EntryRec, Name, Value);
   }
 
+  // If no values are provided for enums, assign values in the order of sorted
+  // enum names.
   if (ValueField.empty()) {
-    llvm::stable_sort(Enum.Entries,
-                      [](const std::unique_ptr<GenericEnum::Entry> &LHS,
-                         const std::unique_ptr<GenericEnum::Entry> &RHS) {
-                        return LHS->first < RHS->first;
-                      });
-
-    for (size_t i = 0; i < Enum.Entries.size(); ++i)
-      Enum.Entries[i]->second = i;
+    // Copy the map entries for sorting and clear the map.
+    auto SavedEntries = Enum.Entries.takeVector();
+    llvm::stable_sort(
+        SavedEntries,
+        [](const std::pair<const Record *, GenericEnum::Entry> &LHS,
+           const std::pair<const Record *, GenericEnum::Entry> &RHS) {
+          return LHS.second.Name < RHS.second.Name;
+        });
+
+    // Repopulate entries using the new sorted order.
+    for (auto [Idx, Entry] : enumerate(SavedEntries))
+      Enum.Entries.try_emplace(Entry.first, Entry.second.Name, Idx);
   }
 }
 

``````````

</details>


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


More information about the llvm-commits mailing list