[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