diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 1c05a7f7638..0aaca52f99e 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -111,6 +111,7 @@ endfunction() add_benchmark(bitset_to_string src/bitset_to_string.cpp) add_benchmark(find_and_count src/find_and_count.cpp) add_benchmark(find_first_of src/find_first_of.cpp) +add_benchmark(iota src/iota.cpp) add_benchmark(locale_classic src/locale_classic.cpp) add_benchmark(minmax_element src/minmax_element.cpp) add_benchmark(mismatch src/mismatch.cpp) diff --git a/benchmarks/src/iota.cpp b/benchmarks/src/iota.cpp new file mode 100644 index 00000000000..9d96d12d773 --- /dev/null +++ b/benchmarks/src/iota.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +template +void bm(benchmark::State& state) { + const auto size = static_cast(state.range(0)); + + std::vector a(size); + + for (auto _ : state) { + std::iota(a.begin(), a.end(), T{22}); + benchmark::DoNotOptimize(a); + } +} + +void common_args(auto bm) { + bm->Arg(7)->Arg(18)->Arg(43)->Arg(131)->Arg(315)->Arg(1212); +} + +BENCHMARK(bm)->Apply(common_args); +BENCHMARK(bm)->Apply(common_args); + +BENCHMARK_MAIN(); diff --git a/stl/inc/numeric b/stl/inc/numeric index 6bad9695f31..ccd04b65752 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -517,6 +517,22 @@ _CONSTEXPR20 void iota(_FwdIt _First, _FwdIt _Last, _Ty _Val) { _STD _Adl_verify_range(_First, _Last); auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); + + if constexpr (_Iterator_is_contiguous && is_integral_v<_Ty> && sizeof(_Ty) >= 4) { + // TRANSITION, DevCom-10593477: help the compiler vectorize + const auto _Ptr = _To_address(_UFirst); + const auto _Size = static_cast(_ULast - _UFirst); + + if (_STD _In_range<_Ty>(_Size)) { + const auto _Size_typed = static_cast<_Ty>(_Size); + for (_Ty _Ix = 0; _Ix != _Size_typed; ++_Ix) { + _Ptr[_Ix] = _Val + _Ix; + } + + return; + } + } + for (; _UFirst != _ULast; ++_UFirst, (void) ++_Val) { *_UFirst = _Val; } diff --git a/stl/inc/utility b/stl/inc/utility index cd224102e59..070899fb3fa 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -788,20 +788,12 @@ _EXPORT_STD template constexpr in_place_index_t<_Idx> in_place_index{}; #endif // _HAS_CXX17 -#if _HAS_CXX20 template -constexpr bool _Is_standard_integer = is_integral_v<_Ty> - && !_Is_any_of_v, bool, char, -#ifdef _NATIVE_WCHAR_T_DEFINED - wchar_t, -#endif // _NATIVE_WCHAR_T_DEFINED -#ifdef __cpp_char8_t - char8_t, -#endif // defined(__cpp_char8_t) - char16_t, char32_t>; +constexpr bool _Is_standard_integer = _Is_any_of_v, signed char, short, int, long, long long, + unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>; -_EXPORT_STD template -_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { +template +_NODISCARD constexpr bool _Cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) { @@ -813,13 +805,13 @@ _NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcep } } -_EXPORT_STD template -_NODISCARD constexpr bool cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { - return !_STD cmp_equal(_Left, _Right); +template +_NODISCARD constexpr bool _Cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return !_STD _Cmp_equal(_Left, _Right); } -_EXPORT_STD template -_NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept { +template +_NODISCARD constexpr bool _Cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept { static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>, "The integer comparison functions only accept standard and extended integer types."); if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) { @@ -831,24 +823,24 @@ _NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept } } -_EXPORT_STD template -_NODISCARD constexpr bool cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept { - return _STD cmp_less(_Right, _Left); +template +_NODISCARD constexpr bool _Cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_less(_Right, _Left); } -_EXPORT_STD template -_NODISCARD constexpr bool cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { - return !_STD cmp_less(_Right, _Left); +template +_NODISCARD constexpr bool _Cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return !_STD _Cmp_less(_Right, _Left); } -_EXPORT_STD template -_NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { - return !_STD cmp_less(_Left, _Right); +template +_NODISCARD constexpr bool _Cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return !_STD _Cmp_less(_Left, _Right); } template -_NODISCARD consteval _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost - static_assert(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types +_NODISCARD constexpr _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost + _STL_INTERNAL_STATIC_ASSERT(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types if constexpr (is_signed_v<_Ty>) { constexpr auto _Unsigned_max = static_cast>(-1); return static_cast<_Ty>((_Unsigned_max >> 1) + 1); // well-defined, N4950 [conv.integral]/3 @@ -858,8 +850,8 @@ _NODISCARD consteval _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty> } template -_NODISCARD consteval _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>::max)(), less throughput cost - static_assert(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types +_NODISCARD constexpr _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty>::max)(), less throughput cost + _STL_INTERNAL_STATIC_ASSERT(_Is_standard_integer<_Ty>); // doesn't attempt to handle all types if constexpr (is_signed_v<_Ty>) { constexpr auto _Unsigned_max = static_cast>(-1); return static_cast<_Ty>(_Unsigned_max >> 1); @@ -868,15 +860,15 @@ _NODISCARD consteval _Ty _Max_limit() noexcept { // same as (numeric_limits<_Ty> } } -_EXPORT_STD template -_NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { +template +_NODISCARD constexpr bool _In_range(const _Ty _Value) noexcept { static_assert(_Is_standard_integer<_Rx> && _Is_standard_integer<_Ty>, "The integer comparison functions only accept standard and extended integer types."); constexpr auto _Ty_min = _Min_limit<_Ty>(); constexpr auto _Rx_min = _Min_limit<_Rx>(); - if constexpr (_STD cmp_less(_Ty_min, _Rx_min)) { + if constexpr (_STD _Cmp_less(_Ty_min, _Rx_min)) { if (_Value < _Ty{_Rx_min}) { return false; } @@ -885,7 +877,7 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { constexpr auto _Ty_max = _Max_limit<_Ty>(); constexpr auto _Rx_max = _Max_limit<_Rx>(); - if constexpr (_STD cmp_greater(_Ty_max, _Rx_max)) { + if constexpr (_STD _Cmp_greater(_Ty_max, _Rx_max)) { if (_Value > _Ty{_Rx_max}) { return false; } @@ -893,6 +885,42 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { return true; } + +#if _HAS_CXX20 +_EXPORT_STD template +_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_equal(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool cmp_not_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_not_equal(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool cmp_less(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_less(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool cmp_greater(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_greater(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool cmp_less_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_less_equal(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept { + return _STD _Cmp_greater_equal(_Left, _Right); +} + +_EXPORT_STD template +_NODISCARD constexpr bool in_range(const _Ty _Value) noexcept { + return _STD _In_range<_Rx>(_Value); +} #endif // _HAS_CXX20 #if _HAS_CXX23