<div dir="ltr">Sorry for not chiming in earlier. A few nits.<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 15, 2014 at 4:58 PM, Samuel Benzaquen <span dir="ltr"><<a href="mailto:sbenza@google.com" target="_blank">sbenza@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: sbenza<br>
Date: Wed Oct 15 09:58:46 2014<br>
New Revision: 219792<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=219792&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=219792&view=rev</a><br>
Log:<br>
Speed up hasName() matcher.<br>
<br>
Summary:<br>
Speed up hasName() matcher by skipping the expensive generation of the<br>
fully qualified name unless we need it.<br>
In the common case of matching an unqualified name, we don't need to<br>
generate the full name. We might not even need to copy any string at<br>
all.<br>
This change speeds up our clang-tidy benchmark by ~10%<br>
<br>
Reviewers: klimek<br>
<br>
Subscribers: klimek, cfe-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D5776" target="_blank">http://reviews.llvm.org/D5776</a><br>
<br>
Modified:<br>
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h<br>
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h<br>
cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp<br>
<br>
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=219792&r1=219791&r2=219792&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=219792&r1=219791&r2=219792&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)<br>
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Wed Oct 15 09:58:46 2014<br>
@@ -1591,16 +1591,8 @@ inline internal::Matcher<Stmt> sizeOfExp<br>
/// \code<br>
/// namespace a { namespace b { class X; } }<br>
/// \endcode<br>
-AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {<br>
- assert(!Name.empty());<br>
- const std::string FullNameString = "::" + Node.getQualifiedNameAsString();<br>
- const StringRef FullName = FullNameString;<br>
- const StringRef Pattern = Name;<br>
- if (Pattern.startswith("::")) {<br>
- return FullName == Pattern;<br>
- } else {<br>
- return FullName.endswith(("::" + Pattern).str());<br>
- }<br>
+inline internal::Matcher<NamedDecl> hasName(StringRef Name) {<br>
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name));<br>
}<br>
<br>
/// \brief Matches NamedDecl nodes whose fully qualified names contain<br>
<br>
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=219792&r1=219791&r2=219792&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=219792&r1=219791&r2=219792&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)<br>
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Wed Oct 15 09:58:46 2014<br>
@@ -574,6 +574,33 @@ private:<br>
std::string Name;<br>
};<br>
<br>
+/// \brief Matches named declarations with a specific name.<br>
+///<br>
+/// See \c hasName() in ASTMatchers.h for details.<br>
+class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {<br>
+ public:<br>
+ explicit HasNameMatcher(StringRef Name);<br>
+<br>
+ bool matchesNode(const NamedDecl &Node) const override;<br>
+<br>
+ private:<br>
+ /// \brief Unqualified match routine.<br>
+ ///<br>
+ /// It is much faster than the full match, but it only works for unqualified<br>
+ /// matches.<br>
+ bool matchesNodeUnqualified(const NamedDecl &Node) const;<br>
+<br>
+ /// \brief Full match routine<br>
+ ///<br>
+ /// It generates the fully qualified name of the declaration (which is<br>
+ /// expensive) before trying to match.<br>
+ /// It is slower but simple and works on all cases.<br>
+ bool matchesNodeFull(const NamedDecl &Node) const;<br>
+<br>
+ const bool UseUnqualifiedMatch;<br>
+ const std::string Name;<br>
+};<br>
+<br>
/// \brief Matches declarations for QualType and CallExpr.<br>
///<br>
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but<br>
<br>
Modified: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=219792&r1=219791&r2=219792&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=219792&r1=219791&r2=219792&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp (original)<br>
+++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp Wed Oct 15 09:58:46 2014<br>
@@ -13,6 +13,7 @@<br>
<br>
#include "clang/ASTMatchers/ASTMatchers.h"<br>
#include "clang/ASTMatchers/ASTMatchersInternal.h"<br>
+#include "llvm/ADT/SmallString.h"<br>
#include "llvm/Support/ManagedStatic.h"<br>
<br>
namespace clang {<br>
@@ -221,6 +222,51 @@ bool AnyOfVariadicOperator(const ast_typ<br>
return false;<br>
}<br>
<br>
+HasNameMatcher::HasNameMatcher(StringRef NameRef)<br>
+ : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {<br>
+ assert(!Name.empty());<br>
+}<br>
+<br>
+bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {<br>
+ assert(UseUnqualifiedMatch);<br>
+ if (Node.getIdentifier()) {<br>
+ // Simple name.<br>
+ return Name == Node.getName();<br>
+ } else if (Node.getDeclName()) {<br></blockquote><div><br></div><div><a href="http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return">http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ // Name needs to be constructed.<br>
+ llvm::SmallString<128> NodeName;<br>
+ llvm::raw_svector_ostream OS(NodeName);<br>
+ Node.printName(OS);<br>
+ return Name == OS.str();<br>
+ } else {<br></blockquote><div><br></div><div><a href="http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return">http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ return false;<br>
+ }<br>
+}<br>
+<br>
+bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {<br>
+ llvm::SmallString<128> NodeName = StringRef("::");<br>
+ llvm::raw_svector_ostream OS(NodeName);<br>
+ Node.printQualifiedName(OS);<br>
+ const StringRef FullName = OS.str();<br>
+ const StringRef Pattern = Name;<br>
+ if (Pattern.startswith("::")) {<br>
+ return FullName == Pattern;<br>
+ } else {<br></blockquote><div><br></div><div><a href="http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return">http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return</a><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ return FullName.endswith(("::" + Pattern).str());<br></blockquote><div><br></div><div>If this shows on the profile, we can also avoid creating a temporary string here:</div><div><br></div><div>return FullName.endswith(Pattern) && FullName.drop_back(Pattern.size()).endswith("::");</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ }<br>
+}<br>
+<br>
+bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {<br>
+ // FIXME: There is still room for improvement, but it would require copying a<br>
+ // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do<br>
+ // not show like that extra complexity is needed right now.<br>
+ if (UseUnqualifiedMatch) {<br>
+ assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));<br>
+ return matchesNodeUnqualified(Node);<br>
+ }<br>
+ return matchesNodeFull(Node);<br>
+}<br>
+<br>
} // end namespace internal<br>
} // end namespace ast_matchers<br>
} // end namespace clang<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>
</div></div>