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
