-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc++] Optimize {set,map}::{lower,upper}_bound #161366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesApple M4:
Full diff: https://github.com/llvm/llvm-project/pull/161366.diff 3 Files Affected:
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 61c910c52c536..ef53bf1fa8364 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1165,6 +1165,48 @@ public:
template <class _Key>
_LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const;
+ template <bool _LowerBound, class _Key>
+ _LIBCPP_HIDE_FROM_ABI __end_node_pointer __lower_upper_bound_unique_impl(const _Key& __v) const {
+ auto __rt = __root();
+ auto __result = __end_node();
+ auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp());
+ while (__rt != nullptr) {
+ auto __comp_res = __comp(__v, __rt->__get_value());
+
+ if (__comp_res.__less()) {
+ __result = static_cast<__end_node_pointer>(__rt);
+ __rt = static_cast<__node_pointer>(__rt->__left_);
+ } else if (__comp_res.__greater()) {
+ __rt = static_cast<__node_pointer>(__rt->__right_);
+ } else if _LIBCPP_CONSTEXPR (_LowerBound) {
+ return static_cast<__end_node_pointer>(__rt);
+ } else {
+ return __rt->__right_ ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result;
+ }
+ }
+ return __result;
+ }
+
+ template <class _Key>
+ _LIBCPP_HIDE_FROM_ABI iterator __lower_bound_unique(const _Key& __v) {
+ return iterator(__lower_upper_bound_unique_impl<true>(__v));
+ }
+
+ template <class _Key>
+ _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_unique(const _Key& __v) const {
+ return const_iterator(__lower_upper_bound_unique_impl<true>(__v));
+ }
+
+ template <class _Key>
+ _LIBCPP_HIDE_FROM_ABI iterator __upper_bound_unique(const _Key& __v) {
+ return iterator(__lower_upper_bound_unique_impl<false>(__v));
+ }
+
+ template <class _Key>
+ _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_unique(const _Key& __v) const {
+ return iterator(__lower_upper_bound_unique_impl<false>(__v));
+ }
+
template <class _Key>
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Key& __v) {
return __lower_bound(__v, __root(), __end_node());
diff --git a/libcxx/include/map b/libcxx/include/map
index a63dfec910aae..58840556d42f5 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -1269,7 +1269,9 @@ public:
# endif // _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
- _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
+ _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
+ return __tree_.__lower_bound_unique(__k);
+ }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
@@ -1282,8 +1284,10 @@ public:
}
# endif
- _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
- _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
+ _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
+ _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
+ return __tree_.__upper_bound_unique(__k);
+ }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
diff --git a/libcxx/include/set b/libcxx/include/set
index 75529e7bac6ff..f77dc4821e997 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -849,8 +849,10 @@ public:
}
# endif // _LIBCPP_STD_VER >= 20
- _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
- _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
+ _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); }
+ _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
+ return __tree_.__lower_bound_unique(__k);
+ }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
@@ -863,8 +865,10 @@ public:
}
# endif
- _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
- _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
+ _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
+ _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
+ return __tree_.__upper_bound_unique(__k);
+ }
# if _LIBCPP_STD_VER >= 14
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
|
98737ea
to
bf8685a
Compare
bf8685a
to
4e6971e
Compare
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions -- libcxx/include/__tree libcxx/include/map libcxx/include/set
View the diff from clang-format here.diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index b176e1abd..d7d074a00 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -2163,8 +2163,8 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const {
template <class _Tp, class _Compare, class _Allocator>
template <class _Key>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__lower_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
+typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound_multi(
+ const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
while (__root != nullptr) {
if (!value_comp()(__root->__get_value(), __v)) {
__result = static_cast<__end_node_pointer>(__root);
@@ -2191,8 +2191,8 @@ typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare,
template <class _Tp, class _Compare, class _Allocator>
template <class _Key>
-typename __tree<_Tp, _Compare, _Allocator>::iterator
-__tree<_Tp, _Compare, _Allocator>::__upper_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
+typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound_multi(
+ const _Key& __v, __node_pointer __root, __end_node_pointer __result) {
while (__root != nullptr) {
if (value_comp()(__v, __root->__get_value())) {
__result = static_cast<__end_node_pointer>(__root);
@@ -2281,8 +2281,9 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) {
} else if (__comp_res.__greater())
__rt = static_cast<__node_pointer>(__rt->__right_);
else
- return _Pp(__lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)),
- __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result));
+ return _Pp(
+ __lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)),
+ __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result));
}
return _Pp(iterator(__result), iterator(__result));
}
@@ -2304,8 +2305,9 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const {
} else if (__comp_res.__greater())
__rt = static_cast<__node_pointer>(__rt->__right_);
else
- return _Pp(__lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)),
- __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result));
+ return _Pp(
+ __lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)),
+ __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result));
}
return _Pp(const_iterator(__result), const_iterator(__result));
}
|
Apple M4: