[libcxx-commits] [libcxx] [libc++] Optimize __hash_table::remove(const_iterator) (PR #236713)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 29 03:23:58 PDT 2026


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/236713

None

>From 8f1351f62d3ad5b2cab307d897b39200ddb401e8 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 29 Oct 2026 11:23:27 +0100
Subject: [PATCH] [libc++] Optimize __hash_table::remove(const_iterator)

---
 libcxx/include/__hash_table | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 23916e3a3ecf32..739a0f8119fa4f 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -1962,20 +1962,32 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT {
   size_t __chash      = std::__constrain_hash(__cn->__hash(), __bc);
   // find previous node
   __next_pointer __pn = __bucket_list_[__chash];
-  for (; __pn->__next_ != __cn; __pn = __pn->__next_)
-    ;
-  // Fix up __bucket_list_
-  // if __pn is not in same bucket (before begin is not in same bucket) &&
-  //    if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
-  if (__pn == __first_node_.__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
-    if (__cn->__next_ == nullptr || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
+
+  if (__pn->__next_ == __cn) {
+    // If we're at the start of the bucket we might need to update the bucket list.
+
+    // If there are no more nodes, update the bucket to be emtpy
+    if (__cn->__next_ == nullptr)
+      __bucket_list_[__chash] = nullptr;
+
+    // If the next element is not in the same bucket, we need update the current bucket to be empty and the next bucket
+    // to the previous node.
+    else if (auto __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc); __nhash != __chash) {
       __bucket_list_[__chash] = nullptr;
-  }
-  // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
-  if (__cn->__next_ != nullptr) {
-    size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc);
-    if (__nhash != __chash)
       __bucket_list_[__nhash] = __pn;
+    }
+    // Otherwise we don't need to do anything special. Simply removing the bucket from the linked list is enough.
+  } else {
+    // The removed node is not at the start of the bucket, so we need to find it.
+    for (; __pn->__next_ != __cn; __pn = __pn->__next_)
+      ;
+
+    // If we're at the end of the bucket and point to the next bucket, we need to update the bucket list.
+    if (__cn->__next_ != nullptr) {
+      size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc);
+      if (__nhash != __chash)
+        __bucket_list_[__nhash] = __pn;
+    }
   }
   // remove __cn
   __pn->__next_ = __cn->__next_;



More information about the libcxx-commits mailing list