[libcxx-commits] [libcxx] [libcxx] Optimize `std::fold_left_with_iter` for segmented iterators (PR #177853)
Connector Switch via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 25 04:40:22 PST 2026
https://github.com/c8ef created https://github.com/llvm/llvm-project/pull/177853
Part of https://github.com/llvm/llvm-project/issues/102817.
This patch attempts to optimize the performance of `std::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
```
>From 50f1bd8d398bd8e24ff2f346ba538d38afde59cc Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Sun, 25 Jan 2026 20:37:09 +0800
Subject: [PATCH] optimize fold_left_with_iter
---
libcxx/docs/ReleaseNotes/23.rst | 4 ++++
libcxx/include/__algorithm/ranges_fold.h | 18 ++++++++++++------
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index 73f5984768592..046ce4ad22b51 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -41,6 +41,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 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..82614ec311164 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>
@@ -80,18 +82,22 @@ concept __indirectly_binary_left_foldable =
struct __fold_left_with_iter {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) {
- using _Up = decay_t<invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
+ using _Up = decay_t<invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
+ using __iter_ref = decltype(*__first);
if (__first == __last) {
return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), _Up(std::move(__init))};
}
_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;
+ auto __for_each_f = [&](__iter_ref __element) {
+ __result = std::invoke(__f, std::move(__result), std::forward<__iter_ref>(__element));
+ };
+ __identity __proj;
+ auto __end = std::__for_each(std::move(__first), std::move(__last), __for_each_f, __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>
More information about the libcxx-commits
mailing list