Author: sbenza Date: Tue Dec 2 12:29:00 2014 New Revision: 223134 URL: http://llvm.org/viewvc/llvm-project?rev=223134&view=rev Log: 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<T>::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 Modified: cfe/trunk/include/clang/AST/ASTTypeTraits.h cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Modified: cfe/trunk/include/clang/AST/ASTTypeTraits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTTypeTraits.h?rev=223134&r1=223133&r2=223134&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTTypeTraits.h (original) +++ cfe/trunk/include/clang/AST/ASTTypeTraits.h Tue Dec 2 12:29:00 2014 @@ -145,6 +145,8 @@ private: template <class T> struct KindToKindId { static const NodeKindId Id = NKI_None; }; + template <class T> + struct KindToKindId<const T> : KindToKindId<T> {}; /// \brief Per kind info. struct KindInfo { @@ -221,6 +223,14 @@ public: return BaseConverter<T>::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 <typename T> + const T &getUnchecked() const { + return BaseConverter<T>::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<QualType>().isBaseOf(NodeKind)) { - return *get<QualType>() == *Other.get<QualType>(); - } + if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) + return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -274,10 +285,14 @@ private: /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. template <typename T, typename BaseT> struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) - return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) + return cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); + return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); @@ -294,6 +309,10 @@ private: return *reinterpret_cast<T *const *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return **reinterpret_cast<T *const *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); @@ -310,6 +329,10 @@ private: return reinterpret_cast<const T *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return *reinterpret_cast<const T *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=223134&r1=223133&r2=223134&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Tue Dec 2 12:29:00 2014 @@ -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<T>()) { - return matches(*Node, Finder, Builder); - } - return false; + return matches(DynNode.getUnchecked<T>(), Finder, Builder); } }; _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
