https://github.com/AnonMiraj created https://github.com/llvm/llvm-project/pull/218278
While looking for memory regressions, I found that #118288 caused [CTRE](https://github.com/hanickadot/compile-time-regular-expressions) to regress by ~9.5% in peak memory (+758 MB). The fix is simple: use a reference to the FoldingSetNodeID in the map. | | Max RSS | | --- | --- | | trunk | 8928 MB | | this PR | **8347 MB (−6.5%)** | [compile-time-tracker]( https://llvm-compile-time-tracker.com/compare.php?from=49de424f45389cb757c3cc8c50daf38d024e2314&to=0cf6a242f9b5a211f9dffd6b8f52aeeb3e91e508&stat=instructions) >From 0cf6a242f9b5a211f9dffd6b8f52aeeb3e91e508 Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Sun, 23 Aug 2026 03:17:25 +0300 Subject: [PATCH] [clang] Shrink AutoTypes map key to reduce peak memory --- clang/include/clang/AST/ASTContext.h | 32 +++++++++++++++++++++++++++- clang/lib/AST/ASTContext.cpp | 4 ++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4ed852d36442..ee591087a44e4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -284,7 +284,9 @@ class ASTContext : public RefCountedBase<ASTContext> { // arguments. Since both dependent and dependency are on the same set, // we can end up in an infinite recursion when looking for a node if we used // a `FoldingSet`, since both could end up in the same bucket. - mutable llvm::DenseMap<llvm::FoldingSetNodeID, AutoType *> AutoTypes; + // Keyed by an interned FoldingSetNodeIDRef rather than a FoldingSetNodeID to + // avoid its large inline SmallVector in every bucket. + mutable llvm::DenseMap<llvm::FoldingSetNodeIDRef, AutoType *> AutoTypes; mutable llvm::FoldingSet<DeducedTemplateSpecializationType> DeducedTemplateSpecializationTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; @@ -4014,5 +4016,33 @@ template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> { return LHS == RHS; } }; +// The empty/tombstone keys have a null Data, which no interned ref has, so +// isEqual guards against comparing through their null pointer. +template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeIDRef> { + static FoldingSetNodeIDRef getEmptyKey() { + return FoldingSetNodeIDRef(nullptr, 0); + } + static FoldingSetNodeIDRef getTombstoneKey() { + return FoldingSetNodeIDRef(nullptr, 1); + } + static unsigned getHashValue(FoldingSetNodeIDRef Val) { + return Val.ComputeHash(); + } + static bool isEqual(FoldingSetNodeIDRef LHS, FoldingSetNodeIDRef RHS) { + if (LHS.getData() == RHS.getData() && LHS.getSize() == RHS.getSize()) + return true; + if (!LHS.getData() || !RHS.getData()) + return false; + return LHS == RHS; + } + static unsigned getHashValue(const FoldingSetNodeID &Val) { + return Val.ComputeHash(); + } + static bool isEqual(const FoldingSetNodeID &LHS, FoldingSetNodeIDRef RHS) { + if (!RHS.getData()) + return false; + return LHS == RHS; + } +}; #endif // LLVM_CLANG_AST_ASTCONTEXT_H diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index abf0cd5e18c2b..197402b5f0f05 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6885,7 +6885,7 @@ ASTContext::getAutoType(DeducedKind DK, QualType DeducedAsType, llvm::FoldingSetNodeID ID; AutoType::Profile(ID, *this, DK, DeducedAsType, Keyword, TypeConstraintConcept, TypeConstraintArgs); - if (auto const AT_iter = AutoTypes.find(ID); AT_iter != AutoTypes.end()) + if (auto const AT_iter = AutoTypes.find_as(ID); AT_iter != AutoTypes.end()) return QualType(AT_iter->getSecond(), 0); if (DK == DeducedKind::Deduced) { @@ -6915,7 +6915,7 @@ ASTContext::getAutoType(DeducedKind DK, QualType DeducedAsType, assert(InsertedID == ID && "ID does not match"); #endif Types.push_back(AT); - AutoTypes.try_emplace(ID, AT); + AutoTypes.try_emplace(ID.Intern(BumpAlloc), AT); return QualType(AT, 0); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
