Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -5774,7 +5774,7 @@ namespace ranges {
constexpr bool _Allow_vectorization =
conjunction_v<_Is_trivially_ranges_swappable<_Elem>, negation<is_volatile<_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()) {
_STD _Reverse_vectorized<_Nx>(_STD to_address(_First), _STD to_address(_Last));
return;
Expand Down Expand Up @@ -5834,7 +5834,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) {
_Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation<is_volatile<_Elem>>>;
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
Expand Down Expand Up @@ -5924,7 +5924,7 @@ namespace ranges {
_Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation<is_volatile<_Elem>>>;
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<iter_difference_t<_Out>>(_Last - _First);
_STD _Contiguous_iter_verify(_Output, _Dest_dist);
Expand Down
38 changes: 20 additions & 18 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -5789,11 +5789,11 @@ template <class _Iter1, class _Iter2, class _Pr>
constexpr bool _Equal_memcmp_is_safe =
_Equal_memcmp_is_safe_helper<remove_const_t<_Iter1>, 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 <size_t _Size>
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 <class _It1, class _It2, class _Pr>
Expand Down Expand Up @@ -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 <class _Ty, class _Elem>
constexpr bool _Vector_alg_in_find_is_safe_elem =
_Is_same_and_builtin_trivially_equality_comparable<_Ty, _Elem>
|| disjunction_v<
_Is_vector_element_size<sizeof(_Elem)>
&& (_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<_Ty, byte>, is_same<_Elem, byte>>,
// We're finding a std::byte in a range of std::byte.
conjunction<is_same<_Ty, byte>, 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<_Ty>, is_integral<_Elem>>,
// We're finding an (object or function) pointer in a range of pointers of the same type.
conjunction<is_pointer<_Ty>, is_same<_Ty, _Elem>>,
// We're finding a nullptr in a range of (object or function) pointers.
conjunction<is_null_pointer<_Ty>, 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<_Ty>, is_integral<_Elem>>,
// We're finding an (object or function) pointer in a range of pointers of the same type.
conjunction<is_pointer<_Ty>, is_same<_Ty, _Elem>>,
// We're finding a nullptr in a range of (object or function) pointers.
conjunction<is_null_pointer<_Ty>, 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.)
Expand Down Expand Up @@ -6840,7 +6842,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse
_Is_trivially_swappable<_Elem>, negation<is_volatile<_Elem>>>;
constexpr size_t _Nx = sizeof(_Elem);

if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) {
if constexpr (_Allow_vectorization && _Is_vector_element_size<sizeof(_Elem)>) {
#if _HAS_CXX20
if (!_STD is_constant_evaluated())
#endif // _HAS_CXX20
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -529,10 +536,12 @@ STATIC_ASSERT(test_equal_memcmp_is_safe_for_types<magic, DefaultComparisonOddSiz
// The only difference between _Equal_memcmp_is_safe and _Vector_alg_in_search_is_safe is how the magic works
STATIC_ASSERT(_Equal_memcmp_is_safe<DefaultComparison*, DefaultComparison*, equal_to<>> == magic);
STATIC_ASSERT(_Equal_memcmp_is_safe<DefaultComparisonOddSize*, DefaultComparisonOddSize*, equal_to<>> == magic);
STATIC_ASSERT(_Equal_memcmp_is_safe<DefaultComparisonLargeSize*, DefaultComparisonLargeSize*, equal_to<>> == 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<DefaultComparison*, DefaultComparison*, equal_to<>> == magic);
STATIC_ASSERT(!_Vector_alg_in_search_is_safe<DefaultComparisonOddSize*, DefaultComparisonOddSize*, equal_to<>>);
STATIC_ASSERT(!_Vector_alg_in_search_is_safe<DefaultComparisonLargeSize*, DefaultComparisonLargeSize*, equal_to<>>);
#endif // ^^^ _Vector_alg_in_search_is_safe is available ^^^
#endif // _HAS_CXX20

Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_006294_vectorized_find_is_safe/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <cstdint>

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
Comment on lines +13 to +17

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's such a trait. Instead, since the actual implementation uses #ifdef __clang__, I believe that this approach is the correct one. It also aligns with #5767


struct DefaultComparison {
int32_t i;
Comment thread
mgovers marked this conversation as resolved.

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<int*, int>); // ints are trivially equality comparable and 4 bytes, so should be allowed
STATIC_ASSERT(_Vector_alg_in_find_is_safe<long*,
long>); // 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<int const*, int>); // "Top level const should not change the answer"
STATIC_ASSERT(!_Vector_alg_in_find_is_safe<float*, float>); // "Don't allow floating point"
STATIC_ASSERT(!_Vector_alg_in_find_is_safe<int volatile*, int>); // "Don't allow volatile"

#if _HAS_CXX20
STATIC_ASSERT(_Vector_alg_in_find_is_safe<DefaultComparison*, DefaultComparison> == vectorized_trivial_comparison);
STATIC_ASSERT(_Vector_alg_in_find_is_safe<DefaultComparisonLargeSize*, DefaultComparisonLargeSize>
== vectorized_trivial_comparison);
STATIC_ASSERT(!_Vector_alg_in_find_is_safe<DefaultComparisonOddSize*, DefaultComparisonOddSize>);
STATIC_ASSERT(!_Vector_alg_in_find_is_safe<DefaultComparisonTooLargeSize*, DefaultComparisonTooLargeSize>);
#endif // _HAS_CXX20
Loading