<algorithm>: reverse_copy is mistakenly vectorized for pair<int&, int&> on 32-bit targets (original) (raw)
Describe the bug
From DevCom-10662768.
MSVC STL's pair<int&, int&> is trivially copyable but not trivially copy assignable. Currently, vectorization of reverse_copy incorrectly detects the element type with is_trivially_copyable, which is problematic with pair<int&, int&> and its friends.
| #if _USE_STD_VECTOR_ALGORITHMS |
|---|
| using _Elem = remove_reference_t<_Iter_ref_t<remove_const_t<decltype(_UFirst)>>>; |
| using _DestElem = remove_reference_t<_Iter_ref_t<decltype(_UDest)>>; |
| constexpr bool _Allow_vectorization = conjunction_v<is_same<remove_const_t<_Elem>, _DestElem>, |
| bool_constant<_Iterators_are_contiguous<decltype(_ULast), decltype(_UDest)>>, is_trivially_copyable<_Elem>, |
| negation<is_volatile<_Elem>>>; |
| constexpr size_t _Nx = sizeof(_Elem); |
| if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { |
| #if _HAS_CXX20 |
| if (!_STD is_constant_evaluated()) |
| #endif // _HAS_CXX20 |
| { |
| _STD _Reverse_copy_vectorized<_Nx>( |
| _STD _To_address(_UFirst), _STD _To_address(_ULast), _STD _To_address(_UDest)); |
| _UDest += _ULast - _UFirst; |
| _STD _Seek_wrapped(_Dest, _UDest); |
| return _Dest; |
| } |
| } |
| #endif // _USE_STD_VECTOR_ALGORITHMS |
| #if _USE_STD_VECTOR_ALGORITHMS |
|---|
| if constexpr (contiguous_iterator<_It> && contiguous_iterator<_Out>) { |
| using _Elem = remove_reference_t<iter_reference_t<_It>>; |
| using _DestElem = remove_reference_t<iter_reference_t<_Out>>; |
| constexpr bool _Allow_vectorization = conjunction_v<is_same<remove_const_t<_Elem>, _DestElem>, |
| is_trivially_copyable<_Elem>, negation<is_volatile<_Elem>>>; |
| constexpr size_t _Nx = sizeof(_Elem); |
| if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { |
| if (!_STD is_constant_evaluated()) { |
| _STD _Reverse_copy_vectorized<_Nx>( |
| _STD to_address(_First), _STD to_address(_Last), _STD to_address(_Result)); |
| _Result += _Last - _First; |
| return _Result; |
| } |
| } |
| } |
| #endif // _USE_STD_VECTOR_ALGORITHMS |
Command-line test case
C:\repro>type repro.cpp
#include <algorithm>
#include <cstdio>
#include <utility>
using Pear = std::pair<int &, int &>;
#ifdef _MSC_VER
static_assert(__is_trivially_copyable(Pear));
static_assert(__is_assignable(Pear &, const Pear &));
static_assert(!__is_trivially_assignable(Pear &, const Pear &));
#endif
int main() {
std::pair<int, int> src[] = {{1, 2}, {3, 4}, {5, 6}};
std::pair<int, int> dst[] = {{3, 1}, {4, 1}, {5, 9}};
std::pair<int &, int &> srcref[] = {src[0], src[1], src[2]};
std::pair<int &, int &> dstref[] = {dst[0], dst[1], dst[2]};
std::reverse_copy(srcref, srcref + 3, dstref);
// Now dst should be {5,6}, {3,4}, {1,2}
for (auto &p : dst) {
printf("%d %d\n", p.first, p.second);
}
}
C:\repro>cl /EHsc /W4 /WX /std:c++latest .\repro.cpp
用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.41.33901 版
版权所有(C) Microsoft Corporation。保留所有权利。
/std:c++latest 作为最新的 C++
working 草稿中的语言功能预览提供。我们希望你提供有关 bug 和改进建议的反馈。
但是,请注意,这些功能按原样提供,没有支持,并且会随着工作草稿的变化
而更改或移除。有关详细信息,请参阅
https://go.microsoft.com/fwlink/?linkid=2045807。
repro.cpp
Microsoft (R) Incremental Linker Version 14.41.33901.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
repro.obj
C:\repro>.\repro.exe
3 1
4 1
5 9
Expected behavior
The output should be
A 64-bit target program outputs the correct results.
STL version
Microsoft Visual Studio Community 2022 Preview
Version 17.11.0 Preview 1.0
Additional context
See also WG21-P3279R0.