Thanks to visit codestin.com
Credit goes to github.com

Skip to content

<algorithm>: reverse_copy is mistakenly vectorized for pair<int&, int&> on 32-bit targets #4686

@frederick-vs-ja

Description

@frederick-vs-ja

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.

STL/stl/inc/algorithm

Lines 5095 to 5115 in 63354c3

#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

STL/stl/inc/algorithm

Lines 5175 to 5192 in 63354c3

#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

5 6
3 4
1 2

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions