|
22 | 22 | #endif
|
23 | 23 | #endif // __clang__
|
24 | 24 |
|
| 25 | +// See vec::DataType definitions for more details |
| 26 | +#ifndef __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE |
| 27 | +#if defined(__INTEL_PREVIEW_BREAKING_CHANGES) |
| 28 | +#define __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE 1 |
| 29 | +#else |
| 30 | +#define __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE 0 |
| 31 | +#endif |
| 32 | +#endif |
| 33 | + |
25 | 34 | #if !defined(__HAS_EXT_VECTOR_TYPE__) && defined(__SYCL_DEVICE_ONLY__)
|
26 | 35 | #error "SYCL device compiler is built without ext_vector_type support"
|
27 | 36 | #endif
|
@@ -84,6 +93,9 @@ struct elem {
|
84 | 93 | };
|
85 | 94 |
|
86 | 95 | namespace detail {
|
| 96 | +// To be defined in tests, trick to access vec's private methods |
| 97 | +template <typename T1, int T2> class vec_base_test; |
| 98 | + |
87 | 99 | template <typename VecT, typename OperationLeftT, typename OperationRightT,
|
88 | 100 | template <typename> class OperationCurrentT, int... Indexes>
|
89 | 101 | class SwizzleOp;
|
@@ -142,7 +154,34 @@ class __SYCL_EBO vec
|
142 | 154 |
|
143 | 155 | // This represent type of underlying value. There should be only one field
|
144 | 156 | // in the class, so vec<float, 16> should be equal to float16 in memory.
|
145 |
| - using DataType = std::array<DataT, AdjustedNum>; |
| 157 | + // |
| 158 | + // In intel/llvm#14130 we incorrectly used std::array as an underlying storage |
| 159 | + // for vec data. The problem with std::array is that it comes from the C++ |
| 160 | + // STL headers which we do not control and they may use something that is |
| 161 | + // illegal in SYCL device code. One of specific examples is use of debug |
| 162 | + // assertions in MSVC's STL implementation. |
| 163 | + // |
| 164 | + // The better approach is to use plain C++ array, but the problem here is that |
| 165 | + // C++ specification does not provide any guarantees about the memory layout |
| 166 | + // of std::array and therefore directly switching to it would technically be |
| 167 | + // an ABI-break, even though the practical chances of encountering the issue |
| 168 | + // are low. |
| 169 | + // |
| 170 | + // To play it safe, we only switch to use plain array if both its size and |
| 171 | + // alignment match those of std::array, or unless the new behavior is forced |
| 172 | + // via __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE or preview breaking changes mode. |
| 173 | + using DataType = std::conditional_t< |
| 174 | +#if __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE |
| 175 | + true, |
| 176 | +#else |
| 177 | + sizeof(std::array<DataT, AdjustedNum>) == sizeof(DataT[AdjustedNum]) && |
| 178 | + alignof(std::array<DataT, AdjustedNum>) == |
| 179 | + alignof(DataT[AdjustedNum]), |
| 180 | +#endif |
| 181 | + DataT[AdjustedNum], std::array<DataT, AdjustedNum>>; |
| 182 | + |
| 183 | + // To allow testing of private methods |
| 184 | + template <typename T1, int T2> friend class detail::vec_base_test; |
146 | 185 |
|
147 | 186 | #ifdef __SYCL_DEVICE_ONLY__
|
148 | 187 | using element_type_for_vector_t = typename detail::map_type<
|
@@ -387,7 +426,7 @@ class __SYCL_EBO vec
|
387 | 426 | typename vector_t_ = vector_t,
|
388 | 427 | typename = typename std::enable_if_t<std::is_same_v<vector_t_, vector_t>>>
|
389 | 428 | constexpr vec(vector_t_ openclVector) {
|
390 |
| - m_Data = sycl::bit_cast<DataType>(openclVector); |
| 429 | + sycl::detail::memcpy(&m_Data, &openclVector, sizeof(openclVector)); |
391 | 430 | }
|
392 | 431 |
|
393 | 432 | /* @SYCL2020
|
@@ -501,7 +540,7 @@ class __SYCL_EBO vec
|
501 | 540 | if constexpr (canUseNativeVectorConvert) {
|
502 | 541 | auto val = detail::convertImpl<T, R, roundingMode, NumElements, OpenCLVecT,
|
503 | 542 | OpenCLVecR>(NativeVector);
|
504 |
| - Result.m_Data = sycl::bit_cast<decltype(Result.m_Data)>(val); |
| 543 | + sycl::detail::memcpy(&Result.m_Data, &val, sizeof(Result)); |
505 | 544 | } else
|
506 | 545 | #endif // __SYCL_DEVICE_ONLY__
|
507 | 546 | {
|
|
0 commit comments