Skip to content

[NFC][TableGen] Remove small heap allocations in SearchableTableEmitter #147845

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 10, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 42 additions & 29 deletions llvm/utils/TableGen/SearchableTableEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,27 @@ 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;
const Record *Def;
Entry(StringRef N, int64_t V, const Record *D)
: Name(N), Value(V), Def(D) {}
};

std::string Name;
const Record *Class = nullptr;
std::string PreprocessorGuard;
std::vector<std::unique_ptr<Entry>> Entries;
DenseMap<const Record *, Entry *> EntryMap;
std::vector<Entry> Entries;
// Map from a Record to an index into the `Entries` vector.
DenseMap<const Record *, uint32_t> EntryMap;

const Entry *getEntry(const Record *Def) const {
auto II = EntryMap.find(Def);
if (II == EntryMap.end())
return nullptr;
return &Entries[II->second];
}
};

struct GenericField {
Expand Down Expand Up @@ -129,11 +143,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");
Expand Down Expand Up @@ -221,7 +236,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");

Expand Down Expand Up @@ -272,8 +287,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)
Expand Down Expand Up @@ -308,8 +323,8 @@ 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, _] : Enum.Entries)
OS << " " << Name << " = " << Value << ",\n";
OS << "};\n";

OS << "#endif\n\n";
Expand Down Expand Up @@ -625,31 +640,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.emplace_back(Name, Value, EntryRec);
}

// 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;
});
llvm::stable_sort(Enum.Entries, [](const GenericEnum::Entry &LHS,
const GenericEnum::Entry &RHS) {
return LHS.Name < RHS.Name;
});

for (size_t i = 0; i < Enum.Entries.size(); ++i)
Enum.Entries[i]->second = i;
for (auto [Idx, Entry] : enumerate(Enum.Entries))
Entry.Value = Idx;
}

// Populate the entry map after the `Entries` vector is finalized.
for (auto [Idx, Entry] : enumerate(Enum.Entries))
Enum.EntryMap.try_emplace(Entry.Def, Idx);
}

void SearchableTableEmitter::collectTableEntries(
Expand Down
Loading