[libcxx-commits] [libcxx] 2d10684 - [libcxx] Optimize `ranges::fold_left_with_iter` for segmented iterators (#177853)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Feb 5 05:12:41 PST 2026


Author: Connector Switch
Date: 2026-02-05T21:12:36+08:00
New Revision: 2d106844e76846073cdec161c4ab2b33497719db

URL: https://github.com/llvm/llvm-project/commit/2d106844e76846073cdec161c4ab2b33497719db
DIFF: https://github.com/llvm/llvm-project/commit/2d106844e76846073cdec161c4ab2b33497719db.diff

LOG: [libcxx] Optimize `ranges::fold_left_with_iter` for segmented iterators (#177853)

Part of https://github.com/llvm/llvm-project/issues/102817.

This patch attempts to optimize the performance of
`ranges::fold_left_with_iter` for segmented iterators.

- before

```
# | rng::fold_left(vector<int>)/8             2.78 ns         2.78 ns    241953718
# | rng::fold_left(vector<int>)/32            12.2 ns         12.2 ns     57579851
# | rng::fold_left(vector<int>)/50            19.2 ns         19.2 ns     36487764
# | rng::fold_left(vector<int>)/8192          3226 ns         3226 ns       216811
# | rng::fold_left(vector<int>)/1048576     441842 ns       441839 ns         1592
# | rng::fold_left(deque<int>)/8              2.83 ns         2.83 ns    243888678
# | rng::fold_left(deque<int>)/32             16.6 ns         16.6 ns     42297458
# | rng::fold_left(deque<int>)/50             22.3 ns         22.3 ns     31387998
# | rng::fold_left(deque<int>)/8192           2492 ns         2492 ns       281637
# | rng::fold_left(deque<int>)/1048576      324936 ns       324936 ns         2154
# | rng::fold_left(list<int>)/8               2.54 ns         2.54 ns    275946635
# | rng::fold_left(list<int>)/32              16.2 ns         16.2 ns     42901634
# | rng::fold_left(list<int>)/50              54.7 ns         54.7 ns     12767450
# | rng::fold_left(list<int>)/8192           15154 ns        15154 ns        56744
# | rng::fold_left(list<int>)/1048576      4976906 ns      4976867 ns          158
```

- after

```
# | rng::fold_left(vector<int>)/8             2.74 ns         2.74 ns    255954900
# | rng::fold_left(vector<int>)/32            12.1 ns         12.1 ns     57843462
# | rng::fold_left(vector<int>)/50            19.2 ns         19.2 ns     36422594
# | rng::fold_left(vector<int>)/8192          3202 ns         3202 ns       218265
# | rng::fold_left(vector<int>)/1048576     435718 ns       435709 ns         1609
# | rng::fold_left(deque<int>)/8              2.52 ns         2.52 ns    277288254
# | rng::fold_left(deque<int>)/32             14.1 ns         14.1 ns     52244463
# | rng::fold_left(deque<int>)/50             16.2 ns         16.2 ns     43131857
# | rng::fold_left(deque<int>)/8192           1695 ns         1695 ns       415620
# | rng::fold_left(deque<int>)/1048576      277729 ns       277731 ns         2532
# | rng::fold_left(list<int>)/8               2.55 ns         2.55 ns    277025050
# | rng::fold_left(list<int>)/32              16.2 ns         16.2 ns     43058857
# | rng::fold_left(list<int>)/50              54.7 ns         54.7 ns     12705516
# | rng::fold_left(list<int>)/8192           15236 ns        15235 ns        56840
# | rng::fold_left(list<int>)/1048576      4827263 ns      4827147 ns          152
```

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes/23.rst
    libcxx/include/__algorithm/ranges_fold.h
    libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/left_folds.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index c19a731a006d7..a1d62a367f33c 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -43,6 +43,10 @@ Implemented Papers
 Improvements and New Features
 -----------------------------
 
+- The ``std::ranges::fold_left_with_iter`` algorithm has been optimized for
+  segmented iterators, resulting in a performance improvement of up to 1.38x
+  for ``std::deque<int>`` iterators.
+
 Deprecations and Removals
 -------------------------
 

diff  --git a/libcxx/include/__algorithm/ranges_fold.h b/libcxx/include/__algorithm/ranges_fold.h
index d2c3921398504..c2d150a16d328 100644
--- a/libcxx/include/__algorithm/ranges_fold.h
+++ b/libcxx/include/__algorithm/ranges_fold.h
@@ -10,12 +10,14 @@
 #ifndef _LIBCPP___ALGORITHM_RANGES_FOLD_H
 #define _LIBCPP___ALGORITHM_RANGES_FOLD_H
 
+#include <__algorithm/for_each.h>
 #include <__concepts/assignable.h>
 #include <__concepts/constructible.h>
 #include <__concepts/convertible_to.h>
 #include <__concepts/invocable.h>
 #include <__concepts/movable.h>
 #include <__config>
+#include <__functional/identity.h>
 #include <__functional/invoke.h>
 #include <__functional/reference_wrapper.h>
 #include <__iterator/concepts.h>
@@ -87,11 +89,17 @@ struct __fold_left_with_iter {
     }
 
     _Up __result = std::invoke(__f, std::move(__init), *__first);
-    for (++__first; __first != __last; ++__first) {
-      __result = std::invoke(__f, std::move(__result), *__first);
-    }
-
-    return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), std::move(__result)};
+    ++__first;
+    __identity __proj;
+    auto __end = std::__for_each(
+        std::move(__first),
+        std::move(__last),
+        [&](auto&& __element) {
+          __result = std::invoke(__f, std::move(__result), std::forward<decltype(__element)>(__element));
+        },
+        __proj);
+
+    return fold_left_with_iter_result<_Ip, _Up>{std::move(__end), std::move(__result)};
   }
 
   template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp>

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/left_folds.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/left_folds.pass.cpp
index 4987ca9cac4ae..107e09a63c96f 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/left_folds.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.fold/left_folds.pass.cpp
@@ -36,6 +36,7 @@
 #include <iterator>
 #include <list>
 #include <ranges>
+#include <set>
 #include <string_view>
 #include <string>
 #include <vector>
@@ -322,6 +323,12 @@ void runtime_only_test_case() {
                                  // int(-15.5) + -6.6 = -15 + -6.6 = -21.6.
     check(data, 0.0, plus, expected);
   }
+
+  {
+    auto const data     = std::set<int>{2, 4, 6, 8, 10, 12};
+    auto const expected = triangular_sum(data);
+    check(data, 0, std::plus<long>(), static_cast<long>(expected));
+  }
 }
 
 int main(int, char**) {


        


More information about the libcxx-commits mailing list