[libcxx-commits] [libcxx] [libcxx] Optimize std::generate for segmented iterators (PR #163006)

Connector Switch via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 15 08:02:21 PDT 2025


https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/163006

>From 962695a02114a3355b5a31727936008d866f53f8 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sat, 11 Oct 2025 23:22:15 +0800
Subject: [PATCH 1/6] [libcxx] Optimize std::generate for segmented iterators

---
 libcxx/include/__algorithm/generate.h         | 27 +++++++++++++++++--
 .../alg.generate/generate.pass.cpp            | 11 ++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index c95b527402f5d..91e2ada7daf77 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -9,7 +9,10 @@
 #ifndef _LIBCPP___ALGORITHM_GENERATE_H
 #define _LIBCPP___ALGORITHM_GENERATE_H
 
+#include <__algorithm/for_each_segment.h>
 #include <__config>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/enable_if.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -17,13 +20,33 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _ForwardIterator, class _Generator>
+template <class _ForwardIterator, class _Sent, class _Generator>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
+__generate(_ForwardIterator __first, _Sent __last, _Generator __gen) {
   for (; __first != __last; ++__first)
     *__first = __gen();
 }
 
+#ifndef _LIBCPP_CXX03_LANG
+template <class _SegmentedIterator,
+          class _Generator,
+          __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+_SegmentedIterator __generate(_SegmentedIterator __first, _SegmentedIterator __last, _Generator& __gen) {
+  using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
+  std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
+    std::__generate(__lfirst, __llast, __gen);
+  });
+  return __last;
+}
+#endif // !_LIBCPP_CXX03_LANG
+
+template <class _ForwardIterator, class _Generator>
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
+  std::__generate(__first, __last, __gen);
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___ALGORITHM_GENERATE_H
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp
index 29d32d7156742..4591d7ece4645 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.generate/generate.pass.cpp
@@ -16,6 +16,7 @@
 
 #include <algorithm>
 #include <cassert>
+#include <deque>
 
 #include "test_macros.h"
 #include "test_iterators.h"
@@ -51,12 +52,22 @@ test()
     assert(ia[3] == 1);
 }
 
+void deque_test() {
+  int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
+  for (const int size : sizes) {
+    std::deque<int> d(size);
+    std::generate(d.begin(), d.end(), gen_test());
+    assert(std::all_of(d.begin(), d.end(), [](int x) { return x == 1; }));
+  }
+}
+
 int main(int, char**)
 {
     test<forward_iterator<int*> >();
     test<bidirectional_iterator<int*> >();
     test<random_access_iterator<int*> >();
     test<int*>();
+    deque_test();
 
 #if TEST_STD_VER > 17
     static_assert(test_constexpr());

>From 2f00429ee9d178e6a27cf94fbafb213a735b752b Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sat, 11 Oct 2025 23:56:28 +0800
Subject: [PATCH 2/6] fix copy ci

---
 .../algorithms/robust_against_copying_comparators.pass.cpp     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
index 256251686bb3e..7a3b17b8a6246 100644
--- a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
@@ -149,7 +149,8 @@ TEST_CONSTEXPR_CXX20 bool all_the_algorithms() {
   assert(copies == 0);
 #endif
   (void)std::generate(first, last, NullaryValue<T>(&copies));
-  assert(copies == 0);
+  assert(copies == 1);
+  copies = 0;
   (void)std::generate_n(first, count, NullaryValue<T>(&copies));
   assert(copies == 0);
   (void)std::includes(first, last, first2, last2, Less<T>(&copies));

>From 252611080c81a2e0d5489b80f48176e10b7ac62d Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 12 Oct 2025 00:00:44 +0800
Subject: [PATCH 3/6] fix missing &

---
 libcxx/include/__algorithm/generate.h                          | 2 +-
 .../algorithms/robust_against_copying_comparators.pass.cpp     | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index 91e2ada7daf77..188f10111d454 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _ForwardIterator, class _Sent, class _Generator>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__generate(_ForwardIterator __first, _Sent __last, _Generator __gen) {
+__generate(_ForwardIterator __first, _Sent __last, _Generator& __gen) {
   for (; __first != __last; ++__first)
     *__first = __gen();
 }
diff --git a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
index 7a3b17b8a6246..256251686bb3e 100644
--- a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp
@@ -149,8 +149,7 @@ TEST_CONSTEXPR_CXX20 bool all_the_algorithms() {
   assert(copies == 0);
 #endif
   (void)std::generate(first, last, NullaryValue<T>(&copies));
-  assert(copies == 1);
-  copies = 0;
+  assert(copies == 0);
   (void)std::generate_n(first, count, NullaryValue<T>(&copies));
   assert(copies == 0);
   (void)std::includes(first, last, first2, last2, Less<T>(&copies));

>From 4589580d9b0a7bb7b9906394e5e5e5b5b7b0eb4e Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 13 Oct 2025 23:14:54 +0800
Subject: [PATCH 4/6] forward std::generate to std::for_each

---
 libcxx/include/__algorithm/generate.h | 32 +++++----------------------
 1 file changed, 5 insertions(+), 27 deletions(-)

diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index 188f10111d454..87483d45e7482 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -9,10 +9,9 @@
 #ifndef _LIBCPP___ALGORITHM_GENERATE_H
 #define _LIBCPP___ALGORITHM_GENERATE_H
 
-#include <__algorithm/for_each_segment.h>
+#include <__algorithm/for_each.h>
 #include <__config>
-#include <__iterator/segmented_iterator.h>
-#include <__type_traits/enable_if.h>
+
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -20,31 +19,10 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _ForwardIterator, class _Sent, class _Generator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-__generate(_ForwardIterator __first, _Sent __last, _Generator& __gen) {
-  for (; __first != __last; ++__first)
-    *__first = __gen();
-}
-
-#ifndef _LIBCPP_CXX03_LANG
-template <class _SegmentedIterator,
-          class _Generator,
-          __enable_if_t<__is_segmented_iterator_v<_SegmentedIterator>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-_SegmentedIterator __generate(_SegmentedIterator __first, _SegmentedIterator __last, _Generator& __gen) {
-  using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
-  std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
-    std::__generate(__lfirst, __llast, __gen);
-  });
-  return __last;
-}
-#endif // !_LIBCPP_CXX03_LANG
-
 template <class _ForwardIterator, class _Generator>
-inline _LIBCPP_HIDE_FROM_ABI
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
-  std::__generate(__first, __last, __gen);
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
+  std::for_each(__first, __last, [&](auto& __element) { __element = __gen(); });
 }
 
 _LIBCPP_END_NAMESPACE_STD

>From bb58a986d2ee0373caf144f914af9c453f8fcc4e Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Mon, 13 Oct 2025 23:17:14 +0800
Subject: [PATCH 5/6] forward std::generate to std::for_each

---
 libcxx/include/__algorithm/generate.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index 87483d45e7482..18af2a1b85434 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -12,7 +12,6 @@
 #include <__algorithm/for_each.h>
 #include <__config>
 
-
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif

>From f1e883ff9bbb2fbc4c8187dd4a12cac10466fa72 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 15 Oct 2025 22:54:07 +0800
Subject: [PATCH 6/6] use std::forward

---
 libcxx/docs/ReleaseNotes/22.rst       | 2 ++
 libcxx/include/__algorithm/generate.h | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index ec23ba9d1e3a1..5ca106125fb22 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -67,6 +67,8 @@ Improvements and New Features
   reduced debug information.
 
 - The performance of ``std::find`` has been improved by up to 2x for integral types
+- The ``std::generate`` algorithm has been optimized for segmented iterators, resulting in a performance improvement for
+  ``std::deque<short>`` and ``std::join_view<vector<vector<short>>>`` iterators.
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index 18af2a1b85434..8f27dbeef4667 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -11,6 +11,7 @@
 
 #include <__algorithm/for_each.h>
 #include <__config>
+#include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -21,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _ForwardIterator, class _Generator>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
 generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen) {
-  std::for_each(__first, __last, [&](auto& __element) { __element = __gen(); });
+  std::for_each(__first, __last, [&](auto&& __element) { std::forward<decltype(__element)>(__element) = __gen(); });
 }
 
 _LIBCPP_END_NAMESPACE_STD



More information about the libcxx-commits mailing list