Author: Nico Weber
Date: 2026-10-05T14:54:44Z
New Revision: b369deb095d967222edc58c3af3afc8e75845ba2

URL: 
https://github.com/llvm/llvm-project/commit/b369deb095d967222edc58c3af3afc8e75845ba2
DIFF: 
https://github.com/llvm/llvm-project/commit/b369deb095d967222edc58c3af3afc8e75845ba2.diff

LOG: [ASTMatchers] Reduce per-matcher, per-node traversal kind overhead 
(#228960)

- Give traverseIgnored() a fast path and inline it
- Construct ParentMapContext eagerly and inline its accessor
- Only check if the node is ignored in matchWithFilter() for expressions

clang-tidy with LLVM's .clang-tidy config on five LLVM files (clang's
ASTContext.cpp, CGExpr.cpp, ParseDecl.cpp, SemaOverload.cpp, and
LoopVectorize.cpp), sum of two runs each:

    instructions: 436.4e9 => 405.8e9, -7.0%
    user time: 32.2 s => 30.2 s, -6.2%

No behavior change.

Added: 
    

Modified: 
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/ParentMapContext.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/ParentMapContext.cpp
    clang/lib/ASTMatchers/ASTMatchFinder.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 9d9978e79be51..b04b633561661 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -873,7 +873,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
   };
 
   /// Returns the dynamic AST node parent map context.
-  ParentMapContext &getParentMapContext();
+  ParentMapContext &getParentMapContext() { return *ParentMapCtx; }
 
   // A traversal scope limits the parts of the AST visible to certain analyses.
   // RecursiveASTVisitor only visits specified children of TranslationUnitDecl.

diff  --git a/clang/include/clang/AST/ParentMapContext.h 
b/clang/include/clang/AST/ParentMapContext.h
index 6f79038627d9e..2141b8b973992 100644
--- a/clang/include/clang/AST/ParentMapContext.h
+++ b/clang/include/clang/AST/ParentMapContext.h
@@ -62,7 +62,14 @@ class ParentMapContext {
 
   const Expr *traverseIgnored(const Expr *E) const;
   Expr *traverseIgnored(Expr *E) const;
-  DynTypedNode traverseIgnored(const DynTypedNode &N) const;
+  DynTypedNode traverseIgnored(const DynTypedNode &N) const {
+    // Fast path: Nothing is ignored in the default traversal mode TK_AsIs.
+    if (Traversal == TK_AsIs)
+      return N;
+    if (const auto *E = N.get<Expr>())
+      return DynTypedNode::create(*traverseIgnored(E));
+    return N;
+  }
 
   class ParentMap;
 

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 851c91e076990..e925a1f44795b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -907,12 +907,6 @@ interp::Context &ASTContext::getInterpContext() const {
   return *InterpContext;
 }
 
-ParentMapContext &ASTContext::getParentMapContext() {
-  if (!ParentMapCtx)
-    ParentMapCtx.reset(new ParentMapContext(*this));
-  return *ParentMapCtx;
-}
-
 static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI,
                                           const LangOptions &LangOpts) {
   switch (LangOpts.getAddressSpaceMapMangling()) {
@@ -946,9 +940,10 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager 
&SM,
                                         LangOpts.XRayNeverInstrumentFiles,
                                         LangOpts.XRayAttrListFiles, SM)),
       ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)),
-      PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
-      BuiltinInfo(builtins), TUKind(TUKind), DeclarationNames(*this),
-      Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
+      PrintingPolicy(LOpts), ParentMapCtx(new ParentMapContext(*this)),
+      Idents(idents), Selectors(sels), BuiltinInfo(builtins), TUKind(TUKind),
+      DeclarationNames(*this), Comments(SM),
+      CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
       CompCategories(this_()), LastSDM(nullptr, 0) {
   addTranslationUnitDecl();
 }

diff  --git a/clang/lib/AST/ParentMapContext.cpp 
b/clang/lib/AST/ParentMapContext.cpp
index 7138dffb46e19..7607cf27bfe60 100644
--- a/clang/lib/AST/ParentMapContext.cpp
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -327,13 +327,6 @@ Expr *ParentMapContext::traverseIgnored(Expr *E) const {
   llvm_unreachable("Invalid Traversal type!");
 }
 
-DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const {
-  if (const auto *E = N.get<Expr>()) {
-    return DynTypedNode::create(*traverseIgnored(E));
-  }
-  return N;
-}
-
 /// Template specializations to abstract away from pointers and TypeLocs.
 /// @{
 template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {

diff  --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp 
b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index d2c024abfe02e..9395b79a7622a 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1049,13 +1049,15 @@ class MatchASTVisitor : public 
RecursiveASTVisitor<MatchASTVisitor>,
     const bool EnableCheckProfiling = Options.CheckProfiling.has_value();
     TimeBucketRegion Timer;
     auto &Matchers = this->Matchers->DeclOrStmt;
+    // traverseIgnored() only ever replaces expressions.
+    const bool IsExpr = DynNode.get<Expr>() != nullptr;
     for (unsigned short I : Filter) {
       auto &MP = Matchers[I];
       if (EnableCheckProfiling)
         Timer.setBucket(&TimeByBucket[MP.second->getID()]);
       BoundNodesTreeBuilder Builder;
 
-      {
+      if (IsExpr) {
         TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind());
         if (getASTContext().getParentMapContext().traverseIgnored(DynNode) !=
             DynNode)


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to