[clang] [Clang] Reduce the size of Decl and classes derived from it (PR #87361)
Nikolas Klauser via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 14 00:10:15 PDT 2024
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/87361
>From b8a626116b0719c1acf75e9e7300df8e2bf82f99 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 2 Apr 2024 18:00:05 +0200
Subject: [PATCH 1/3] [Clang] Reduce the size of Decl and classes derived from
it
---
clang/include/clang/AST/DeclBase.h | 66 ++++++++++++++---------
clang/lib/AST/DeclBase.cpp | 29 ++++++----
clang/lib/Serialization/ASTReaderDecl.cpp | 2 +-
3 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 47ed6d0d1db0df..172bd581b527c8 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -268,17 +268,34 @@ class alignas(8) Decl {
/// }
/// void A::f(); // SemanticDC == namespace 'A'
/// // LexicalDC == global namespace
- llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
+ llvm::PointerIntPair<
+ llvm::PointerIntPair<llvm::PointerUnion<DeclContext *, MultipleDC *>, 1,
+ bool>,
+ 1, bool>
+ DeclCtxWithInvalidDeclAndHasAttrs;
- bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
- bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
+ 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 +305,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 +402,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 +530,7 @@ 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 +559,16 @@ 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 +603,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 04bbc49ab2f319..91e04f7a8a91be 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -130,7 +130,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 +334,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 +366,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 +962,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 +1007,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 a22f760408c634..2e186109327fb2 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -594,7 +594,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() ||
>From c17265390361c20230ce8ca22667e77068e3b2cb Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 8 Apr 2024 14:27:48 +0200
Subject: [PATCH 2/3] Address comments
---
clang/include/clang/AST/DeclBase.h | 3 +++
clang/lib/AST/DeclBase.cpp | 2 ++
2 files changed, 5 insertions(+)
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 172bd581b527c8..9a3f8c41de387e 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -268,6 +268,9 @@ class alignas(8) Decl {
/// }
/// void A::f(); // SemanticDC == namespace 'A'
/// // LexicalDC == global namespace
+
+ // 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>,
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 91e04f7a8a91be..c06b41d6b29f89 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
//===----------------------------------------------------------------------===//
>From 4c9ecd68ea7c2f550fd5168f07998fccd1cf3d42 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 12 Apr 2024 12:22:57 +0200
Subject: [PATCH 3/3] Fix formatting
---
clang/include/clang/AST/DeclBase.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 9a3f8c41de387e..1fedba95d8ea3c 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -533,7 +533,9 @@ class alignas(8) Decl {
return AccessSpecifier(Access);
}
- bool hasAttrs() const { return DeclCtxWithInvalidDeclAndHasAttrs.getPointer().getInt(); }
+ bool hasAttrs() const {
+ return DeclCtxWithInvalidDeclAndHasAttrs.getPointer().getInt();
+ }
void setAttrs(const AttrVec& Attrs) {
return setAttrsImpl(Attrs, getASTContext());
@@ -562,7 +564,8 @@ 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); });
More information about the cfe-commits
mailing list