From b6f0a83f417e857c27be13d625e9f205feab777d Mon Sep 17 00:00:00 2001 From: Samuel Benzaquen Date: Tue, 2 Dec 2014 18:29:00 +0000 Subject: [PATCH] Skip some unnecessary type checks. Summary: Skip some unnecessary type checks wrt DynTypedNodes. Add DynTypedNode::getUnchecked() to skip the runtime check when the type is known. Speed up DynTypedNode::operator== by using isSame() instead of isBaseOf(). Skip the type check in MatcherInterface::matches(). All calls come from DynTypedMatcher::matches(), which already did the type check. This change speeds up our clang-tidy benchmark by ~4%. Reviewers: klimek Subscribers: klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D6468 llvm-svn: 223134 --- clang/include/clang/AST/ASTTypeTraits.h | 37 +++++++++++++++---- .../clang/ASTMatchers/ASTMatchersInternal.h | 5 +-- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index 4fe9a3f87f53..dc3c34f28d94 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -145,6 +145,8 @@ private: template struct KindToKindId { static const NodeKindId Id = NKI_None; }; + template + struct KindToKindId : KindToKindId {}; /// \brief Per kind info. struct KindInfo { @@ -221,6 +223,14 @@ public: return BaseConverter::get(NodeKind, Storage.buffer); } + /// \brief Retrieve the stored node as type \c T. + /// + /// Similar to \c get(), but asserts that the type is what we are expecting. + template + const T &getUnchecked() const { + return BaseConverter::getUnchecked(NodeKind, Storage.buffer); + } + ASTNodeKind getNodeKind() const { return NodeKind; } /// \brief Returns a pointer that identifies the stored AST node. @@ -251,14 +261,15 @@ public: return getMemoizationData() < Other.getMemoizationData(); } bool operator==(const DynTypedNode &Other) const { - if (!NodeKind.isBaseOf(Other.NodeKind) && - !Other.NodeKind.isBaseOf(NodeKind)) + // DynTypedNode::create() stores the exact kind of the node in NodeKind. + // If they contain the same node, their NodeKind must be the same. + if (!NodeKind.isSame(Other.NodeKind)) return false; // FIXME: Implement for other types. - if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { - return *get() == *Other.get(); - } + if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) + return getUnchecked() == Other.getUnchecked(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -274,10 +285,14 @@ private: /// \brief Converter that uses dyn_cast from a stored BaseT*. template struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) - return dyn_cast(*reinterpret_cast(Storage)); + if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) + return cast(*reinterpret_cast(Storage)); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)); + return *cast(*reinterpret_cast(Storage)); + } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); @@ -294,6 +309,10 @@ private: return *reinterpret_cast(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind)); + return **reinterpret_cast(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); @@ -310,6 +329,10 @@ private: return reinterpret_cast(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind)); + return *reinterpret_cast(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 3aecf4b0e440..95e740e65b11 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -218,10 +218,7 @@ public: bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { - if (const T *Node = DynNode.get()) { - return matches(*Node, Finder, Builder); - } - return false; + return matches(DynNode.getUnchecked(), Finder, Builder); } };