Skip to content

Commit a0979df

Browse files
[SYCL] Fix vec constructors
Implements KhronosGroup/SYCL-Docs#668. Note that the "test" added here is less of a 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 80c6fe3 commit a0979df

File tree

4 files changed

+85
-32
lines changed

4 files changed

+85
-32
lines changed

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

Lines changed: 12 additions & 0 deletions
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_PREVIEW_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 `1` once they all land.
20+
// `__SYCL_USE_PLAIN_ARRAY_AS_VEC_STORAGE` needs to be changed to use this
21+
// `__SYCL_USE_PREVIEW_VEC_IMPL` at that time as well.
22+
#define __SYCL_USE_PREVIEW_VEC_IMPL 0
23+
#else
24+
#define __SYCL_USE_PREVIEW_VEC_IMPL 0
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

Lines changed: 42 additions & 13 deletions
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_PREVIEW_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

Lines changed: 16 additions & 8 deletions
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_PREVIEW_VEC_IMPL` once it's auto-set.
2+
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes -D__SYCL_USE_PREVIEW_VEC_IMPL=1
23
// RUN: %clangxx -fsycl -fsyntax-only %s
34

45
#include <sycl/sycl.hpp>
@@ -14,17 +15,20 @@ 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 NOT_IN_PREVIEW !
20+
#else
21+
#define NOT_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
static_assert( std::is_assignable_v<vec<half, 1>, half>);
23-
static_assert( std::is_assignable_v<vec<half, 1>, float>);
24-
static_assert( std::is_assignable_v<vec<half, 1>, double>);
27+
static_assert(NOT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, float>);
28+
static_assert(NOT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, double>);
2529
static_assert( std::is_assignable_v<vec<half, 1>, vec<half, 1>>);
26-
static_assert( std::is_assignable_v<vec<half, 1>, vec<float, 1>>);
27-
static_assert( std::is_assignable_v<vec<half, 1>, vec<double, 1>>);
30+
static_assert(NOT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, vec<float, 1>>);
31+
static_assert(NOT_IN_PREVIEW std::is_assignable_v<vec<half, 1>, vec<double, 1>>);
2832
static_assert( std::is_assignable_v<vec<half, 1>, sw_half_1>);
2933
static_assert( std::is_assignable_v<vec<half, 1>, sw_float_1>);
3034
static_assert( std::is_assignable_v<vec<half, 1>, sw_double_1>);
@@ -48,7 +52,11 @@ static_assert( !std::is_assignable_v<vec<half, 2>, sw_double_2>);
4852
static_assert( std::is_assignable_v<vec<float, 1>, half>);
4953
static_assert( std::is_assignable_v<vec<float, 1>, float>);
5054
static_assert( std::is_assignable_v<vec<float, 1>, double>);
55+
#if __SYCL_DEVICE_ONLY__
5156
static_assert( std::is_assignable_v<vec<float, 1>, vec<half, 1>>);
57+
#else
58+
static_assert(NOT_IN_PREVIEW std::is_assignable_v<vec<float, 1>, vec<half, 1>>);
59+
#endif
5260
static_assert( std::is_assignable_v<vec<float, 1>, vec<float, 1>>);
5361
static_assert( std::is_assignable_v<vec<float, 1>, vec<double, 1>>);
5462
static_assert( std::is_assignable_v<vec<float, 1>, sw_half_1>);

sycl/test/basic_tests/vectors/cxx_conversions.cpp

Lines changed: 15 additions & 11 deletions
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_PREVIEW_VEC_IMPL` once it's auto-set.
2+
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes -D__SYCL_USE_PREVIEW_VEC_IMPL=1
23
// RUN: %clangxx -fsycl -fsyntax-only %s
34

45
#include <sycl/sycl.hpp>
@@ -36,30 +37,33 @@ 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+
#if __INTEL_PREVIEW_BREAKING_CHANGES
41+
#define NOT_IN_PREVIEW !
42+
#else
43+
#define NOT_IN_PREVIEW
44+
#endif
4045

41-
// NOTE: Empty space is for the future markup using NOT_IN_PREVIEW/PREVIEW_ONLY
42-
// macros.
46+
// clang-format off
4347

4448
static_assert( std::is_invocable_v<decltype(f_half_v1), half>);
45-
static_assert( std::is_invocable_v<decltype(f_half_v1), float>);
46-
static_assert( std::is_invocable_v<decltype(f_half_v1), double>);
49+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), float>);
50+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), double>);
4751
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_half_1>);
4852
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_float_1>);
4953
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_double_1>);
5054
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<half, 1>>);
51-
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<float, 1>>);
52-
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<double, 1>>);
55+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), vec<float, 1>>);
56+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_half_v1), vec<double, 1>>);
5357

54-
static_assert( std::is_invocable_v<decltype(f_float_v1), half>);
58+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), half>);
5559
static_assert( std::is_invocable_v<decltype(f_float_v1), float>);
5660
static_assert( std::is_invocable_v<decltype(f_float_v1), double>);
5761
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_half_1>);
5862
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_float_1>);
5963
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_double_1>);
60-
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<half, 1>>);
64+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), vec<half, 1>>);
6165
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<float, 1>>);
62-
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<double, 1>>);
66+
static_assert(NOT_IN_PREVIEW std::is_invocable_v<decltype(f_float_v1), vec<double, 1>>);
6367

6468
static_assert( !std::is_invocable_v<decltype(f_half_v4), half>);
6569
static_assert( !std::is_invocable_v<decltype(f_half_v4), float>);

0 commit comments

Comments
 (0)