r219792 - Speed up hasName() matcher.

Samuel Benzaquen sbenza at google.com
Thu Oct 16 07:54:47 PDT 2014


Sent http://reviews.llvm.org/D5826 as a follow change.

On Thu, Oct 16, 2014 at 4:13 AM, Alexander Kornienko <alexfh at google.com>
wrote:

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


More information about the cfe-commits mailing list