[llvm] [ADT] ImutAVLFactory: avoid overhead of vector for freelist (PR #196534)

Christoph Cullmann via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 19 09:33:57 PDT 2026


https://github.com/christoph-cullmann updated https://github.com/llvm/llvm-project/pull/196534

>From da3cae7993c481455b8bfc606dee9aaf514b217c Mon Sep 17 00:00:00 2001
From: Christoph Cullmann <cullmann at kde.org>
Date: Fri, 8 May 2026 15:45:36 +0200
Subject: [PATCH 1/2] [ADT] ImutAVLFactory: avoid overhead of vector for
 freelist

we can use the next pointer of the TreeTy to have a zero overhead
freelist of all free nodes

avoids allocations in the destruction phase
---
 llvm/include/llvm/ADT/ImmutableSet.h | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/llvm/include/llvm/ADT/ImmutableSet.h b/llvm/include/llvm/ADT/ImmutableSet.h
index b9c3e68e51365..ffff28e56d6f7 100644
--- a/llvm/include/llvm/ADT/ImmutableSet.h
+++ b/llvm/include/llvm/ADT/ImmutableSet.h
@@ -29,7 +29,6 @@
 #include <functional>
 #include <iterator>
 #include <new>
-#include <vector>
 
 namespace llvm {
 
@@ -342,7 +341,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;
   }
 };
 
@@ -367,8 +367,10 @@ class ImutAVLFactory {
 
   CacheTy Cache;
   uintptr_t Allocator;
-  std::vector<TreeTy*> createdNodes;
-  std::vector<TreeTy*> freeNodes;
+  SmallVector<TreeTy *, 0> createdNodes;
+
+  // We use next inside the TreeTy to build a single-linked freelist.
+  TreeTy *freeNodes = nullptr;
 
   bool ownsAllocator() const {
     return (Allocator & 0x1) == 0;
@@ -454,15 +456,15 @@ 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();
+    TreeTy *T = freeNodes;
+    if (T) {
+      freeNodes = T->next;
+      T->next = nullptr;
       assert(T != L);
       assert(T != R);
     } else {
-      T = (TreeTy*) A.Allocate<TreeTy>();
+      BumpPtrAllocator &A = getAllocator();
+      T = (TreeTy *)A.Allocate<TreeTy>();
     }
     new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
     createdNodes.push_back(T);

>From 567729c9037ff9c39683aa66fbc20c4f30ade234 Mon Sep 17 00:00:00 2001
From: Christoph Cullmann <christoph at cullmann.dev>
Date: Sun, 19 Jul 2026 18:33:44 +0200
Subject: [PATCH 2/2] adjust to rename of next to Next

---
 llvm/include/llvm/ADT/ImmutableSet.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ADT/ImmutableSet.h b/llvm/include/llvm/ADT/ImmutableSet.h
index e13072d5290ed..52bd4dd97317a 100644
--- a/llvm/include/llvm/ADT/ImmutableSet.h
+++ b/llvm/include/llvm/ADT/ImmutableSet.h
@@ -378,7 +378,7 @@ 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;
-    next = factory->freeNodes;
+    this->Next = factory->freeNodes;
     factory->freeNodes = this;
   }
 };
@@ -486,8 +486,8 @@ class ImutAVLFactory
   TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
     TreeTy *T = freeNodes;
     if (T) {
-      freeNodes = T->next;
-      T->next = nullptr;
+      freeNodes = T->Next;
+      T->Next = nullptr;
       assert(T != L);
       assert(T != R);
     } else {



More information about the llvm-commits mailing list