From: Benjamin Kramer Date: Wed, 21 Oct 2015 16:33:15 +0000 (+0000) Subject: Shrink DynTypedNode by one pointer from 40 to 32 bytes (on x86_64). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1f347b07358abbd4dce855250136a5ba40c8df3;p=clang Shrink DynTypedNode by one pointer from 40 to 32 bytes (on x86_64). The MemoizationData cache was introduced to avoid a series of enum compares at the cost of making DynTypedNode bigger. This change reverts to using an enum compare but instead of building a chain of comparison the enum values are reordered so the check can be performed with a simple greater than. The alternative would be to steal a bit from the enum but I think that's a more complex solution and not really needed here. I tried this on several large .cpp files with clang-tidy and didn't notice any performance difference. The test change is due to matchers being sorted by their node kind. Differential Revision: http://reviews.llvm.org/D13946 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@250905 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index dc3c34f28d..420c125d28 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -106,18 +106,25 @@ public: } }; + /// Check if the given ASTNodeKind identifies a type that offers pointer + /// identity. This is useful for the fast path in DynTypedNode. + bool hasPointerIdentity() const { + return KindId > NKI_LastKindWithoutPointerIdentity; + } + private: /// \brief Kind ids. /// /// Includes all possible base and derived kinds. enum NodeKindId { NKI_None, - NKI_CXXCtorInitializer, NKI_TemplateArgument, - NKI_NestedNameSpecifier, NKI_NestedNameSpecifierLoc, NKI_QualType, NKI_TypeLoc, + NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, + NKI_CXXCtorInitializer, + NKI_NestedNameSpecifier, NKI_Decl, #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, #include "clang/AST/DeclNodes.inc" @@ -238,7 +245,11 @@ public: /// Note that this is not supported by all AST nodes. For AST nodes /// that don't have a pointer-defined identity inside the AST, this /// method returns NULL. - const void *getMemoizationData() const { return MemoizationData; } + const void *getMemoizationData() const { + return NodeKind.hasPointerIdentity() + ? *reinterpret_cast(Storage.buffer) + : nullptr; + } /// \brief Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; @@ -286,18 +297,18 @@ private: template struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) - return cast(*reinterpret_cast(Storage)); + return &getUnchecked(NodeKind, Storage); return nullptr; } static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)); - return *cast(*reinterpret_cast(Storage)); + return *cast(static_cast( + *reinterpret_cast(Storage))); } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); - Result.MemoizationData = &Node; - new (Result.Storage.buffer) const BaseT * (&Node); + new (Result.Storage.buffer) const void *(&Node); return Result; } }; @@ -306,18 +317,18 @@ private: template struct PtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) - return *reinterpret_cast(Storage); + return &getUnchecked(NodeKind, Storage); return nullptr; } static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind)); - return **reinterpret_cast(Storage); + return *static_cast( + *reinterpret_cast(Storage)); } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); - Result.MemoizationData = &Node; - new (Result.Storage.buffer) const T * (&Node); + new (Result.Storage.buffer) const void *(&Node); return Result; } }; @@ -336,14 +347,12 @@ private: static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); - Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; - const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -353,12 +362,9 @@ private: /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and /// \c TemplateArguments on the other hand do not have storage or unique /// pointers and thus need to be stored by value. - typedef llvm::AlignedCharArrayUnion< - Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *> - KindsByPointer; - llvm::AlignedCharArrayUnion - Storage; + llvm::AlignedCharArrayUnion Storage; }; template diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index ca1dfefd53..66960a0bb2 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -455,8 +455,8 @@ TEST_F(RegistryTest, Completion) { // Polymorphic. EXPECT_TRUE(hasCompletion( Comps, "hasDescendant(", - "Matcher " - "hasDescendant(Matcher" + " hasDescendant(Matcher)")); CompVector WhileComps = getCompletions("whileStmt", 0);