Skip to content

Conversation

@philnik777
Copy link
Contributor

This removes a bit of code duplication and might simplify future segmented iterator optimitations.

@github-actions
Copy link

github-actions bot commented Oct 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the introduce_for_each_segment_backward branch 2 times, most recently from 81c10c2 to 6254e5f Compare October 28, 2025 14:06
@philnik777 philnik777 force-pushed the introduce_for_each_segment_backward branch from 6254e5f to d6a492b Compare November 27, 2025 14:49
@philnik777 philnik777 force-pushed the introduce_for_each_segment_backward branch from d6a492b to ef82efb Compare December 5, 2025 08:41
@philnik777 philnik777 marked this pull request as ready for review December 10, 2025 10:50
@philnik777 philnik777 force-pushed the introduce_for_each_segment_backward branch from ef82efb to 5ec024e Compare December 10, 2025 10:50
@philnik777 philnik777 requested a review from a team as a code owner December 10, 2025 10:50
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This removes a bit of code duplication and might simplify future segmented iterator optimitations.


Full diff: https://github.com/llvm/llvm-project/pull/165160.diff

3 Files Affected:

  • (modified) libcxx/include/__algorithm/copy_backward.h (+5-21)
  • (modified) libcxx/include/__algorithm/for_each_segment.h (+26)
  • (modified) libcxx/include/__algorithm/move_backward.h (+5-21)
diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h
index 6c9eba672e154..8758d2c9e7b5d 100644
--- a/libcxx/include/__algorithm/copy_backward.h
+++ b/libcxx/include/__algorithm/copy_backward.h
@@ -11,6 +11,7 @@
 
 #include <__algorithm/copy_move_common.h>
 #include <__algorithm/copy_n.h>
+#include <__algorithm/for_each_segment.h>
 #include <__algorithm/iterator_operations.h>
 #include <__algorithm/min.h>
 #include <__config>
@@ -173,27 +174,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)).second;
+    });
     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..c02436c9aa33c 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 void
+__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..43b72057a5eca 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)).second;
+    });
     return std::make_pair(__last, std::move(__result));
   }
 

@philnik777 philnik777 merged commit d15ff59 into llvm:main Dec 11, 2025
78 of 81 checks passed
@philnik777 philnik777 deleted the introduce_for_each_segment_backward branch December 11, 2025 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants