[libcxx-commits] [libcxx] [libc++] Optimize multi{map, set}::insert(InputIterator, InputIterator) (PR #152691)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 14 02:26:04 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/152691
>From 9b9dbdaa37ee23f9f6eb5847e5f284f4ceddfc0b Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 8 Aug 2025 12:12:52 +0200
Subject: [PATCH] [libc++] Optimize multi{map,set}::insert
---
libcxx/include/__tree | 29 +++++++++++++++++++++++++++++
libcxx/include/map | 9 +++------
libcxx/include/set | 11 ++++-------
3 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 6dadd0915c984..5bee65b4392df 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -970,6 +970,35 @@ public:
__emplace_hint_multi(__p, std::move(__value));
}
+ template <class _InIter, class _Sent>
+ _LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) {
+ if (__first == __last)
+ return;
+
+ if (__root() == nullptr) { // Make sure we always have a root node
+ __node_holder __node = __construct_node(*__first);
+ __insert_node_at(__end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__node.release()));
+ ++__first;
+ }
+
+ auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root())));
+
+ for (; __first != __last; ++__first) {
+ __node_holder __node = __construct_node(*__first);
+ // Always check the max node first. This optimizes for sorted ranges inserted at the end.
+ if (!value_comp()(__node->__get_value(), __max_node->__get_value())) { // __node >= __max_val
+ __insert_node_at(static_cast<__end_node_pointer>(__max_node),
+ __max_node->__right_,
+ static_cast<__node_base_pointer>(__node.get()));
+ __max_node = __node.release();
+ } else {
+ __end_node_pointer __parent;
+ __node_base_pointer& __child = __find_leaf_high(__parent, __node->__value_);
+ __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__node.release()));
+ }
+ }
+ }
+
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_assign_unique(const value_type& __v, __node_pointer __dest);
_LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
diff --git a/libcxx/include/map b/libcxx/include/map
index 9f98abef9afe0..d8ff14b078f6d 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -593,6 +593,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
# include <__memory/unique_ptr.h>
# include <__memory_resource/polymorphic_allocator.h>
# include <__node_handle>
+# include <__ranges/access.h>
# include <__ranges/concepts.h>
# include <__ranges/container_compatible_range.h>
# include <__ranges/from_range.h>
@@ -1749,17 +1750,13 @@ public:
template <class _InputIterator>
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) {
- for (const_iterator __e = cend(); __f != __l; ++__f)
- __tree_.__emplace_hint_multi(__e.__i_, *__f);
+ __tree_.__insert_range_multi(__f, __l);
}
# if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<value_type> _Range>
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
- const_iterator __end = cend();
- for (auto&& __element : __range) {
- __tree_.__emplace_hint_multi(__end.__i_, std::forward<decltype(__element)>(__element));
- }
+ __tree_.__insert_range_multi(ranges::begin(__range), ranges::end(__range));
}
# endif
diff --git a/libcxx/include/set b/libcxx/include/set
index c77345bc5dc1f..18488b56e7dd2 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -530,6 +530,7 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
# include <__memory/allocator_traits.h>
# include <__memory_resource/polymorphic_allocator.h>
# include <__node_handle>
+# include <__ranges/access.h>
# include <__ranges/concepts.h>
# include <__ranges/container_compatible_range.h>
# include <__ranges/from_range.h>
@@ -1205,18 +1206,14 @@ public:
}
template <class _InputIterator>
- _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) {
- for (const_iterator __e = cend(); __f != __l; ++__f)
- __tree_.__emplace_hint_multi(__e, *__f);
+ _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
+ __tree_.__insert_range_multi(__first, __last);
}
# if _LIBCPP_STD_VER >= 23
template <_ContainerCompatibleRange<value_type> _Range>
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
- const_iterator __end = cend();
- for (auto&& __element : __range) {
- __tree_.__emplace_hint_multi(__end, std::forward<decltype(__element)>(__element));
- }
+ __tree_.__insert_range_multi(ranges::begin(__range), ranges::end(__range));
}
# endif
More information about the libcxx-commits
mailing list