[libcxx-commits] [libcxx] [libc++] Merge the segmented iterator code for {copy, move}_backward (PR #165160)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Oct 26 09:02:36 PDT 2025
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/165160
This removes a bit of code duplication and might simplify future segmented iterator optimitations.
>From ae7d2eb6038cb69e3f1a279c8f0a85d266e36dbe Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 26 Oct 2025 17:00:09 +0100
Subject: [PATCH] [libc++] Merge the segmented iterator code for
{copy,move}_backward
---
libcxx/include/__algorithm/copy_backward.h | 25 +++---------------
libcxx/include/__algorithm/for_each_segment.h | 26 +++++++++++++++++++
libcxx/include/__algorithm/move_backward.h | 26 ++++---------------
3 files changed, 35 insertions(+), 42 deletions(-)
diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h
index 6c9eba672e154..7ca60814c41ab 100644
--- a/libcxx/include/__algorithm/copy_backward.h
+++ b/libcxx/include/__algorithm/copy_backward.h
@@ -173,27 +173,10 @@ struct __copy_backward_impl {
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const {
- using _Traits = __segmented_iterator_traits<_InIter>;
- auto __sfirst = _Traits::__segment(__first);
- auto __slast = _Traits::__segment(__last);
- if (__sfirst == __slast) {
- auto __iters =
- std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
- return std::make_pair(__last, __iters.second);
- }
-
- __result =
- std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
- .second;
- --__slast;
- while (__sfirst != __slast) {
- __result =
- std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
- .second;
- --__slast;
- }
- __result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
- .second;
+ using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
+ std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
+ __result = std::__copy_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result));
+ });
return std::make_pair(__last, std::move(__result));
}
diff --git a/libcxx/include/__algorithm/for_each_segment.h b/libcxx/include/__algorithm/for_each_segment.h
index 93aa8259b2f7f..de0ed243d7acc 100644
--- a/libcxx/include/__algorithm/for_each_segment.h
+++ b/libcxx/include/__algorithm/for_each_segment.h
@@ -48,6 +48,32 @@ __for_each_segment(_SegmentedIterator __first, _SegmentedIterator __last, _Funct
__func(_Traits::__begin(__sfirst), _Traits::__local(__last));
}
+template <class _SegmentedIterator, class _Functor>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
+__for_each_segment_backward(_SegmentedIterator __first, _SegmentedIterator __last, _Functor __func) {
+ using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
+
+ auto __sfirst = _Traits::__segment(__first);
+ auto __slast = _Traits::__segment(__last);
+
+ // We are in a single segment, so we might not be at the beginning or end
+ if (__sfirst == __slast) {
+ __func(_Traits::__local(__first), _Traits::__local(__last));
+ return;
+ }
+
+ // We have more than one segment. Iterate over the last segment, since we might not start at the end
+ __func(_Traits::__begin(__slast), _Traits::__local(__last));
+ --__slast;
+ // iterate over the segments which are guaranteed to be completely in the range
+ while (__sfirst != __slast) {
+ __func(_Traits::__begin(__slast), _Traits::__end(__slast));
+ --__slast;
+ }
+ // iterate over the first segment
+ __func(_Traits::__local(__first), _Traits::__end(__slast));
+}
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H
diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h
index a4698327b474d..d7bc88975ce93 100644
--- a/libcxx/include/__algorithm/move_backward.h
+++ b/libcxx/include/__algorithm/move_backward.h
@@ -11,6 +11,7 @@
#include <__algorithm/copy_backward.h>
#include <__algorithm/copy_move_common.h>
+#include <__algorithm/for_each_segment.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__config>
@@ -54,27 +55,10 @@ struct __move_backward_impl {
template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator_v<_InIter>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
operator()(_InIter __first, _InIter __last, _OutIter __result) const {
- using _Traits = __segmented_iterator_traits<_InIter>;
- auto __sfirst = _Traits::__segment(__first);
- auto __slast = _Traits::__segment(__last);
- if (__sfirst == __slast) {
- auto __iters =
- std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
- return std::make_pair(__last, __iters.second);
- }
-
- __result =
- std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
- .second;
- --__slast;
- while (__sfirst != __slast) {
- __result =
- std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
- .second;
- --__slast;
- }
- __result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
- .second;
+ using __local_iterator = typename __segmented_iterator_traits<_InIter>::__local_iterator;
+ std::__for_each_segment_backward(__first, __last, [&__result](__local_iterator __lfirst, __local_iterator __llast) {
+ __result = std::__move_backward<_AlgPolicy>(std::move(__lfirst), std::move(__llast), std::move(__result));
+ });
return std::make_pair(__last, std::move(__result));
}
More information about the libcxx-commits
mailing list