Skip to content

Commit e9280a1

Browse files
authored
[libc++] Backport segmented iterator optimization for std::for_each to C++11 (llvm#134960)
Previously, the segmented iterator optimization for `std::for_each` was restricted to C++23 and later due to its dependency on `__movable_box`, which is not available in earlier standards. This patch eliminates that restriction, enabling consistent optimizations starting from C++11. By backporting this enhancement, we improve performance across older standards and create opportunities to extend similar optimizations to other algorithms by forwarding their calls to `std::for_each`.
1 parent f91df0d commit e9280a1

File tree

15 files changed

+277
-163
lines changed

15 files changed

+277
-163
lines changed

libcxx/docs/ReleaseNotes/21.rst

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ Improvements and New Features
6767
- The ``std::stable_sort`` algorithm uses radix sort for floating-point types now, which can improve the performance
6868
up to 10x, depending on type of sorted elements and the initial state of the sorted array.
6969

70+
- The segmented iterator optimization for ``std::for_each`` has been backported to C++11. Previously it was only available
71+
in C++23 and later.
72+
7073
Deprecations and Removals
7174
-------------------------
7275

libcxx/include/__algorithm/for_each.h

+20-24
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,40 @@
1313
#include <__algorithm/for_each_segment.h>
1414
#include <__config>
1515
#include <__iterator/segmented_iterator.h>
16-
#include <__ranges/movable_box.h>
17-
#include <__utility/in_place.h>
18-
#include <__utility/move.h>
16+
#include <__type_traits/enable_if.h>
1917

2018
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2119
# pragma GCC system_header
2220
#endif
2321

24-
_LIBCPP_PUSH_MACROS
25-
#include <__undef_macros>
26-
2722
_LIBCPP_BEGIN_NAMESPACE_STD
2823

29-
template <class _InputIterator, class _Function>
30-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
31-
for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
24+
template <class _InputIterator, class _Sent, class _Func>
25+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __for_each(_InputIterator __first, _Sent __last, _Func& __f) {
3226
for (; __first != __last; ++__first)
3327
__f(*__first);
34-
return __f;
3528
}
3629

37-
// __movable_box is available in C++20, but is actually a copyable-box, so optimization is only correct in C++23
38-
#if _LIBCPP_STD_VER >= 23
39-
template <class _SegmentedIterator, class _Function>
40-
requires __is_segmented_iterator<_SegmentedIterator>::value
41-
_LIBCPP_HIDE_FROM_ABI constexpr _Function
42-
for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) {
43-
ranges::__movable_box<_Function> __wrapped_func(in_place, std::move(__func));
44-
std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) {
45-
__wrapped_func =
46-
ranges::__movable_box<_Function>(in_place, std::for_each(__lfirst, __llast, std::move(*__wrapped_func)));
30+
#ifndef _LIBCPP_CXX03_LANG
31+
template <class _SegmentedIterator,
32+
class _Function,
33+
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
34+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
35+
__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function& __func) {
36+
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
37+
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
38+
std::__for_each(__lfirst, __llast, __func);
4739
});
48-
return std::move(*__wrapped_func);
4940
}
50-
#endif // _LIBCPP_STD_VER >= 23
41+
#endif // !_LIBCPP_CXX03_LANG
5142

52-
_LIBCPP_END_NAMESPACE_STD
43+
template <class _InputIterator, class _Function>
44+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
45+
for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
46+
std::__for_each(__first, __last, __f);
47+
return __f;
48+
}
5349

54-
_LIBCPP_POP_MACROS
50+
_LIBCPP_END_NAMESPACE_STD
5551

5652
#endif // _LIBCPP___ALGORITHM_FOR_EACH_H

libcxx/include/algorithm

+1
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,7 @@ template <class BidirectionalIterator, class Compare>
20612061
# include <cstring>
20622062
# include <iterator>
20632063
# include <memory>
2064+
# include <optional>
20642065
# include <stdexcept>
20652066
# include <type_traits>
20662067
# include <utility>

libcxx/include/array

+1
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ _LIBCPP_POP_MACROS
566566
# include <cstdlib>
567567
# include <iterator>
568568
# include <new>
569+
# include <optional>
569570
# include <type_traits>
570571
# include <utility>
571572
# endif

libcxx/include/bitset

+1
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,7 @@ _LIBCPP_POP_MACROS
973973
# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
974974
# include <concepts>
975975
# include <cstdlib>
976+
# include <optional>
976977
# include <type_traits>
977978
# endif
978979
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)

libcxx/include/codecvt

+1
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ _LIBCPP_END_NAMESPACE_STD
596596
# include <limits>
597597
# include <mutex>
598598
# include <new>
599+
# include <optional>
599600
# include <stdexcept>
600601
# include <type_traits>
601602
# include <typeinfo>

libcxx/include/condition_variable

+1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ _LIBCPP_POP_MACROS
357357
# include <initializer_list>
358358
# include <iosfwd>
359359
# include <new>
360+
# include <optional>
360361
# include <stdexcept>
361362
# include <system_error>
362363
# include <type_traits>

libcxx/include/ios

+1
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,7 @@ _LIBCPP_POP_MACROS
887887
# include <limits>
888888
# include <mutex>
889889
# include <new>
890+
# include <optional>
890891
# include <stdexcept>
891892
# include <system_error>
892893
# include <type_traits>

libcxx/include/locale

+1
Original file line numberDiff line numberDiff line change
@@ -3692,6 +3692,7 @@ _LIBCPP_POP_MACROS
36923692
# include <cstdarg>
36933693
# include <iterator>
36943694
# include <mutex>
3695+
# include <optional>
36953696
# include <stdexcept>
36963697
# include <type_traits>
36973698
# include <typeinfo>

libcxx/include/streambuf

+1
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ _LIBCPP_POP_MACROS
386386

387387
# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
388388
# include <cstdint>
389+
# include <optional>
389390
# endif
390391
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
391392

libcxx/include/string

+1
Original file line numberDiff line numberDiff line change
@@ -4027,6 +4027,7 @@ _LIBCPP_POP_MACROS
40274027
# include <cstdlib>
40284028
# include <iterator>
40294029
# include <new>
4030+
# include <optional>
40304031
# include <type_traits>
40314032
# include <typeinfo>
40324033
# include <utility>

libcxx/include/string_view

+1
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,7 @@ _LIBCPP_POP_MACROS
952952
# include <concepts>
953953
# include <cstdlib>
954954
# include <iterator>
955+
# include <optional>
955956
# include <type_traits>
956957
# endif
957958
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)

libcxx/include/system_error

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ template <> struct hash<std::error_condition>;
168168
# include <cstdint>
169169
# include <cstring>
170170
# include <limits>
171+
# include <optional>
171172
# include <type_traits>
172173
# endif
173174
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)

libcxx/include/vector

+1
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
362362
# if _LIBCPP_HAS_LOCALIZATION
363363
# include <locale>
364364
# endif
365+
# include <optional>
365366
# include <string>
366367
# include <string_view>
367368
# include <tuple>

0 commit comments

Comments
 (0)