Skip to content

Commit aa0068b

Browse files
[SYCL] Fix vec constructors (#17712)
Implements KhronosGroup/SYCL-Docs#668. Note that the "test" changes here are less of the documentation of "intent" but rather the documentation of the effect of the change. Also, the idea behind specification changes was to keep all "reasonable" code in the wild compiling and several changes are needed together to make that happen. Until all of them land, keep the new code out of `-fpreview-breaking-changes` mode.
1 parent 8033329 commit aa0068b

File tree

4 files changed

+85
-33
lines changed

4 files changed

+85
-33
lines changed

sycl/include/sycl/detail/type_traits/vec_marray_traits.hpp

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313

1414
#include <sycl/detail/defines_elementary.hpp>
1515

16+
#ifndef __SYCL_USE_LIBSYCL8_VEC_IMPL
17+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
18+
// Several specification changes need to be implemented together to keep CTS
19+
// passing. We'll switch to `0` once they all land.
20+
// `__SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE` needs to be changed to use this
21+
// `__SYCL_USE_LIBSYCL8_VEC_IMPL` at that time as well.
22+
#define __SYCL_USE_LIBSYCL8_VEC_IMPL 1
23+
#else
24+
#define __SYCL_USE_LIBSYCL8_VEC_IMPL 1
25+
#endif
26+
#endif
27+
1628
namespace sycl {
1729
inline namespace _V1 {
1830
template <typename DataT, int NumElements> class __SYCL_EBO vec;

sycl/include/sycl/vector.hpp

+42-13
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,11 @@ inline constexpr bool is_fundamental_or_half_or_bfloat16 =
137137
std::is_fundamental_v<T> || std::is_same_v<std::remove_const_t<T>, half> ||
138138
std::is_same_v<std::remove_const_t<T>, ext::oneapi::bfloat16>;
139139

140-
// Proposed SYCL specification changes have sycl::vec having different ctors
141-
// available based on the number of elements. Without C++20's concepts we'll
142-
// have to use partial specialization to represent that. This is a helper to do
143-
// that. An alternative could be to have different specializations of the
144-
// `sycl::vec` itself but then we'd need to outline all the common interfaces to
145-
// re-use them.
146-
//
147-
// Note: the functional changes haven't been implemented yet, we've split
148-
// vec_base in advance as a way to make changes easier to review/verify.
149-
//
150-
// Another note: `vector_t` is going to be removed, so corresponding ctor was
151-
// kept inside `sycl::vec` to have all `vector_t` functionality in a single
152-
// place.
140+
// Per SYCL specification sycl::vec has different ctors available based on the
141+
// number of elements. Without C++20's concepts we'd have to use partial
142+
// specialization to represent that. This is a helper to do that. An alternative
143+
// could be to have different specializations of the `sycl::vec` itself but then
144+
// we'd need to outline all the common interfaces to re-use them.
153145
template <typename DataT, int NumElements> class vec_base {
154146
// https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html#memory-layout-and-alignment
155147
// It is required by the SPEC to align vec<DataT, 3> with vec<DataT, 4>.
@@ -271,6 +263,43 @@ template <typename DataT, int NumElements> class vec_base {
271263
: vec_base{VecArgArrayCreator<DataT, argTN...>::Create(args...),
272264
std::make_index_sequence<NumElements>()} {}
273265
};
266+
267+
#if !__SYCL_USE_LIBSYCL8_VEC_IMPL
268+
template <typename DataT> class vec_base<DataT, 1> {
269+
using DataType = std::conditional_t<
270+
#if __SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE
271+
true,
272+
#else
273+
sizeof(std::array<DataT, 1>) == sizeof(DataT[1]) &&
274+
alignof(std::array<DataT, 1>) == alignof(DataT[1]),
275+
#endif
276+
DataT[1], std::array<DataT, 1>>;
277+
278+
protected:
279+
static constexpr int alignment = (std::min)((size_t)64, sizeof(DataType));
280+
alignas(alignment) DataType m_Data{};
281+
282+
public:
283+
constexpr vec_base() = default;
284+
constexpr vec_base(const vec_base &) = default;
285+
constexpr vec_base(vec_base &&) = default;
286+
constexpr vec_base &operator=(const vec_base &) = default;
287+
constexpr vec_base &operator=(vec_base &&) = default;
288+
289+
// Not `explicit` on purpose, differs from NumElements > 1.
290+
constexpr vec_base(const DataT &arg) : m_Data{{arg}} {}
291+
292+
// FIXME: Temporary workaround because swizzle's `operator DataT` is a
293+
// template.
294+
template <typename Swizzle,
295+
typename = std::enable_if_t<is_swizzle_v<Swizzle>>,
296+
typename = std::enable_if_t<Swizzle::size() == 1>,
297+
typename = std::enable_if<
298+
std::is_convertible_v<typename Swizzle::element_type, DataT>>>
299+
constexpr vec_base(const Swizzle &other)
300+
: vec_base(static_cast<DataT>(other)) {}
301+
};
302+
#endif
274303
} // namespace detail
275304

276305
///////////////////////// class sycl::vec /////////////////////////

sycl/test/basic_tests/vectors/assign.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes
1+
// TODO: Remove `__SYCL_USE_LIBSYCL8_VEC_IMPL` once it's auto-set.
2+
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes -D__SYCL_USE_LIBSYCL8_VEC_IMPL=0
23
// RUN: %clangxx -fsycl -fsyntax-only %s
34

45
#include <sycl/sycl.hpp>
@@ -14,20 +15,23 @@ using sw_float_2 = decltype(std::declval<vec<float, 4>>().swizzle<1, 2>());
1415
using sw_double_1 = decltype(std::declval<vec<double, 4>>().swizzle<1>());
1516
using sw_double_2 = decltype(std::declval<vec<double, 4>>().swizzle<1, 2>());
1617

17-
// clang-format off
18+
#if __INTEL_PREVIEW_BREAKING_CHANGES
19+
#define EXCEPT_IN_PREVIEW !
20+
#else
21+
#define EXCEPT_IN_PREVIEW
22+
#endif
1823

19-
// NOTE: Empty space is for the future markup using NOT_IN_PREVIEW/PREVIEW_ONLY
20-
// macros.
24+
// clang-format off
2125

2226
// IN_PREVIEW_ONLY condition<>
2327
// EXCEPT_IN_PREVIEW condition<>
2428

2529
static_assert( std::is_assignable_v<vec<half, 1>, half>);
26-
static_assert( std::is_assignable_v<vec<half, 1>, float>);
27-
static_assert( std::is_assignable_v<vec<half, 1>, double>);
30+
static_assert(EXCEPT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, float>);
31+
static_assert(EXCEPT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, double>);
2832
static_assert( std::is_assignable_v<vec<half, 1>, vec<half, 1>>);
29-
static_assert( std::is_assignable_v<vec<half, 1>, vec<float, 1>>);
30-
static_assert( std::is_assignable_v<vec<half, 1>, vec<double, 1>>);
33+
static_assert(EXCEPT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, vec<float, 1>>);
34+
static_assert(EXCEPT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, vec<double, 1>>);
3135
static_assert( std::is_assignable_v<vec<half, 1>, sw_half_1>);
3236
static_assert( std::is_assignable_v<vec<half, 1>, sw_float_1>);
3337
static_assert( std::is_assignable_v<vec<half, 1>, sw_double_1>);
@@ -51,7 +55,11 @@ static_assert( !std::is_assignable_v<vec<half, 2>, sw_double_2>)
5155
static_assert( std::is_assignable_v<vec<float, 1>, half>);
5256
static_assert( std::is_assignable_v<vec<float, 1>, float>);
5357
static_assert( std::is_assignable_v<vec<float, 1>, double>);
58+
#if __SYCL_DEVICE_ONLY__
5459
static_assert( std::is_assignable_v<vec<float, 1>, vec<half, 1>>);
60+
#else
61+
static_assert(EXCEPT_IN_PREVIEW std::is_assignable_v<vec<float, 1>, vec<half, 1>>);
62+
#endif
5563
static_assert( std::is_assignable_v<vec<float, 1>, vec<float, 1>>);
5664
static_assert( std::is_assignable_v<vec<float, 1>, vec<double, 1>>);
5765
static_assert( std::is_assignable_v<vec<float, 1>, sw_half_1>);

sycl/test/basic_tests/vectors/cxx_conversions.cpp

+15-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes
1+
// TODO: Remove `__SYCL_USE_LIBSYCL8_VEC_IMPL` once it's auto-set.
2+
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes -D__SYCL_USE_LIBSYCL8_VEC_IMPL=0
23
// RUN: %clangxx -fsycl -fsyntax-only %s
34

45
#include <sycl/sycl.hpp>
@@ -36,34 +37,36 @@ using sw_float_2 = decltype(std::declval<vec<float, 4>>().swizzle<1, 2>());
3637
using sw_double_1 = decltype(std::declval<vec<double, 4>>().swizzle<1>());
3738
using sw_double_2 = decltype(std::declval<vec<double, 4>>().swizzle<1, 2>());
3839

39-
// clang-format off
40-
41-
// NOTE: Empty space is for the future markup using NOT_IN_PREVIEW/PREVIEW_ONLY
42-
// macros.
40+
#if __INTEL_PREVIEW_BREAKING_CHANGES
41+
#define EXCEPT_IN_PREVIEW !
42+
#else
43+
#define EXCEPT_IN_PREVIEW
44+
#endif
4345

46+
// clang-format off
4447

4548
// IN_PREVIEW_ONLY condition<>
4649
// EXCEPT_IN_PREVIEW condition<>
4750

4851
static_assert( std::is_invocable_v<decltype(f_half_v1), half>);
49-
static_assert( std::is_invocable_v<decltype(f_half_v1), float>);
50-
static_assert( std::is_invocable_v<decltype(f_half_v1), double>);
52+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), float>);
53+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), double>);
5154
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_half_1>);
5255
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_float_1>);
5356
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_double_1>);
5457
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<half, 1>>);
55-
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<float, 1>>);
56-
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<double, 1>>);
58+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), vec<float, 1>>);
59+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), vec<double, 1>>);
5760

58-
static_assert( std::is_invocable_v<decltype(f_float_v1), half>);
61+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), half>);
5962
static_assert( std::is_invocable_v<decltype(f_float_v1), float>);
6063
static_assert( std::is_invocable_v<decltype(f_float_v1), double>);
6164
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_half_1>);
6265
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_float_1>);
6366
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_double_1>);
64-
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<half, 1>>);
67+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), vec<half, 1>>);
6568
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<float, 1>>);
66-
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<double, 1>>);
69+
static_assert(EXCEPT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), vec<double, 1>>);
6770

6871
static_assert( !std::is_invocable_v<decltype(f_half_v4), half>);
6972
static_assert( !std::is_invocable_v<decltype(f_half_v4), float>);

0 commit comments

Comments
 (0)