https://github.com/higher-performance created https://github.com/llvm/llvm-project/pull/87824
Avoids the need to linearly re-scan all seen parent nodes to check for duplicates, which previously caused a slowdown for ancestry checks in Clang AST matchers. Fixes: #86881 >From 5e2b6b996a938129c087c5538155fb1b39e59ce8 Mon Sep 17 00:00:00 2001 From: higher-performance <113926381+higher-performa...@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:36:05 -0400 Subject: [PATCH] Fix quadratic slowdown in AST matcher parent map generation Avoids the need to linearly re-scan all seen parent nodes to check for duplicates, which previously caused a slowdown for ancestry checks in Clang AST matchers. Fixes https://github.com/llvm/llvm-project/issues/86881. --- clang/lib/AST/ParentMapContext.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp index 21cfd5b1de6e9d..3369df38754485 100644 --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -61,7 +61,28 @@ class ParentMapContext::ParentMap { template <typename, typename...> friend struct ::MatchParents; /// Contains parents of a node. - using ParentVector = llvm::SmallVector<DynTypedNode, 2>; + class ParentVector { + public: + ParentVector() = default; + explicit ParentVector(size_t n, const DynTypedNode &value) { + Items.reserve(n); + for (; n > 0; --n) { + push_back(value); + } + } + bool contains(const DynTypedNode &value) { + return Seen.contains(value); + } + void push_back(const DynTypedNode &value) { + if (!value.getMemoizationData() || Seen.insert(value).second) { + Items.push_back(value); + } + } + llvm::ArrayRef<DynTypedNode> view() const { return Items; } + private: + llvm::SmallVector<DynTypedNode, 2> Items; + llvm::SmallDenseSet<DynTypedNode, 2> Seen; + }; /// Maps from a node to its parents. This is used for nodes that have /// pointer identity only, which are more common and we can save space by @@ -99,7 +120,7 @@ class ParentMapContext::ParentMap { return llvm::ArrayRef<DynTypedNode>(); } if (const auto *V = I->second.template dyn_cast<ParentVector *>()) { - return llvm::ArrayRef(*V); + return V->view(); } return getSingleDynTypedNodeFromParentMap(I->second); } @@ -252,7 +273,7 @@ class ParentMapContext::ParentMap { const auto *S = It->second.dyn_cast<const Stmt *>(); if (!S) { if (auto *Vec = It->second.dyn_cast<ParentVector *>()) - return llvm::ArrayRef(*Vec); + return Vec->view(); return getSingleDynTypedNodeFromParentMap(It->second); } const auto *P = dyn_cast<Expr>(S); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits