Skip to content

Commit c6f9c84

Browse files
authored
[Clang] Reduce the size of Decl and classes derived from it (#87361)
Class | Old size (in bytes) | New size (in bytes) ----------------------------------|---------------------|-------------------- Decl | 40 | 32 AccessSpecDecl | 40 | 40 BlockDecl | 128 | 120 CapturedDecl | 88 | 80 EmptyDecl | 40 | 32 ExportDecl | 80 | 72 ExternCContextDecl | 72 | 64 FileScopeAsmDecl | 56 | 48 FriendDecl | 64 | 56 FriendTemplateDecl | 64 | 64 ImplicitConceptSpecializationDecl | 40 | 40 ImportDecl | 56 | 48 LifetimeExtendedTemporaryDecl | 72 | 64 LinkageSpecDecl | 80 | 72 NamedDecl | 48 | 40 ObjCPropertyImplDecl | 96 | 88 PragmaCommentDecl | 40 | 40 PragmaDetectMismatchDecl | 48 | 40 RequiresExprBodyDecl | 72 | 64 StaticAssertDecl | 64 | 56 TopLevelStmtDecl | 88 | 80 TranslationUnitDecl | 104 | 96 BaseUsingDecl | 56 | 48 UsingDecl | 88 | 80 UsingEnumDecl | 72 | 64 HLSLBufferDecl | 96 | 88 LabelDecl | 80 | 72 NamespaceAliasDecl | 96 | 88 NamespaceDecl | 112 | 104 ObjCCompatibleAliasDecl | 56 | 48 ObjCContainerDecl | 88 | 80 ObjCMethodDecl | 136 | 128 ObjCPropertyDecl | 128 | 120 TemplateDecl | 64 | 56 BuiltinTemplateDecl | 72 | 64 TypeDecl | 64 | 56 UnresolvedUsingIfExistsDecl | 48 | 40 UsingDirectiveDecl | 88 | 80 UsingPackDecl | 64 | 56 UsingShadowDecl | 80 | 72 ValueDecl | 56 | 48 When parsing libc++'s `<string>` header the used memory is reduced from 42.8MB to 42.5MB.
1 parent 09327ef commit c6f9c84

File tree

3 files changed

+70
-35
lines changed

3 files changed

+70
-35
lines changed

clang/include/clang/AST/DeclBase.h

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,37 @@ class alignas(8) Decl {
268268
/// }
269269
/// void A::f(); // SemanticDC == namespace 'A'
270270
/// // LexicalDC == global namespace
271-
llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
272271

273-
bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
274-
bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
272+
// Compress the InvalidDecl and HasAttrs bits into DeclCtx to keep Decl below
273+
// 32 bytes in size
274+
llvm::PointerIntPair<
275+
llvm::PointerIntPair<llvm::PointerUnion<DeclContext *, MultipleDC *>, 1,
276+
bool>,
277+
1, bool>
278+
DeclCtxWithInvalidDeclAndHasAttrs;
279+
280+
bool isInSemaDC() const {
281+
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
282+
.getPointer()
283+
.is<DeclContext *>();
284+
}
285+
286+
bool isOutOfSemaDC() const {
287+
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
288+
.getPointer()
289+
.is<MultipleDC *>();
290+
}
275291

276292
MultipleDC *getMultipleDC() const {
277-
return DeclCtx.get<MultipleDC*>();
293+
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
294+
.getPointer()
295+
.get<MultipleDC *>();
278296
}
279297

280298
DeclContext *getSemanticDC() const {
281-
return DeclCtx.get<DeclContext*>();
299+
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
300+
.getPointer()
301+
.get<DeclContext *>();
282302
}
283303

284304
/// Loc - The location of this decl.
@@ -288,14 +308,6 @@ class alignas(8) Decl {
288308
LLVM_PREFERRED_TYPE(Kind)
289309
unsigned DeclKind : 7;
290310

291-
/// InvalidDecl - This indicates a semantic error occurred.
292-
LLVM_PREFERRED_TYPE(bool)
293-
unsigned InvalidDecl : 1;
294-
295-
/// HasAttrs - This indicates whether the decl has attributes or not.
296-
LLVM_PREFERRED_TYPE(bool)
297-
unsigned HasAttrs : 1;
298-
299311
/// Implicit - Whether this declaration was implicitly generated by
300312
/// the implementation rather than explicitly written by the user.
301313
LLVM_PREFERRED_TYPE(bool)
@@ -393,21 +405,22 @@ class alignas(8) Decl {
393405
protected:
394406
Decl(Kind DK, DeclContext *DC, SourceLocation L)
395407
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
396-
DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false),
397-
Implicit(false), Used(false), Referenced(false),
408+
DeclCtxWithInvalidDeclAndHasAttrs({DC, false}, false), Loc(L),
409+
DeclKind(DK), Implicit(false), Used(false), Referenced(false),
398410
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
399411
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
400412
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
401-
if (StatisticsEnabled) add(DK);
413+
if (StatisticsEnabled)
414+
add(DK);
402415
}
403416

404417
Decl(Kind DK, EmptyShell Empty)
405-
: DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false),
406-
Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
407-
Access(AS_none), FromASTFile(0),
418+
: DeclKind(DK), Implicit(false), Used(false), Referenced(false),
419+
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
408420
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
409421
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
410-
if (StatisticsEnabled) add(DK);
422+
if (StatisticsEnabled)
423+
add(DK);
411424
}
412425

413426
virtual ~Decl();
@@ -520,7 +533,9 @@ class alignas(8) Decl {
520533
return AccessSpecifier(Access);
521534
}
522535

523-
bool hasAttrs() const { return HasAttrs; }
536+
bool hasAttrs() const {
537+
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer().getInt();
538+
}
524539

525540
void setAttrs(const AttrVec& Attrs) {
526541
return setAttrsImpl(Attrs, getASTContext());
@@ -549,13 +564,17 @@ class alignas(8) Decl {
549564
}
550565

551566
template <typename... Ts> void dropAttrs() {
552-
if (!HasAttrs) return;
567+
if (!hasAttrs())
568+
return;
553569

554570
AttrVec &Vec = getAttrs();
555571
llvm::erase_if(Vec, [](Attr *A) { return isa<Ts...>(A); });
556572

557-
if (Vec.empty())
558-
HasAttrs = false;
573+
if (Vec.empty()) {
574+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
575+
InnerPtr.setInt(false);
576+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
577+
}
559578
}
560579

561580
template <typename T> void dropAttr() { dropAttrs<T>(); }
@@ -590,7 +609,10 @@ class alignas(8) Decl {
590609
/// setInvalidDecl - Indicates the Decl had a semantic error. This
591610
/// allows for graceful error recovery.
592611
void setInvalidDecl(bool Invalid = true);
593-
bool isInvalidDecl() const { return (bool) InvalidDecl; }
612+
613+
bool isInvalidDecl() const {
614+
return DeclCtxWithInvalidDeclAndHasAttrs.getInt();
615+
}
594616

595617
/// isImplicit - Indicates whether the declaration was implicitly
596618
/// generated by the implementation. If false, this declaration

clang/lib/AST/DeclBase.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252

5353
using namespace clang;
5454

55+
static_assert(sizeof(Decl) <= 32, "Decl grew beyond 32 bytes!");
56+
5557
//===----------------------------------------------------------------------===//
5658
// Statistics
5759
//===----------------------------------------------------------------------===//
@@ -130,7 +132,7 @@ const char *Decl::getDeclKindName() const {
130132
}
131133

132134
void Decl::setInvalidDecl(bool Invalid) {
133-
InvalidDecl = Invalid;
135+
DeclCtxWithInvalidDeclAndHasAttrs.setInt(Invalid);
134136
assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition());
135137
if (!Invalid) {
136138
return;
@@ -334,7 +336,9 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const {
334336
Decl::~Decl() = default;
335337

336338
void Decl::setDeclContext(DeclContext *DC) {
337-
DeclCtx = DC;
339+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
340+
InnerPtr.setPointer(DC);
341+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
338342
}
339343

340344
void Decl::setLexicalDeclContext(DeclContext *DC) {
@@ -364,12 +368,16 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
364368
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
365369
ASTContext &Ctx) {
366370
if (SemaDC == LexicalDC) {
367-
DeclCtx = SemaDC;
371+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
372+
InnerPtr.setPointer(SemaDC);
373+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
368374
} else {
369375
auto *MDC = new (Ctx) Decl::MultipleDC();
370376
MDC->SemanticDC = SemaDC;
371377
MDC->LexicalDC = LexicalDC;
372-
DeclCtx = MDC;
378+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
379+
InnerPtr.setPointer(MDC);
380+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
373381
}
374382
}
375383

@@ -956,19 +964,24 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
956964
}
957965

958966
void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) {
959-
assert(!HasAttrs && "Decl already contains attrs.");
967+
assert(!hasAttrs() && "Decl already contains attrs.");
960968

961969
AttrVec &AttrBlank = Ctx.getDeclAttrs(this);
962970
assert(AttrBlank.empty() && "HasAttrs was wrong?");
963971

964972
AttrBlank = attrs;
965-
HasAttrs = true;
973+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
974+
InnerPtr.setInt(true);
975+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
966976
}
967977

968978
void Decl::dropAttrs() {
969-
if (!HasAttrs) return;
979+
if (!hasAttrs())
980+
return;
970981

971-
HasAttrs = false;
982+
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
983+
InnerPtr.setInt(false);
984+
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
972985
getASTContext().eraseDeclAttrs(this);
973986
}
974987

@@ -996,7 +1009,7 @@ void Decl::addAttr(Attr *A) {
9961009
}
9971010

9981011
const AttrVec &Decl::getAttrs() const {
999-
assert(HasAttrs && "No attrs to get!");
1012+
assert(hasAttrs() && "No attrs to get!");
10001013
return getASTContext().getDeclAttrs(this);
10011014
}
10021015

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
588588
bool HasStandaloneLexicalDC = DeclBits.getNextBit();
589589
bool HasAttrs = DeclBits.getNextBit();
590590
D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit());
591-
D->InvalidDecl = DeclBits.getNextBit();
591+
D->DeclCtxWithInvalidDeclAndHasAttrs.setInt(DeclBits.getNextBit());
592592
D->FromASTFile = true;
593593

594594
if (D->isTemplateParameter() || D->isTemplateParameterPack() ||

0 commit comments

Comments
 (0)