Skip to content

Commit 0354867

Browse files
authored
[NFC][TableGen] Remove small heap allocations in SearchableTableEmitter (#147845)
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).
1 parent 77d04ff commit 0354867

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

llvm/utils/TableGen/SearchableTableEmitter.cpp

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "Common/CodeGenTarget.h"
1818
#include "llvm/ADT/ArrayRef.h"
1919
#include "llvm/ADT/DenseMap.h"
20+
#include "llvm/ADT/MapVector.h"
2021
#include "llvm/ADT/STLExtras.h"
2122
#include "llvm/ADT/StringExtras.h"
2223
#include "llvm/TableGen/Error.h"
@@ -44,13 +45,23 @@ static int64_t getInt(const Record *R, StringRef Field) {
4445

4546
namespace {
4647
struct GenericEnum {
47-
using Entry = std::pair<StringRef, int64_t>;
48+
struct Entry {
49+
StringRef Name;
50+
int64_t Value;
51+
Entry(StringRef N, int64_t V) : Name(N), Value(V) {}
52+
};
4853

4954
std::string Name;
5055
const Record *Class = nullptr;
5156
std::string PreprocessorGuard;
52-
std::vector<std::unique_ptr<Entry>> Entries;
53-
DenseMap<const Record *, Entry *> EntryMap;
57+
MapVector<const Record *, Entry> Entries;
58+
59+
const Entry *getEntry(const Record *Def) const {
60+
auto II = Entries.find(Def);
61+
if (II == Entries.end())
62+
return nullptr;
63+
return &II->second;
64+
}
5465
};
5566

5667
struct GenericField {
@@ -129,11 +140,12 @@ class SearchableTableEmitter {
129140
else if (Field.IsInstruction)
130141
return I->getAsString();
131142
else if (Field.Enum) {
132-
auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()];
143+
const GenericEnum::Entry *Entry =
144+
Field.Enum->getEntry(cast<DefInit>(I)->getDef());
133145
if (!Entry)
134146
PrintFatalError(Loc,
135147
Twine("Entry for field '") + Field.Name + "' is null");
136-
return Entry->first.str();
148+
return Entry->Name.str();
137149
}
138150
PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
139151
"'; expected: bit, bits, string, or code");
@@ -221,7 +233,7 @@ int64_t SearchableTableEmitter::getNumericKey(const SearchIndex &Index,
221233
}
222234
if (Field.Enum) {
223235
const Record *EnumEntry = Rec->getValueAsDef(Field.Name);
224-
return Field.Enum->EntryMap[EnumEntry]->second;
236+
return Field.Enum->getEntry(EnumEntry)->Value;
225237
}
226238
assert(isa<BitsRecTy>(Field.RecType) && "unexpected field type");
227239

@@ -272,8 +284,8 @@ bool SearchableTableEmitter::compareBy(const Record *LHS, const Record *RHS,
272284
} else if (Field.Enum) {
273285
auto LHSr = cast<DefInit>(LHSI)->getDef();
274286
auto RHSr = cast<DefInit>(RHSI)->getDef();
275-
int64_t LHSv = Field.Enum->EntryMap[LHSr]->second;
276-
int64_t RHSv = Field.Enum->EntryMap[RHSr]->second;
287+
int64_t LHSv = Field.Enum->getEntry(LHSr)->Value;
288+
int64_t RHSv = Field.Enum->getEntry(RHSr)->Value;
277289
if (LHSv < RHSv)
278290
return true;
279291
if (LHSv > RHSv)
@@ -308,8 +320,9 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
308320
emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
309321

310322
OS << "enum " << Enum.Name << " {\n";
311-
for (const auto &Entry : Enum.Entries)
312-
OS << " " << Entry->first << " = " << Entry->second << ",\n";
323+
for (const auto &[Name, Value] :
324+
make_second_range(Enum.Entries.getArrayRef()))
325+
OS << " " << Name << " = " << Value << ",\n";
313326
OS << "};\n";
314327

315328
OS << "#endif\n\n";
@@ -625,30 +638,28 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
625638
void SearchableTableEmitter::collectEnumEntries(
626639
GenericEnum &Enum, StringRef NameField, StringRef ValueField,
627640
ArrayRef<const Record *> Items) {
641+
Enum.Entries.reserve(Items.size());
628642
for (const Record *EntryRec : Items) {
629-
StringRef Name;
630-
if (NameField.empty())
631-
Name = EntryRec->getName();
632-
else
633-
Name = EntryRec->getValueAsString(NameField);
634-
635-
int64_t Value = 0;
636-
if (!ValueField.empty())
637-
Value = getInt(EntryRec, ValueField);
638-
639-
Enum.Entries.push_back(std::make_unique<GenericEnum::Entry>(Name, Value));
640-
Enum.EntryMap.try_emplace(EntryRec, Enum.Entries.back().get());
643+
StringRef Name = NameField.empty() ? EntryRec->getName()
644+
: EntryRec->getValueAsString(NameField);
645+
int64_t Value = ValueField.empty() ? 0 : getInt(EntryRec, ValueField);
646+
Enum.Entries.try_emplace(EntryRec, Name, Value);
641647
}
642648

649+
// If no values are provided for enums, assign values in the order of sorted
650+
// enum names.
643651
if (ValueField.empty()) {
644-
llvm::stable_sort(Enum.Entries,
645-
[](const std::unique_ptr<GenericEnum::Entry> &LHS,
646-
const std::unique_ptr<GenericEnum::Entry> &RHS) {
647-
return LHS->first < RHS->first;
648-
});
649-
650-
for (size_t i = 0; i < Enum.Entries.size(); ++i)
651-
Enum.Entries[i]->second = i;
652+
// Copy the map entries for sorting and clear the map.
653+
auto SavedEntries = Enum.Entries.takeVector();
654+
using MapVectorEntryTy = std::pair<const Record *, GenericEnum::Entry>;
655+
llvm::stable_sort(SavedEntries, [](const MapVectorEntryTy &LHS,
656+
const MapVectorEntryTy &RHS) {
657+
return LHS.second.Name < RHS.second.Name;
658+
});
659+
660+
// Repopulate entries using the new sorted order.
661+
for (auto [Idx, Entry] : enumerate(SavedEntries))
662+
Enum.Entries.try_emplace(Entry.first, Entry.second.Name, Idx);
652663
}
653664
}
654665

0 commit comments

Comments
 (0)