Hi klimek,

Store the result matcher after the first call and reuse it later on.
Recreating the matchers just to use them once incurs in a lot of
unnecessary temporary memory allocations.
This change speeds up our clang-tidy benchmarks by ~2%.

http://reviews.llvm.org/D6564

Files:
  include/clang/ASTMatchers/ASTMatchers.h
  include/clang/ASTMatchers/ASTMatchersInternal.h
  include/clang/ASTMatchers/ASTMatchersMacros.h
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3159,12 +3159,10 @@
 /// \endcode
 /// functionDecl(isInstantiated())
 ///   matches 'A(int) {...};' and 'A(unsigned) {...}'.
-AST_MATCHER(Decl, isInstantiated) {
+AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
   auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
                                     functionDecl(isTemplateInstantiation())));
-  auto InnerMatcher =
-      decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
-  return InnerMatcher.matches(Node, Finder, Builder);
+  return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
 }
 
 /// \brief Matches statements inside of a template instantiation.
@@ -3181,11 +3179,10 @@
 /// unless(stmt(isInTemplateInstantiation()))
 ///   will NOT match j += 42; as it's shared between the template definition and
 ///   instantiation.
-AST_MATCHER(Stmt, isInTemplateInstantiation) {
-  auto InnerMatcher =
-      stmt(hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
-                                  functionDecl(isTemplateInstantiation())))));
-  return InnerMatcher.matches(Node, Finder, Builder);
+AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
+  return stmt(
+      hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+                             functionDecl(isTemplateInstantiation())))));
 }
 
 /// \brief Matches explicit template specializations of function, class, or
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -44,6 +44,7 @@
 #include "clang/AST/Type.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
 #include <map>
 #include <string>
 #include <vector>
@@ -1620,6 +1621,23 @@
   const Matcher<InnerTBase> InnerMatcher;
 };
 
+/// \brief A simple memoizer of T(*)() functions.
+///
+/// It will call the passed 'Func' template parameter at most once.
+/// Used to support AST_MATCHER_FUNCTION() macro.
+template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
+  struct Wrapper {
+    Wrapper() : M(Func()) {}
+    Matcher M;
+  };
+
+public:
+  static const Matcher &getInstance() {
+    static llvm::ManagedStatic<Wrapper> Instance;
+    return Instance->M;
+  }
+};
+
 // Define the create() method out of line to silence a GCC warning about
 // the struct "Func" having greater visibility than its base, which comes from
 // using the flag -fvisibility-inlines-hidden.
Index: include/clang/ASTMatchers/ASTMatchersMacros.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersMacros.h
+++ include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -37,6 +37,17 @@
 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
 
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher)                        \
+  inline ReturnType DefineMatcher##_getInstance();                             \
+  inline ReturnType DefineMatcher() {                                          \
+    return internal::MemoizedMatcher<                                          \
+        ReturnType, DefineMatcher##_getInstance>::getInstance();               \
+  }                                                                            \
+  inline ReturnType DefineMatcher##_getInstance()
+
 /// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
 /// defines a single-parameter function named DefineMatcher() that returns a
 /// ReturnType object.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to