[AST] Various optimizations + refactoring in DeclarationName(Table)
Introduce the following optimizations in DeclarationName(Table):
1. Store common kinds inline in DeclarationName instead of
DeclarationNameExtra. Currently the kind of C++ constructor, destructor,
conversion function and overloaded operator names is stored in
DeclarationNameExtra. Instead store it inline in DeclarationName.
To do this align IdentifierInfo, CXXSpecialName, DeclarationNameExtra
and CXXOperatorIdName to 8 bytes so that we can use the lower 3 bits of
DeclarationName::Ptr. This is already the case on 64 bits archs anyway.
This also allow us to remove DeclarationNameExtra from CXXSpecialName
and CXXOperatorIdName, which shave off a pointer from CXXSpecialName.
2. Synchronize the enumerations DeclarationName::NameKind,
DeclarationName::StoredNameKind and Selector::IdentifierInfoFlag.
This makes DeclarationName::getNameKind much more efficient since we can
replace the switch table by a single comparison and an addition.
3. Put the overloaded operator names inline in DeclarationNameTable to remove
an indirection. This increase the size of DeclarationNameTable a little
bit but this is not important since it is only used in ASTContext, and
never copied nor moved from. This also get rid of the last dynamic
allocation in DeclarationNameTable.
Altogether these optimizations cut the run time of parsing all of Boost by
about 0.8%. While we are at it, do the following NFC modifications:
1. Put the internal classes CXXSpecialName, CXXDeductionGuideNameExtra,
CXXOperatorIdName, CXXLiteralOperatorIdName and DeclarationNameExtra
in a namespace detail since these classes are only meant to be used by
DeclarationName and DeclarationNameTable. Make this more explicit by making
the members of these classes private and friending DeclarationName(Table).
2. Make DeclarationName::getFETokenInfo a non-template since every users are
using it to get a void *. It was supposed to be used with a type to avoid
a subsequent static_cast.
3. Change the internal functions DeclarationName::getAs* to castAs* since when
we use them we already know the correct kind. This has no external impact
since all of these are private.
Reviewed By: erichkeane, rjmccall
Differential Revision: https://reviews.llvm.org/D52267
llvm-svn: 342729
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index 8434341..f2c152f 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -49,10 +49,12 @@
switch (LHS.getNameKind()) {
case DeclarationName::Identifier: {
- IdentifierInfo *LII = LHS.getAsIdentifierInfo();
- IdentifierInfo *RII = RHS.getAsIdentifierInfo();
- if (!LII) return RII ? -1 : 0;
- if (!RII) return 1;
+ IdentifierInfo *LII = LHS.castAsIdentifierInfo();
+ IdentifierInfo *RII = RHS.castAsIdentifierInfo();
+ if (!LII)
+ return RII ? -1 : 0;
+ if (!RII)
+ return 1;
return LII->getName().compare(RII->getName());
}
@@ -66,15 +68,18 @@
if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
return LHSSelector.getAsIdentifierInfo()->getName().compare(
- RHSSelector.getAsIdentifierInfo()->getName());
+ RHSSelector.getAsIdentifierInfo()->getName());
}
unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
switch (LHSSelector.getNameForSlot(I).compare(
- RHSSelector.getNameForSlot(I))) {
- case -1: return -1;
- case 1: return 1;
- default: break;
+ RHSSelector.getNameForSlot(I))) {
+ case -1:
+ return -1;
+ case 1:
+ return 1;
+ default:
+ break;
}
}
@@ -102,7 +107,7 @@
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName().compare(
- RHS.getCXXLiteralIdentifier()->getName());
+ RHS.getCXXLiteralIdentifier()->getName());
case DeclarationName::CXXUsingDirective:
return 0;
@@ -131,25 +136,24 @@
}
void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
- DeclarationName &N = *this;
- switch (N.getNameKind()) {
+ switch (getNameKind()) {
case DeclarationName::Identifier:
- if (const IdentifierInfo *II = N.getAsIdentifierInfo())
+ if (const IdentifierInfo *II = getAsIdentifierInfo())
OS << II->getName();
return;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- N.getObjCSelector().print(OS);
+ getObjCSelector().print(OS);
return;
case DeclarationName::CXXConstructorName:
- return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
+ return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
case DeclarationName::CXXDestructorName:
OS << '~';
- return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy);
+ return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy);
case DeclarationName::CXXDeductionGuideName:
OS << "<deduction guide for ";
@@ -158,13 +162,13 @@
return;
case DeclarationName::CXXOperatorName: {
- static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
- nullptr,
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- Spelling,
+ static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+ nullptr,
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ Spelling,
#include "clang/Basic/OperatorKinds.def"
};
- const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
+ const char *OpName = OperatorNames[getCXXOverloadedOperator()];
assert(OpName && "not an overloaded operator");
OS << "operator";
@@ -175,12 +179,12 @@
}
case DeclarationName::CXXLiteralOperatorName:
- OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
+ OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
return;
case DeclarationName::CXXConversionFunctionName: {
OS << "operator ";
- QualType Type = N.getCXXNameType();
+ QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>()) {
OS << *Rec->getDecl();
return;
@@ -209,46 +213,6 @@
} // namespace clang
-DeclarationName::NameKind DeclarationName::getNameKind() const {
- switch (getStoredNameKind()) {
- case StoredIdentifier: return Identifier;
- case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
- case StoredObjCOneArgSelector: return ObjCOneArgSelector;
-
- case StoredDeclarationNameExtra:
- switch (getExtra()->ExtraKindOrNumArgs) {
- case DeclarationNameExtra::CXXConstructor:
- return CXXConstructorName;
-
- case DeclarationNameExtra::CXXDestructor:
- return CXXDestructorName;
-
- case DeclarationNameExtra::CXXDeductionGuide:
- return CXXDeductionGuideName;
-
- case DeclarationNameExtra::CXXConversionFunction:
- return CXXConversionFunctionName;
-
- case DeclarationNameExtra::CXXLiteralOperator:
- return CXXLiteralOperatorName;
-
- case DeclarationNameExtra::CXXUsingDirective:
- return CXXUsingDirective;
-
- default:
- // Check if we have one of the CXXOperator* enumeration values.
- if (getExtra()->ExtraKindOrNumArgs <
- DeclarationNameExtra::CXXUsingDirective)
- return CXXOperatorName;
-
- return ObjCMultiArgSelector;
- }
- }
-
- // Can't actually get here.
- llvm_unreachable("This should be unreachable!");
-}
-
bool DeclarationName::isDependentName() const {
QualType T = getCXXNameType();
if (!T.isNull() && T->isDependentType())
@@ -269,122 +233,56 @@
return OS.str();
}
-QualType DeclarationName::getCXXNameType() const {
- if (CXXSpecialName *CXXName = getAsCXXSpecialName())
- return CXXName->Type;
- else
- return QualType();
-}
-
-TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const {
- if (auto *Guide = getAsCXXDeductionGuideNameExtra())
- return Guide->Template;
- return nullptr;
-}
-
-OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
- if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
- unsigned value
- = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
- return static_cast<OverloadedOperatorKind>(value);
- } else {
- return OO_None;
- }
-}
-
-IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
- if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
- return CXXLit->ID;
- else
- return nullptr;
-}
-
-void *DeclarationName::getFETokenInfoAsVoidSlow() const {
+void *DeclarationName::getFETokenInfoSlow() const {
switch (getNameKind()) {
case Identifier:
- llvm_unreachable("Handled by getFETokenInfo()");
-
+ llvm_unreachable("case Identifier already handled by getFETokenInfo!");
case CXXConstructorName:
case CXXDestructorName:
case CXXConversionFunctionName:
- return getAsCXXSpecialName()->FETokenInfo;
-
- case CXXDeductionGuideName:
- return getAsCXXDeductionGuideNameExtra()->FETokenInfo;
-
+ return castAsCXXSpecialNameExtra()->FETokenInfo;
case CXXOperatorName:
- return getAsCXXOperatorIdName()->FETokenInfo;
-
+ return castAsCXXOperatorIdName()->FETokenInfo;
+ case CXXDeductionGuideName:
+ return castAsCXXDeductionGuideNameExtra()->FETokenInfo;
case CXXLiteralOperatorName:
- return getAsCXXLiteralOperatorIdName()->FETokenInfo;
-
+ return castAsCXXLiteralOperatorIdName()->FETokenInfo;
default:
- llvm_unreachable("Declaration name has no FETokenInfo");
+ llvm_unreachable("DeclarationName has no FETokenInfo!");
}
}
-void DeclarationName::setFETokenInfo(void *T) {
+void DeclarationName::setFETokenInfoSlow(void *T) {
switch (getNameKind()) {
case Identifier:
- getAsIdentifierInfo()->setFETokenInfo(T);
- break;
-
+ llvm_unreachable("case Identifier already handled by setFETokenInfo!");
case CXXConstructorName:
case CXXDestructorName:
case CXXConversionFunctionName:
- getAsCXXSpecialName()->FETokenInfo = T;
+ castAsCXXSpecialNameExtra()->FETokenInfo = T;
break;
-
- case CXXDeductionGuideName:
- getAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
- break;
-
case CXXOperatorName:
- getAsCXXOperatorIdName()->FETokenInfo = T;
+ castAsCXXOperatorIdName()->FETokenInfo = T;
break;
-
+ case CXXDeductionGuideName:
+ castAsCXXDeductionGuideNameExtra()->FETokenInfo = T;
+ break;
case CXXLiteralOperatorName:
- getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
+ castAsCXXLiteralOperatorIdName()->FETokenInfo = T;
break;
-
default:
- llvm_unreachable("Declaration name has no FETokenInfo");
+ llvm_unreachable("DeclarationName has no FETokenInfo!");
}
}
-DeclarationName DeclarationName::getUsingDirectiveName() {
- // Single instance of DeclarationNameExtra for using-directive
- static const DeclarationNameExtra UDirExtra =
- { DeclarationNameExtra::CXXUsingDirective };
-
- uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
- Ptr |= StoredDeclarationNameExtra;
-
- return DeclarationName(Ptr);
-}
-
LLVM_DUMP_METHOD void DeclarationName::dump() const {
llvm::errs() << *this << '\n';
}
DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
// Initialize the overloaded operator names.
- CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
- for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
- CXXOperatorNames[Op].ExtraKindOrNumArgs
- = Op + DeclarationNameExtra::CXXConversionFunction;
- CXXOperatorNames[Op].FETokenInfo = nullptr;
- }
-}
-
-DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXConstructorName,
- Ty.getUnqualifiedType());
-}
-
-DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXDestructorName,
- Ty.getUnqualifiedType());
+ for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op)
+ CXXOperatorNames[Op].Kind = static_cast<OverloadedOperatorKind>(Op);
}
DeclarationName
@@ -398,65 +296,72 @@
if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos))
return DeclarationName(Name);
- auto *Name = new (Ctx) CXXDeductionGuideNameExtra;
- Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide;
- Name->Template = Template;
- Name->FETokenInfo = nullptr;
-
+ auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template);
CXXDeductionGuideNames.InsertNode(Name, InsertPos);
return DeclarationName(Name);
}
+DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) {
+ // The type of constructors is unqualified.
+ Ty = Ty.getUnqualifiedType();
+ // Do we already have this C++ constructor name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXConstructorName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXConstructorNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXConstructorName};
+}
+
+DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) {
+ // The type of destructors is unqualified.
+ Ty = Ty.getUnqualifiedType();
+ // Do we already have this C++ destructor name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXDestructorName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXDestructorNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXDestructorName};
+}
+
DeclarationName
DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) {
- return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
+ // Do we already have this C++ conversion function name ?
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(Ty.getAsOpaquePtr());
+ void *InsertPos = nullptr;
+ if (auto *Name =
+ CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos))
+ return {Name, DeclarationName::StoredCXXConversionFunctionName};
+
+ // We have to create it.
+ auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty);
+ CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos);
+ return {SpecialName, DeclarationName::StoredCXXConversionFunctionName};
}
DeclarationName
DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
CanQualType Ty) {
- assert(Kind >= DeclarationName::CXXConstructorName &&
- Kind <= DeclarationName::CXXConversionFunctionName &&
- "Kind must be a C++ special name kind");
-
- DeclarationNameExtra::ExtraKind EKind;
switch (Kind) {
case DeclarationName::CXXConstructorName:
- EKind = DeclarationNameExtra::CXXConstructor;
- assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
- break;
+ return getCXXConstructorName(Ty);
case DeclarationName::CXXDestructorName:
- EKind = DeclarationNameExtra::CXXDestructor;
- assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
- break;
+ return getCXXDestructorName(Ty);
case DeclarationName::CXXConversionFunctionName:
- EKind = DeclarationNameExtra::CXXConversionFunction;
- break;
+ return getCXXConversionFunctionName(Ty);
default:
- return DeclarationName();
+ llvm_unreachable("Invalid kind in getCXXSpecialName!");
}
-
- // Unique selector, to guarantee there is one per name.
- llvm::FoldingSetNodeID ID;
- ID.AddInteger(EKind);
- ID.AddPointer(Ty.getAsOpaquePtr());
-
- void *InsertPos = nullptr;
- if (CXXSpecialName *Name = CXXSpecialNames.FindNodeOrInsertPos(ID, InsertPos))
- return DeclarationName(Name);
-
- CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
- SpecialName->ExtraKindOrNumArgs = EKind;
- SpecialName->Type = Ty;
- SpecialName->FETokenInfo = nullptr;
-
- CXXSpecialNames.InsertNode(SpecialName, InsertPos);
- return DeclarationName(SpecialName);
-}
-
-DeclarationName
-DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
- return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
}
DeclarationName
@@ -465,15 +370,10 @@
ID.AddPointer(II);
void *InsertPos = nullptr;
- if (CXXLiteralOperatorIdName *Name =
- CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
- return DeclarationName (Name);
+ if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName(Name);
- CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
- LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
- LiteralName->ID = II;
- LiteralName->FETokenInfo = nullptr;
-
+ auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II);
CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
}