Skip to content

Commit 10980e6

Browse files
committed
[NFC][TableGen] Remove small heap allocations in SearchableTableEmitter
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 9293b65 commit 10980e6

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

llvm/utils/TableGen/SearchableTableEmitter.cpp

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,27 @@ static int64_t getInt(const Record *R, StringRef Field) {
4444

4545
namespace {
4646
struct GenericEnum {
47-
using Entry = std::pair<StringRef, int64_t>;
47+
struct Entry {
48+
StringRef Name;
49+
int64_t Value;
50+
const Record *Def;
51+
Entry(StringRef N, int64_t V, const Record *D)
52+
: Name(N), Value(V), Def(D) {}
53+
};
4854

4955
std::string Name;
5056
const Record *Class = nullptr;
5157
std::string PreprocessorGuard;
52-
std::vector<std::unique_ptr<Entry>> Entries;
53-
DenseMap<const Record *, Entry *> EntryMap;
58+
std::vector<Entry> Entries;
59+
// Map from a Record to an index into the `Entries` vector.
60+
DenseMap<const Record *, uint32_t> EntryMap;
61+
62+
const Entry *getEntry(const Record *Def) const {
63+
auto II = EntryMap.find(Def);
64+
if (II == EntryMap.end())
65+
return nullptr;
66+
return &Entries[II->second];
67+
}
5468
};
5569

5670
struct GenericField {
@@ -129,11 +143,12 @@ class SearchableTableEmitter {
129143
else if (Field.IsInstruction)
130144
return I->getAsString();
131145
else if (Field.Enum) {
132-
auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()];
146+
const GenericEnum::Entry *Entry =
147+
Field.Enum->getEntry(cast<DefInit>(I)->getDef());
133148
if (!Entry)
134149
PrintFatalError(Loc,
135150
Twine("Entry for field '") + Field.Name + "' is null");
136-
return Entry->first.str();
151+
return Entry->Name.str();
137152
}
138153
PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
139154
"'; expected: bit, bits, string, or code");
@@ -221,7 +236,7 @@ int64_t SearchableTableEmitter::getNumericKey(const SearchIndex &Index,
221236
}
222237
if (Field.Enum) {
223238
const Record *EnumEntry = Rec->getValueAsDef(Field.Name);
224-
return Field.Enum->EntryMap[EnumEntry]->second;
239+
return Field.Enum->getEntry(EnumEntry)->Value;
225240
}
226241
assert(isa<BitsRecTy>(Field.RecType) && "unexpected field type");
227242

@@ -272,8 +287,8 @@ bool SearchableTableEmitter::compareBy(const Record *LHS, const Record *RHS,
272287
} else if (Field.Enum) {
273288
auto LHSr = cast<DefInit>(LHSI)->getDef();
274289
auto RHSr = cast<DefInit>(RHSI)->getDef();
275-
int64_t LHSv = Field.Enum->EntryMap[LHSr]->second;
276-
int64_t RHSv = Field.Enum->EntryMap[RHSr]->second;
290+
int64_t LHSv = Field.Enum->getEntry(LHSr)->Value;
291+
int64_t RHSv = Field.Enum->getEntry(RHSr)->Value;
277292
if (LHSv < RHSv)
278293
return true;
279294
if (LHSv > RHSv)
@@ -308,8 +323,8 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
308323
emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
309324

310325
OS << "enum " << Enum.Name << " {\n";
311-
for (const auto &Entry : Enum.Entries)
312-
OS << " " << Entry->first << " = " << Entry->second << ",\n";
326+
for (const auto &[Name, Value, _] : Enum.Entries)
327+
OS << " " << Name << " = " << Value << ",\n";
313328
OS << "};\n";
314329

315330
OS << "#endif\n\n";
@@ -625,31 +640,29 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
625640
void SearchableTableEmitter::collectEnumEntries(
626641
GenericEnum &Enum, StringRef NameField, StringRef ValueField,
627642
ArrayRef<const Record *> Items) {
643+
Enum.Entries.reserve(Items.size());
628644
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());
645+
StringRef Name = NameField.empty() ? EntryRec->getName()
646+
: EntryRec->getValueAsString(NameField);
647+
int64_t Value = ValueField.empty() ? 0 : getInt(EntryRec, ValueField);
648+
Enum.Entries.emplace_back(Name, Value, EntryRec);
641649
}
642650

651+
// If no values are provided for enums, assign values in the order of sorted
652+
// enum names.
643653
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-
});
654+
llvm::stable_sort(Enum.Entries, [](const GenericEnum::Entry &LHS,
655+
const GenericEnum::Entry &RHS) {
656+
return LHS.Name < RHS.Name;
657+
});
649658

650-
for (size_t i = 0; i < Enum.Entries.size(); ++i)
651-
Enum.Entries[i]->second = i;
659+
for (auto [Idx, Entry] : enumerate(Enum.Entries))
660+
Entry.Value = Idx;
652661
}
662+
663+
// Populate the entry map after the `Entries` vector is finalized.
664+
for (auto [Idx, Entry] : enumerate(Enum.Entries))
665+
Enum.EntryMap.try_emplace(Entry.Def, Idx);
653666
}
654667

655668
void SearchableTableEmitter::collectTableEntries(

0 commit comments

Comments
 (0)