[llvm] Avoid overhead of std::vector for free nodes (PR #196534)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 06:49:12 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Christoph Cullmann (christoph-cullmann)

<details>
<summary>Changes</summary>

We can use the next pointer to have zero overhead freelist of all free nodes.

For large clang-tidy runs with large LiveVariables this saves xxx MB.

For this run I got 800 MB allocated on top just for the freeNodes vector during the ::destroy() call.

<img width="2348" height="1426" alt="destroy_vector_costs" src="https://github.com/user-attachments/assets/049a7971-2f48-4a20-8476-fe416d9c697f" />

I hope I did not misunderstand how the free list is meant to work.

I use the next pointer to just keep it as single linked list of free'd nodes.

---
Full diff: https://github.com/llvm/llvm-project/pull/196534.diff


1 Files Affected:

- (modified) llvm/include/llvm/ADT/ImmutableSet.h (+9-5) 


``````````diff
diff --git a/llvm/include/llvm/ADT/ImmutableSet.h b/llvm/include/llvm/ADT/ImmutableSet.h
index b9c3e68e51365..1011d17f0a6f5 100644
--- a/llvm/include/llvm/ADT/ImmutableSet.h
+++ b/llvm/include/llvm/ADT/ImmutableSet.h
@@ -342,7 +342,8 @@ class ImutAVLTree {
     // We need to clear the mutability bit in case we are
     // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
     IsMutable = false;
-    factory->freeNodes.push_back(this);
+    next = factory->freeNodes;
+    factory->freeNodes = this;
   }
 };
 
@@ -368,7 +369,9 @@ class ImutAVLFactory {
   CacheTy Cache;
   uintptr_t Allocator;
   std::vector<TreeTy*> createdNodes;
-  std::vector<TreeTy*> freeNodes;
+
+  // we use next inside the TreeTy to build a single-linked freelist
+  TreeTy* freeNodes = nullptr;
 
   bool ownsAllocator() const {
     return (Allocator & 0x1) == 0;
@@ -456,9 +459,10 @@ class ImutAVLFactory {
   TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
     BumpPtrAllocator& A = getAllocator();
     TreeTy* T;
-    if (!freeNodes.empty()) {
-      T = freeNodes.back();
-      freeNodes.pop_back();
+    if (freeNodes) {
+      T = freeNodes;
+      freeNodes = freeNodes->next;
+      T->next = nullptr;
       assert(T != L);
       assert(T != R);
     } else {

``````````

</details>


https://github.com/llvm/llvm-project/pull/196534


More information about the llvm-commits mailing list