[clang] c6f9c84 - [Clang] Reduce the size of Decl and classes derived from it (#87361)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 14 03:08:35 PDT 2024
Author: Nikolas Klauser
Date: 2024-04-14T12:08:30+02:00
New Revision: c6f9c84e498ee05a812511ae969773ff166fd25e
URL: https://github.com/llvm/llvm-project/commit/c6f9c84e498ee05a812511ae969773ff166fd25e
DIFF: https://github.com/llvm/llvm-project/commit/c6f9c84e498ee05a812511ae969773ff166fd25e.diff
LOG: [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.
Added:
Modified:
clang/include/clang/AST/DeclBase.h
clang/lib/AST/DeclBase.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 858450926455c6..4bee18767dd11b 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -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.
@@ -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)
@@ -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();
@@ -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());
@@ -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>(); }
@@ -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
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 66a727d9dd0c39..8c83c711d882d9 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -52,6 +52,8 @@
using namespace clang;
+static_assert(sizeof(Decl) <= 32, "Decl grew beyond 32 bytes!");
+
//===----------------------------------------------------------------------===//
// Statistics
//===----------------------------------------------------------------------===//
@@ -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;
@@ -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) {
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index ff72fc30c718f8..c5dd89e1c8a4db 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -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() ||
More information about the cfe-commits
mailing list