diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 582f7d627cc..de7b712b0c8 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5774,7 +5774,7 @@ namespace ranges { constexpr bool _Allow_vectorization = conjunction_v<_Is_trivially_ranges_swappable<_Elem>, negation>>; - if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { + if constexpr (_Allow_vectorization && _Is_vector_element_size<_Nx>) { if (!_STD is_constant_evaluated()) { _STD _Reverse_vectorized<_Nx>(_STD to_address(_First), _STD to_address(_Last)); return; @@ -5834,7 +5834,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { _Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation>>; constexpr size_t _Nx = sizeof(_Elem); - if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { + if constexpr (_Allow_vectorization && _Is_vector_element_size<_Nx>) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 @@ -5924,7 +5924,7 @@ namespace ranges { _Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation>>; constexpr size_t _Nx = sizeof(_Elem); - if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { + if constexpr (_Allow_vectorization && _Is_vector_element_size<_Nx>) { if (!_STD is_constant_evaluated()) { const auto _Dest_dist = static_cast>(_Last - _First); _STD _Contiguous_iter_verify(_Output, _Dest_dist); diff --git a/stl/inc/xutility b/stl/inc/xutility index bc62b17f16d..ea39e607b4c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -5789,11 +5789,11 @@ template constexpr bool _Equal_memcmp_is_safe = _Equal_memcmp_is_safe_helper, remove_const_t<_Iter2>, remove_const_t<_Pr>>; -#if _VECTORIZED_SEARCH || _VECTORIZED_ADJACENT_FIND || _VECTORIZED_FIND_END || _VECTORIZED_FIND_FIRST_OF \ - || _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY template constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 || _Size == 8; +#if _VECTORIZED_SEARCH || _VECTORIZED_ADJACENT_FIND || _VECTORIZED_FIND_END || _VECTORIZED_FIND_FIRST_OF \ + || _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY // Can we activate the vector algorithms for search, adjacent_find, find_end, find_first_of, and default_searcher? // (Also used indirectly for unique and unique_copy.) template @@ -6344,23 +6344,25 @@ struct _Vector_alg_in_find_is_safe_object_pointers<_Ty1*, _Ty2*> // Can we activate the vector algorithms to find a value in a range of elements? template constexpr bool _Vector_alg_in_find_is_safe_elem = - _Is_same_and_builtin_trivially_equality_comparable<_Ty, _Elem> - || disjunction_v< + _Is_vector_element_size + && (_Is_same_and_builtin_trivially_equality_comparable<_Ty, _Elem> + || disjunction_v< #ifdef __cpp_lib_byte - // We're finding a std::byte in a range of std::byte. - conjunction, is_same<_Elem, byte>>, + // We're finding a std::byte in a range of std::byte. + conjunction, is_same<_Elem, byte>>, #endif // defined(__cpp_lib_byte) - // We're finding an integer in a range of integers. - // This case is the one that requires careful runtime handling in _Could_compare_equal_to_value_type. - conjunction, is_integral<_Elem>>, - // We're finding an (object or function) pointer in a range of pointers of the same type. - conjunction, is_same<_Ty, _Elem>>, - // We're finding a nullptr in a range of (object or function) pointers. - conjunction, is_pointer<_Elem>>, - // We're finding an object pointer in a range of object pointers, and: - // - One of the pointer types is a cv void*. - // - One of the pointer types is a cv1 U* and the other is a cv2 U*. - _Vector_alg_in_find_is_safe_object_pointers<_Ty, _Elem>>; + + // We're finding an integer in a range of integers. + // This case is the one that requires careful runtime handling in _Could_compare_equal_to_value_type. + conjunction, is_integral<_Elem>>, + // We're finding an (object or function) pointer in a range of pointers of the same type. + conjunction, is_same<_Ty, _Elem>>, + // We're finding a nullptr in a range of (object or function) pointers. + conjunction, is_pointer<_Elem>>, + // We're finding an object pointer in a range of object pointers, and: + // - One of the pointer types is a cv void*. + // - One of the pointer types is a cv1 U* and the other is a cv2 U*. + _Vector_alg_in_find_is_safe_object_pointers<_Ty, _Elem>>); // Can we activate the vector algorithms for find, count, remove, remove_copy, and ranges::find_last? // (Also used indirectly for replace and search_n.) @@ -6840,7 +6842,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse _Is_trivially_swappable<_Elem>, negation>>; constexpr size_t _Nx = sizeof(_Elem); - if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { + if constexpr (_Allow_vectorization && _Is_vector_element_size) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 diff --git a/tests/std/test.lst b/tests/std/test.lst index e0348743600..cee31194f85 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -281,6 +281,7 @@ tests\GH_005800_stable_sort_large_alignment tests\GH_005816_numeric_limits_traps tests\GH_005968_headers_provide_begin_end tests\GH_005974_asan_annotate_optional +tests\GH_006294_vectorized_find_is_safe tests\LWG2381_num_get_floating_point tests\LWG2510_tag_classes tests\LWG2597_complex_branch_cut diff --git a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp index 52bcd932c13..ab5c7f6b391 100644 --- a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp @@ -157,6 +157,13 @@ struct DefaultComparisonOddSize { bool operator==(const DefaultComparisonOddSize&) const noexcept = default; }; + +struct DefaultComparisonLargeSize { + long long i; + long long j; + + bool operator==(const DefaultComparisonLargeSize&) const noexcept = default; +}; #endif // _HAS_CXX20 #ifdef __cpp_lib_is_pointer_interconvertible @@ -529,10 +536,12 @@ STATIC_ASSERT(test_equal_memcmp_is_safe_for_types> == magic); STATIC_ASSERT(_Equal_memcmp_is_safe> == magic); +STATIC_ASSERT(_Equal_memcmp_is_safe> == magic); #if _VECTORIZED_SEARCH || _VECTORIZED_ADJACENT_FIND || _VECTORIZED_FIND_END || _VECTORIZED_FIND_FIRST_OF \ || _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY STATIC_ASSERT(_Vector_alg_in_search_is_safe> == magic); STATIC_ASSERT(!_Vector_alg_in_search_is_safe>); +STATIC_ASSERT(!_Vector_alg_in_search_is_safe>); #endif // ^^^ _Vector_alg_in_search_is_safe is available ^^^ #endif // _HAS_CXX20 diff --git a/tests/std/tests/GH_006294_vectorized_find_is_safe/env.lst b/tests/std/tests/GH_006294_vectorized_find_is_safe/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_006294_vectorized_find_is_safe/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_006294_vectorized_find_is_safe/test.compile.pass.cpp b/tests/std/tests/GH_006294_vectorized_find_is_safe/test.compile.pass.cpp new file mode 100644 index 00000000000..b727bfc2d3e --- /dev/null +++ b/tests/std/tests/GH_006294_vectorized_find_is_safe/test.compile.pass.cpp @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +using namespace std; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#if _HAS_CXX20 + +#ifdef __clang__ +constexpr bool vectorized_trivial_comparison = true; +#else +constexpr bool vectorized_trivial_comparison = false; +#endif + +struct DefaultComparison { + int32_t i; + + bool operator==(const DefaultComparison&) const noexcept = default; +}; + +struct DefaultComparisonOddSize { + int32_t i; + int16_t j; + + bool operator==(const DefaultComparisonOddSize&) const noexcept = default; +}; + +struct DefaultComparisonLargeSize { + int32_t i; + int32_t j; + + bool operator==(const DefaultComparisonLargeSize&) const noexcept = default; +}; + +struct DefaultComparisonTooLargeSize { + int64_t i; + int64_t j; + + bool operator==(const DefaultComparisonTooLargeSize&) const noexcept = default; +}; + +#endif // _HAS_CXX20 + +STATIC_ASSERT( + _Vector_alg_in_find_is_safe); // ints are trivially equality comparable and 4 bytes, so should be allowed +STATIC_ASSERT(_Vector_alg_in_find_is_safe); // long is an integral type with a supported element size (4 or 8 bytes), so should be allowed + +STATIC_ASSERT(_Vector_alg_in_find_is_safe); // "Top level const should not change the answer" +STATIC_ASSERT(!_Vector_alg_in_find_is_safe); // "Don't allow floating point" +STATIC_ASSERT(!_Vector_alg_in_find_is_safe); // "Don't allow volatile" + +#if _HAS_CXX20 +STATIC_ASSERT(_Vector_alg_in_find_is_safe == vectorized_trivial_comparison); +STATIC_ASSERT(_Vector_alg_in_find_is_safe + == vectorized_trivial_comparison); +STATIC_ASSERT(!_Vector_alg_in_find_is_safe); +STATIC_ASSERT(!_Vector_alg_in_find_is_safe); +#endif // _HAS_CXX20