Skip to content

Commit

Permalink
[Clang] Reduce the size of Decl and classes derived from it (#87361)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
philnik777 committed Apr 14, 2024
1 parent 09327ef commit c6f9c84
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 35 deletions.
72 changes: 47 additions & 25 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,17 +268,37 @@ class alignas(8) Decl {
/// }
/// void A::f(); // SemanticDC == namespace 'A'
/// // LexicalDC == global namespace
llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;

bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
// Compress the InvalidDecl and HasAttrs bits into DeclCtx to keep Decl below
// 32 bytes in size
llvm::PointerIntPair<
llvm::PointerIntPair<llvm::PointerUnion<DeclContext *, MultipleDC *>, 1,
bool>,
1, bool>
DeclCtxWithInvalidDeclAndHasAttrs;

bool isInSemaDC() const {
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
.getPointer()
.is<DeclContext *>();
}

bool isOutOfSemaDC() const {
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
.getPointer()
.is<MultipleDC *>();
}

MultipleDC *getMultipleDC() const {
return DeclCtx.get<MultipleDC*>();
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
.getPointer()
.get<MultipleDC *>();
}

DeclContext *getSemanticDC() const {
return DeclCtx.get<DeclContext*>();
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer()
.getPointer()
.get<DeclContext *>();
}

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

/// InvalidDecl - This indicates a semantic error occurred.
LLVM_PREFERRED_TYPE(bool)
unsigned InvalidDecl : 1;

/// HasAttrs - This indicates whether the decl has attributes or not.
LLVM_PREFERRED_TYPE(bool)
unsigned HasAttrs : 1;

/// Implicit - Whether this declaration was implicitly generated by
/// the implementation rather than explicitly written by the user.
LLVM_PREFERRED_TYPE(bool)
Expand Down Expand Up @@ -393,21 +405,22 @@ class alignas(8) Decl {
protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false),
Implicit(false), Used(false), Referenced(false),
DeclCtxWithInvalidDeclAndHasAttrs({DC, false}, false), Loc(L),
DeclKind(DK), Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
if (StatisticsEnabled) add(DK);
if (StatisticsEnabled)
add(DK);
}

Decl(Kind DK, EmptyShell Empty)
: DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false),
Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
Access(AS_none), FromASTFile(0),
: DeclKind(DK), Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
if (StatisticsEnabled) add(DK);
if (StatisticsEnabled)
add(DK);
}

virtual ~Decl();
Expand Down Expand Up @@ -520,7 +533,9 @@ class alignas(8) Decl {
return AccessSpecifier(Access);
}

bool hasAttrs() const { return HasAttrs; }
bool hasAttrs() const {
return DeclCtxWithInvalidDeclAndHasAttrs.getPointer().getInt();
}

void setAttrs(const AttrVec& Attrs) {
return setAttrsImpl(Attrs, getASTContext());
Expand Down Expand Up @@ -549,13 +564,17 @@ class alignas(8) Decl {
}

template <typename... Ts> void dropAttrs() {
if (!HasAttrs) return;
if (!hasAttrs())
return;

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

if (Vec.empty())
HasAttrs = false;
if (Vec.empty()) {
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setInt(false);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
}
}

template <typename T> void dropAttr() { dropAttrs<T>(); }
Expand Down Expand Up @@ -590,7 +609,10 @@ class alignas(8) Decl {
/// setInvalidDecl - Indicates the Decl had a semantic error. This
/// allows for graceful error recovery.
void setInvalidDecl(bool Invalid = true);
bool isInvalidDecl() const { return (bool) InvalidDecl; }

bool isInvalidDecl() const {
return DeclCtxWithInvalidDeclAndHasAttrs.getInt();
}

/// isImplicit - Indicates whether the declaration was implicitly
/// generated by the implementation. If false, this declaration
Expand Down
31 changes: 22 additions & 9 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@

using namespace clang;

static_assert(sizeof(Decl) <= 32, "Decl grew beyond 32 bytes!");

//===----------------------------------------------------------------------===//
// Statistics
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -130,7 +132,7 @@ const char *Decl::getDeclKindName() const {
}

void Decl::setInvalidDecl(bool Invalid) {
InvalidDecl = Invalid;
DeclCtxWithInvalidDeclAndHasAttrs.setInt(Invalid);
assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition());
if (!Invalid) {
return;
Expand Down Expand Up @@ -334,7 +336,9 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const {
Decl::~Decl() = default;

void Decl::setDeclContext(DeclContext *DC) {
DeclCtx = DC;
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setPointer(DC);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
}

void Decl::setLexicalDeclContext(DeclContext *DC) {
Expand Down Expand Up @@ -364,12 +368,16 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
ASTContext &Ctx) {
if (SemaDC == LexicalDC) {
DeclCtx = SemaDC;
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setPointer(SemaDC);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
} else {
auto *MDC = new (Ctx) Decl::MultipleDC();
MDC->SemanticDC = SemaDC;
MDC->LexicalDC = LexicalDC;
DeclCtx = MDC;
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setPointer(MDC);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
}
}

Expand Down Expand Up @@ -956,19 +964,24 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
}

void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) {
assert(!HasAttrs && "Decl already contains attrs.");
assert(!hasAttrs() && "Decl already contains attrs.");

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

AttrBlank = attrs;
HasAttrs = true;
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setInt(true);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
}

void Decl::dropAttrs() {
if (!HasAttrs) return;
if (!hasAttrs())
return;

HasAttrs = false;
auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer();
InnerPtr.setInt(false);
DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr);
getASTContext().eraseDeclAttrs(this);
}

Expand Down Expand Up @@ -996,7 +1009,7 @@ void Decl::addAttr(Attr *A) {
}

const AttrVec &Decl::getAttrs() const {
assert(HasAttrs && "No attrs to get!");
assert(hasAttrs() && "No attrs to get!");
return getASTContext().getDeclAttrs(this);
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
bool HasStandaloneLexicalDC = DeclBits.getNextBit();
bool HasAttrs = DeclBits.getNextBit();
D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit());
D->InvalidDecl = DeclBits.getNextBit();
D->DeclCtxWithInvalidDeclAndHasAttrs.setInt(DeclBits.getNextBit());
D->FromASTFile = true;

if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
Expand Down

0 comments on commit c6f9c84

Please sign in to comment.