r223134 - Skip some unnecessary type checks.

Samuel Benzaquen sbenza at google.com
Tue Dec 2 10:29:00 PST 2014


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);
   }
 };
 





More information about the cfe-commits mailing list