Skip to content

Commit 2bc6f9d

Browse files
jayfoadmshockwave
andauthored
[TableGen] Only store direct superclasses in Record (#123072)
In Record only store the direct superclasses instead of all superclasses. getSuperClasses recurses to find all superclasses when necessary. This gives a small reduction in memory usage. On lib/Target/X86/X86.td I measured about 2.0% reduction in total bytes allocated (measured by valgrind) and 1.3% reduction in peak memory usage (measured by /usr/bin/time -v). --------- Co-authored-by: Min-Yih Hsu <min@myhsu.dev>
1 parent 6e3b16b commit 2bc6f9d

File tree

16 files changed

+122
-146
lines changed

16 files changed

+122
-146
lines changed

clang/utils/TableGen/ClangAttrEmitter.cpp

+34-29
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,8 @@ createArgument(const Record &Arg, StringRef Attr,
15261526

15271527
if (!Ptr) {
15281528
// Search in reverse order so that the most-derived type is handled first.
1529-
for (const auto &[Base, _] : reverse(Search->getSuperClasses())) {
1529+
std::vector<const Record *> SCs = Search->getSuperClasses();
1530+
for (const Record *Base : reverse(SCs)) {
15301531
if ((Ptr = createArgument(Arg, Attr, Base)))
15311532
break;
15321533
}
@@ -1856,17 +1857,16 @@ static LateAttrParseKind getLateAttrParseKind(const Record *Attr) {
18561857
auto *LAPK = Attr->getValueAsDef(LateParsedStr);
18571858

18581859
// Typecheck the `LateParsed` field.
1859-
SmallVector<const Record *, 1> SuperClasses;
1860-
LAPK->getDirectSuperClasses(SuperClasses);
1861-
if (SuperClasses.size() != 1)
1860+
if (LAPK->getDirectSuperClasses().size() != 1)
18621861
PrintFatalError(Attr, "Field `" + Twine(LateParsedStr) +
18631862
"`should only have one super class");
18641863

1865-
if (SuperClasses[0]->getName() != LateAttrParseKindStr)
1864+
const Record *SuperClass = LAPK->getDirectSuperClasses()[0].first;
1865+
if (SuperClass->getName() != LateAttrParseKindStr)
18661866
PrintFatalError(
18671867
Attr, "Field `" + Twine(LateParsedStr) + "`should only have type `" +
18681868
Twine(LateAttrParseKindStr) + "` but found type `" +
1869-
SuperClasses[0]->getName() + "`");
1869+
SuperClass->getName() + "`");
18701870

18711871
// Get Kind and verify the enum name matches the name in `Attr.td`.
18721872
unsigned Kind = LAPK->getValueAsInt(KindFieldStr);
@@ -2465,8 +2465,8 @@ static void emitStringSwitchCases(std::map<StringRef, FSIVecTy> &Map,
24652465
}
24662466

24672467
static bool isTypeArgument(const Record *Arg) {
2468-
return !Arg->getSuperClasses().empty() &&
2469-
Arg->getSuperClasses().back().first->getName() == "TypeArgument";
2468+
return !Arg->getDirectSuperClasses().empty() &&
2469+
Arg->getDirectSuperClasses().back().first->getName() == "TypeArgument";
24702470
}
24712471

24722472
/// Emits the first-argument-is-type property for attributes.
@@ -2507,42 +2507,45 @@ static void emitClangAttrArgContextList(const RecordKeeper &Records,
25072507
}
25082508

25092509
static bool isIdentifierArgument(const Record *Arg) {
2510-
return !Arg->getSuperClasses().empty() &&
2511-
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
2510+
return !Arg->getDirectSuperClasses().empty() &&
2511+
StringSwitch<bool>(
2512+
Arg->getDirectSuperClasses().back().first->getName())
25122513
.Case("IdentifierArgument", true)
25132514
.Case("EnumArgument", true)
25142515
.Case("VariadicEnumArgument", true)
25152516
.Default(false);
25162517
}
25172518

25182519
static bool isVariadicIdentifierArgument(const Record *Arg) {
2519-
return !Arg->getSuperClasses().empty() &&
2520-
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
2520+
return !Arg->getDirectSuperClasses().empty() &&
2521+
StringSwitch<bool>(
2522+
Arg->getDirectSuperClasses().back().first->getName())
25212523
.Case("VariadicIdentifierArgument", true)
25222524
.Case("VariadicParamOrParamIdxArgument", true)
25232525
.Default(false);
25242526
}
25252527

25262528
static bool isVariadicExprArgument(const Record *Arg) {
2527-
return !Arg->getSuperClasses().empty() &&
2528-
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
2529+
return !Arg->getDirectSuperClasses().empty() &&
2530+
StringSwitch<bool>(
2531+
Arg->getDirectSuperClasses().back().first->getName())
25292532
.Case("VariadicExprArgument", true)
25302533
.Default(false);
25312534
}
25322535

25332536
static bool isStringLiteralArgument(const Record *Arg) {
2534-
if (Arg->getSuperClasses().empty())
2537+
if (Arg->getDirectSuperClasses().empty())
25352538
return false;
2536-
StringRef ArgKind = Arg->getSuperClasses().back().first->getName();
2539+
StringRef ArgKind = Arg->getDirectSuperClasses().back().first->getName();
25372540
if (ArgKind == "EnumArgument")
25382541
return Arg->getValueAsBit("IsString");
25392542
return ArgKind == "StringArgument";
25402543
}
25412544

25422545
static bool isVariadicStringLiteralArgument(const Record *Arg) {
2543-
if (Arg->getSuperClasses().empty())
2546+
if (Arg->getDirectSuperClasses().empty())
25442547
return false;
2545-
StringRef ArgKind = Arg->getSuperClasses().back().first->getName();
2548+
StringRef ArgKind = Arg->getDirectSuperClasses().back().first->getName();
25462549
if (ArgKind == "VariadicEnumArgument")
25472550
return Arg->getValueAsBit("IsString");
25482551
return ArgKind == "VariadicStringArgument";
@@ -2631,8 +2634,9 @@ static void emitClangAttrStrictIdentifierArgList(const RecordKeeper &Records,
26312634
}
26322635

26332636
static bool keywordThisIsaIdentifierInArgument(const Record *Arg) {
2634-
return !Arg->getSuperClasses().empty() &&
2635-
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
2637+
return !Arg->getDirectSuperClasses().empty() &&
2638+
StringSwitch<bool>(
2639+
Arg->getDirectSuperClasses().back().first->getName())
26362640
.Case("VariadicParamOrParamIdxArgument", true)
26372641
.Default(false);
26382642
}
@@ -2718,11 +2722,11 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS,
27182722
if (!R.getValueAsBit("ASTNode"))
27192723
continue;
27202724

2721-
ArrayRef<std::pair<const Record *, SMRange>> Supers = R.getSuperClasses();
2725+
std::vector<const Record *> Supers = R.getSuperClasses();
27222726
assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
27232727
std::string SuperName;
27242728
bool Inheritable = false;
2725-
for (const auto &[R, _] : reverse(Supers)) {
2729+
for (const Record *R : reverse(Supers)) {
27262730
if (R->getName() != "TargetSpecificAttr" &&
27272731
R->getName() != "DeclOrTypeAttr" && SuperName.empty())
27282732
SuperName = R->getName().str();
@@ -3419,10 +3423,10 @@ namespace {
34193423
AttrClass *findSuperClass(const Record *R) const {
34203424
// TableGen flattens the superclass list, so we just need to walk it
34213425
// in reverse.
3422-
auto SuperClasses = R->getSuperClasses();
3423-
for (signed i = 0, e = SuperClasses.size(); i != e; ++i) {
3424-
auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first);
3425-
if (SuperClass) return SuperClass;
3426+
std::vector<const Record *> SuperClasses = R->getSuperClasses();
3427+
for (const Record *R : reverse(SuperClasses)) {
3428+
if (AttrClass *SuperClass = findClassByRecord(R))
3429+
return SuperClass;
34263430
}
34273431
return nullptr;
34283432
}
@@ -4661,8 +4665,9 @@ static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) {
46614665
}
46624666

46634667
static bool isParamExpr(const Record *Arg) {
4664-
return !Arg->getSuperClasses().empty() &&
4665-
StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
4668+
return !Arg->getDirectSuperClasses().empty() &&
4669+
StringSwitch<bool>(
4670+
Arg->getDirectSuperClasses().back().first->getName())
46664671
.Case("ExprArgument", true)
46674672
.Case("VariadicExprArgument", true)
46684673
.Default(false);
@@ -4785,7 +4790,7 @@ void EmitClangAttrParsedAttrImpl(const RecordKeeper &Records, raw_ostream &OS) {
47854790
if (Arg->getValueAsBitOrUnset("Fake", UnusedUnset))
47864791
continue;
47874792
ArgNames.push_back(Arg->getValueAsString("Name").str());
4788-
for (const auto &[Class, _] : Arg->getSuperClasses()) {
4793+
for (const Record *Class : Arg->getSuperClasses()) {
47894794
if (Class->getName().starts_with("Variadic")) {
47904795
ArgNames.back().append("...");
47914796
break;

clang/utils/TableGen/NeonEmitter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2029,8 +2029,8 @@ void NeonEmitter::createIntrinsic(const Record *R,
20292029
std::vector<TypeSpec> TypeSpecs = TypeSpec::fromTypeSpecs(Types);
20302030

20312031
ClassKind CK = ClassNone;
2032-
if (R->getSuperClasses().size() >= 2)
2033-
CK = ClassMap[R->getSuperClasses()[1].first];
2032+
if (!R->getDirectSuperClasses().empty())
2033+
CK = ClassMap[R->getDirectSuperClasses()[0].first];
20342034

20352035
std::vector<std::pair<TypeSpec, TypeSpec>> NewTypeSpecs;
20362036
if (!CartesianProductWith.empty()) {

llvm/docs/TableGen/BackGuide.rst

+15-16
Original file line numberDiff line numberDiff line change
@@ -610,29 +610,28 @@ functions returns null.
610610
Getting Record Superclasses
611611
===========================
612612

613-
The ``Record`` class provides a function to obtain the superclasses of a
614-
record. It is named ``getSuperClasses`` and returns an ``ArrayRef`` of an
615-
array of ``std::pair`` pairs. The superclasses are in post-order: the order
616-
in which the superclasses were visited while copying their fields into the
617-
record. Each pair consists of a pointer to the ``Record`` instance for a
618-
superclass record and an instance of the ``SMRange`` class. The range
619-
indicates the source file locations of the beginning and end of the class
620-
definition.
621-
622-
This example obtains the superclasses of the ``Prototype`` record and then
623-
iterates over the pairs in the returned array.
613+
The ``Record`` class provides a function to obtain the direct superclasses
614+
of a record. It is named ``getDirectSuperClasses`` and returns an
615+
``ArrayRef`` of an array of ``std::pair`` pairs. Each pair consists of a
616+
pointer to the ``Record`` instance for a superclass record and an instance
617+
of the ``SMRange`` class. The range indicates the source file locations of
618+
the beginning and end of the class definition.
619+
620+
This example obtains the direct superclasses of the ``Prototype`` record and
621+
then iterates over the pairs in the returned array.
624622

625623
.. code-block:: text
626624
627625
ArrayRef<std::pair<const Record *, SMRange>>
628-
Superclasses = Prototype->getSuperClasses();
629-
for (const auto &SuperPair : Superclasses) {
626+
Superclasses = Prototype->getDirectSuperClasses();
627+
for (const auto &[Super, Range] : Superclasses) {
630628
...
631629
}
632630
633-
The ``Record`` class also provides a function, ``getDirectSuperClasses``, to
634-
append the *direct* superclasses of a record to a given vector of type
635-
``SmallVectorImpl<Record *>``.
631+
The ``Record`` class also provides a function, ``getSuperClasses``, to
632+
return a vector of *all* superclasses of a record. The superclasses are in
633+
post-order: the order in which the superclasses were visited while copying
634+
their fields into the record.
636635

637636
Emitting Text to the Output Stream
638637
==================================

llvm/include/llvm/TableGen/Record.h

+33-14
Original file line numberDiff line numberDiff line change
@@ -1667,9 +1667,9 @@ class Record {
16671667
SmallVector<AssertionInfo, 0> Assertions;
16681668
SmallVector<DumpInfo, 0> Dumps;
16691669

1670-
// All superclasses in the inheritance forest in post-order (yes, it
1670+
// Direct superclasses, which are roots of the inheritance forest (yes, it
16711671
// must be a forest; diamond-shaped inheritance is not allowed).
1672-
SmallVector<std::pair<const Record *, SMRange>, 0> SuperClasses;
1672+
SmallVector<std::pair<const Record *, SMRange>, 0> DirectSuperClasses;
16731673

16741674
// Tracks Record instances. Not owned by Record.
16751675
RecordKeeper &TrackedRecords;
@@ -1703,8 +1703,9 @@ class Record {
17031703
Record(const Record &O)
17041704
: Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
17051705
Values(O.Values), Assertions(O.Assertions),
1706-
SuperClasses(O.SuperClasses), TrackedRecords(O.TrackedRecords),
1707-
ID(getNewUID(O.getRecords())), Kind(O.Kind) {}
1706+
DirectSuperClasses(O.DirectSuperClasses),
1707+
TrackedRecords(O.TrackedRecords), ID(getNewUID(O.getRecords())),
1708+
Kind(O.Kind) {}
17081709

17091710
static unsigned getNewUID(RecordKeeper &RK);
17101711

@@ -1755,15 +1756,30 @@ class Record {
17551756
ArrayRef<AssertionInfo> getAssertions() const { return Assertions; }
17561757
ArrayRef<DumpInfo> getDumps() const { return Dumps; }
17571758

1758-
ArrayRef<std::pair<const Record *, SMRange>> getSuperClasses() const {
1759-
return SuperClasses;
1759+
/// Append all superclasses in post-order to \p Classes.
1760+
void getSuperClasses(std::vector<const Record *> &Classes) const {
1761+
for (const Record *SC : make_first_range(DirectSuperClasses)) {
1762+
SC->getSuperClasses(Classes);
1763+
Classes.push_back(SC);
1764+
}
1765+
}
1766+
1767+
/// Return all superclasses in post-order.
1768+
std::vector<const Record *> getSuperClasses() const {
1769+
std::vector<const Record *> Classes;
1770+
getSuperClasses(Classes);
1771+
return Classes;
17601772
}
17611773

17621774
/// Determine whether this record has the specified direct superclass.
1763-
bool hasDirectSuperClass(const Record *SuperClass) const;
1775+
bool hasDirectSuperClass(const Record *SuperClass) const {
1776+
return is_contained(make_first_range(DirectSuperClasses), SuperClass);
1777+
}
17641778

1765-
/// Append the direct superclasses of this record to Classes.
1766-
void getDirectSuperClasses(SmallVectorImpl<const Record *> &Classes) const;
1779+
/// Return the direct superclasses of this record.
1780+
ArrayRef<std::pair<const Record *, SMRange>> getDirectSuperClasses() const {
1781+
return DirectSuperClasses;
1782+
}
17671783

17681784
bool isTemplateArg(const Init *Name) const {
17691785
return llvm::is_contained(TemplateArgs, Name);
@@ -1831,29 +1847,32 @@ class Record {
18311847
void checkUnusedTemplateArgs();
18321848

18331849
bool isSubClassOf(const Record *R) const {
1834-
for (const auto &[SC, _] : SuperClasses)
1835-
if (SC == R)
1850+
for (const Record *SC : make_first_range(DirectSuperClasses)) {
1851+
if (SC == R || SC->isSubClassOf(R))
18361852
return true;
1853+
}
18371854
return false;
18381855
}
18391856

18401857
bool isSubClassOf(StringRef Name) const {
1841-
for (const auto &[SC, _] : SuperClasses) {
1858+
for (const Record *SC : make_first_range(DirectSuperClasses)) {
18421859
if (const auto *SI = dyn_cast<StringInit>(SC->getNameInit())) {
18431860
if (SI->getValue() == Name)
18441861
return true;
18451862
} else if (SC->getNameInitAsString() == Name) {
18461863
return true;
18471864
}
1865+
if (SC->isSubClassOf(Name))
1866+
return true;
18481867
}
18491868
return false;
18501869
}
18511870

1852-
void addSuperClass(const Record *R, SMRange Range) {
1871+
void addDirectSuperClass(const Record *R, SMRange Range) {
18531872
assert(!CorrespondingDefInit &&
18541873
"changing type of record after it has been referenced");
18551874
assert(!isSubClassOf(R) && "Already subclassing record!");
1856-
SuperClasses.emplace_back(R, Range);
1875+
DirectSuperClasses.emplace_back(R, Range);
18571876
}
18581877

18591878
/// If there are any field references that refer to fields that have been

llvm/lib/TableGen/DetailedRecordsBackend.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,14 @@ void DetailedRecordsEmitter::printTemplateArgs(const Record &Rec,
152152
// are enclosed in parentheses.
153153
void DetailedRecordsEmitter::printSuperclasses(const Record &Rec,
154154
raw_ostream &OS) {
155-
ArrayRef<std::pair<const Record *, SMRange>> Superclasses =
156-
Rec.getSuperClasses();
155+
std::vector<const Record *> Superclasses = Rec.getSuperClasses();
157156
if (Superclasses.empty()) {
158157
OS << " Superclasses: (none)\n";
159158
return;
160159
}
161160

162161
OS << " Superclasses:";
163-
for (const auto &[ClassRec, Loc] : Superclasses) {
162+
for (const Record *ClassRec : Superclasses) {
164163
if (Rec.hasDirectSuperClass(ClassRec))
165164
OS << formatv(" {0}", ClassRec->getNameInitAsString());
166165
else

llvm/lib/TableGen/JSONBackend.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ void JSONEmitter::run(raw_ostream &OS) {
151151

152152
json::Array SuperClasses;
153153
// Add this def to the instance list for each of its superclasses.
154-
for (const auto &[SuperClass, Loc] : Def->getSuperClasses()) {
154+
for (const Record *SuperClass : Def->getSuperClasses()) {
155155
std::string SuperName = SuperClass->getNameInitAsString();
156156
SuperClasses.push_back(SuperName);
157157
InstanceLists[SuperName].push_back(Name);

0 commit comments

Comments
 (0)