diff --git a/libcxx/benchmarks/CMakeLists.txt b/libcxx/benchmarks/CMakeLists.txt --- a/libcxx/benchmarks/CMakeLists.txt +++ b/libcxx/benchmarks/CMakeLists.txt @@ -159,6 +159,7 @@ set(BENCHMARK_TESTS algorithms.partition_point.bench.cpp algorithms/equal.bench.cpp + algorithms/for_each.bench.cpp algorithms/lower_bound.bench.cpp algorithms/make_heap.bench.cpp algorithms/make_heap_then_sort_heap.bench.cpp diff --git a/libcxx/benchmarks/algorithms/for_each.bench.cpp b/libcxx/benchmarks/algorithms/for_each.bench.cpp new file mode 100644 --- /dev/null +++ b/libcxx/benchmarks/algorithms/for_each.bench.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +static void bm_for_each(benchmark::State& state) { + std::deque vec1(state.range(), '1'); + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::for_each(vec1.begin(), vec1.end(), [](char& v) { + v = std::clamp(v, (char)10, (char)100); + })); + } +} +BENCHMARK(bm_for_each)->DenseRange(1, 8)->Range(16, 1 << 20); + +BENCHMARK_MAIN(); diff --git a/libcxx/include/__algorithm/for_each.h b/libcxx/include/__algorithm/for_each.h --- a/libcxx/include/__algorithm/for_each.h +++ b/libcxx/include/__algorithm/for_each.h @@ -10,7 +10,11 @@ #ifndef _LIBCPP___ALGORITHM_FOR_EACH_H #define _LIBCPP___ALGORITHM_FOR_EACH_H +#include <__algorithm/for_each_segment.h> #include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/enable_if.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,14 +23,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function for_each(_InputIterator __first, - _InputIterator __last, - _Function __f) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function +for_each(_InputIterator __first, _InputIterator __last, _Function __f) { for (; __first != __last; ++__first) __f(*__first); return __f; } +#if _LIBCPP_STD_VER >= 20 +template + requires __is_segmented_iterator<_SegmentedIterator>::value +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function +for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) { + std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) { + __func = std::for_each(__lfirst, __llast, std::move(__func)); + }); + return __func; +} +#endif // _LIBCPP_STD_VER >= 14 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_FOR_EACH_H