Skip to content

[NFC][SYCL] Add few vec tests to document current behavior #17720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions sycl/test/basic_tests/vectors/assign.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes
// RUN: %clangxx -fsycl -fsyntax-only %s

#include <sycl/sycl.hpp>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include the header with only sycl::vec type declarations (+half)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have such policy for sycl/test-e2e but not here. IMO, it's wrong to selectively enforce it like that. If someone sees much value in not using sycl/sycl.hpp under sycl/test, then we need to clean up all existing tests and add a check that it's not added in new tests (like what I did for e2e tests).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it's wrong to selectively enforce it like that.

What do you mean by "selectively" enforce? Isn't it a general practice to write the smallest test. Basically, your test aims to test vector class functionality but instead includes the whole SYCL library. What is the value in that? The negative effect of including sycl/sycl.hpp is overhead on parsing a lot of C++ code unrelated to the tested functionality. Considering that developers are running these tests multiple times and CI is running these tests a lot, removing unnecessary overhead seems like a win to me.

If someone sees much value in not using sycl/sycl.hpp under sycl/test, then we need to clean up all existing tests and add a check that it's not added in new tests (like what I did for e2e tests).

I agree that we should enforce good practices either through code review or with tooling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that individual non-official include is strictly better than sycl/sycl.hpp (because otherwise we wouldn't have had a similar discussion when I was proposing the opposite - using detail/core.hpp vs sycl/sycl.hpp in e2e tests). As such, without documented guidelines, it should be author's choice.


using sycl::half;
using sycl::vec;
using sw_half_1 = decltype(std::declval<vec<half, 4>>().swizzle<1>());
using sw_half_2 = decltype(std::declval<vec<half, 4>>().swizzle<1, 2>());

using sw_float_1 = decltype(std::declval<vec<float, 4>>().swizzle<1>());
using sw_float_2 = decltype(std::declval<vec<float, 4>>().swizzle<1, 2>());

using sw_double_1 = decltype(std::declval<vec<double, 4>>().swizzle<1>());
using sw_double_2 = decltype(std::declval<vec<double, 4>>().swizzle<1, 2>());

// clang-format off

// NOTE: Empty space is for the future markup using NOT_IN_PREVIEW/PREVIEW_ONLY
// macros.

// IN_PREVIEW_ONLY condition<>
// EXCEPT_IN_PREVIEW condition<>

Comment on lines +22 to +24
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving discussion from #17712 (comment) to here.

@uditagarwal97 , can you review please?

static_assert( std::is_assignable_v<vec<half, 1>, half>);
static_assert( std::is_assignable_v<vec<half, 1>, float>);
static_assert( std::is_assignable_v<vec<half, 1>, double>);
static_assert( std::is_assignable_v<vec<half, 1>, vec<half, 1>>);
static_assert( std::is_assignable_v<vec<half, 1>, vec<float, 1>>);
static_assert( std::is_assignable_v<vec<half, 1>, vec<double, 1>>);
static_assert( std::is_assignable_v<vec<half, 1>, sw_half_1>);
static_assert( std::is_assignable_v<vec<half, 1>, sw_float_1>);
static_assert( std::is_assignable_v<vec<half, 1>, sw_double_1>);
static_assert( !std::is_assignable_v<vec<half, 1>, sw_half_2>);
static_assert( !std::is_assignable_v<vec<half, 1>, sw_float_2>);
static_assert( !std::is_assignable_v<vec<half, 1>, sw_double_2>);

static_assert( std::is_assignable_v<vec<half, 2>, half>);
static_assert( std::is_assignable_v<vec<half, 2>, float>);
static_assert( std::is_assignable_v<vec<half, 2>, double>);
static_assert( std::is_assignable_v<vec<half, 2>, vec<half, 1>>);
static_assert( !std::is_assignable_v<vec<half, 2>, vec<float, 1>>);
static_assert( !std::is_assignable_v<vec<half, 2>, vec<double, 1>>);
static_assert( std::is_assignable_v<vec<half, 2>, sw_half_1>);
static_assert( std::is_assignable_v<vec<half, 2>, sw_float_1>);
static_assert( std::is_assignable_v<vec<half, 2>, sw_double_1>);
static_assert( std::is_assignable_v<vec<half, 2>, sw_half_2>);
static_assert( !std::is_assignable_v<vec<half, 2>, sw_float_2>);
static_assert( !std::is_assignable_v<vec<half, 2>, sw_double_2>);

static_assert( std::is_assignable_v<vec<float, 1>, half>);
static_assert( std::is_assignable_v<vec<float, 1>, float>);
static_assert( std::is_assignable_v<vec<float, 1>, double>);
static_assert( std::is_assignable_v<vec<float, 1>, vec<half, 1>>);
static_assert( std::is_assignable_v<vec<float, 1>, vec<float, 1>>);
static_assert( std::is_assignable_v<vec<float, 1>, vec<double, 1>>);
static_assert( std::is_assignable_v<vec<float, 1>, sw_half_1>);
static_assert( std::is_assignable_v<vec<float, 1>, sw_float_1>);
static_assert( std::is_assignable_v<vec<float, 1>, sw_double_1>);
static_assert( !std::is_assignable_v<vec<float, 1>, sw_half_2>);
static_assert( !std::is_assignable_v<vec<float, 1>, sw_float_2>);
static_assert( !std::is_assignable_v<vec<float, 1>, sw_double_2>);

static_assert( std::is_assignable_v<vec<float, 2>, half>);
static_assert( std::is_assignable_v<vec<float, 2>, float>);
static_assert( std::is_assignable_v<vec<float, 2>, double>);
#if __SYCL_DEVICE_ONLY__
static_assert( std::is_assignable_v<vec<float, 2>, vec<half, 1>>);
#else
static_assert( !std::is_assignable_v<vec<float, 2>, vec<half, 1>>);
#endif
static_assert( std::is_assignable_v<vec<float, 2>, vec<float, 1>>);
static_assert( std::is_assignable_v<vec<float, 2>, vec<double, 1>>);
static_assert( std::is_assignable_v<vec<float, 2>, sw_half_1>);
static_assert( std::is_assignable_v<vec<float, 2>, sw_float_1>);
static_assert( std::is_assignable_v<vec<float, 2>, sw_double_1>);
static_assert( !std::is_assignable_v<vec<float, 2>, sw_half_2>);
static_assert( std::is_assignable_v<vec<float, 2>, sw_float_2>);
static_assert( !std::is_assignable_v<vec<float, 2>, sw_double_2>);
134 changes: 134 additions & 0 deletions sycl/test/basic_tests/vectors/cxx_conversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// RUN: %clangxx -fsycl -fsyntax-only %s -fpreview-breaking-changes
// RUN: %clangxx -fsycl -fsyntax-only %s

#include <sycl/sycl.hpp>

template <class From, class To, class = void>
struct is_explicitly_convertible_to_impl : std::false_type {};

template <class From, class To>
struct is_explicitly_convertible_to_impl<
From, To, std::void_t<decltype(static_cast<To>(std::declval<From>()))>>
: std::true_type {};

template <class From, class To>
struct is_explicitly_convertible_to
: is_explicitly_convertible_to_impl<From, To> {};

template <class From, class To>
inline constexpr bool is_explicitly_convertible_to_v =
is_explicitly_convertible_to<From, To>::value;

using sycl::half;
using sycl::vec;

void f_half_v1(vec<half, 1>);
void f_half_v4(vec<half, 4>);
void f_float_v1(vec<float, 1>);
void f_float_v4(vec<float, 4>);

using sw_half_1 = decltype(std::declval<vec<half, 4>>().swizzle<1>());
using sw_half_2 = decltype(std::declval<vec<half, 4>>().swizzle<1, 2>());

using sw_float_1 = decltype(std::declval<vec<float, 4>>().swizzle<1>());
using sw_float_2 = decltype(std::declval<vec<float, 4>>().swizzle<1, 2>());

using sw_double_1 = decltype(std::declval<vec<double, 4>>().swizzle<1>());
using sw_double_2 = decltype(std::declval<vec<double, 4>>().swizzle<1, 2>());

// clang-format off

// NOTE: Empty space is for the future markup using NOT_IN_PREVIEW/PREVIEW_ONLY
// macros.


// IN_PREVIEW_ONLY condition<>
// EXCEPT_IN_PREVIEW condition<>

static_assert( std::is_invocable_v<decltype(f_half_v1), half>);
static_assert( std::is_invocable_v<decltype(f_half_v1), float>);
static_assert( std::is_invocable_v<decltype(f_half_v1), double>);
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_half_1>);
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_float_1>);
static_assert( std::is_invocable_v<decltype(f_half_v1), sw_double_1>);
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<half, 1>>);
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<float, 1>>);
static_assert( std::is_invocable_v<decltype(f_half_v1), vec<double, 1>>);

static_assert( std::is_invocable_v<decltype(f_float_v1), half>);
static_assert( std::is_invocable_v<decltype(f_float_v1), float>);
static_assert( std::is_invocable_v<decltype(f_float_v1), double>);
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_half_1>);
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_float_1>);
static_assert( std::is_invocable_v<decltype(f_float_v1), sw_double_1>);
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<half, 1>>);
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<float, 1>>);
static_assert( std::is_invocable_v<decltype(f_float_v1), vec<double, 1>>);

static_assert( !std::is_invocable_v<decltype(f_half_v4), half>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), float>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), double>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_half_1>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_float_1>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_double_1>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_half_2, sw_half_2>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_float_2, sw_float_2>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_double_2, sw_double_2>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_half_2, sw_float_2>);
static_assert( !std::is_invocable_v<decltype(f_half_v4), sw_half_2, sw_double_2>);

static_assert( !std::is_invocable_v<decltype(f_float_v4), half>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), float>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), double>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_half_1>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_float_1>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_double_1>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_half_2, sw_half_2>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_float_2, sw_float_2>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_double_2, sw_double_2>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_float_2, sw_float_2>);
static_assert( !std::is_invocable_v<decltype(f_float_v4), sw_float_2, sw_double_2>);

static_assert( is_explicitly_convertible_to_v<half, vec<half, 1>>);
static_assert( is_explicitly_convertible_to_v<float, vec<half, 1>>);
static_assert( is_explicitly_convertible_to_v<double, vec<half, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_half_1, vec<half, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_float_1, vec<half, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_double_1, vec<half, 1>>);

static_assert( is_explicitly_convertible_to_v<half, vec<float, 1>>);
static_assert( is_explicitly_convertible_to_v<float, vec<float, 1>>);
static_assert( is_explicitly_convertible_to_v<double, vec<float, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_half_1, vec<float, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_float_1, vec<float, 1>>);
static_assert( is_explicitly_convertible_to_v<sw_double_1, vec<float, 1>>);

static_assert( is_explicitly_convertible_to_v<half, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<float, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<double, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<sw_half_1, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<sw_float_1, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<sw_double_1, vec<half, 4>>);
static_assert( !is_explicitly_convertible_to_v<sw_half_2, vec<half, 4>>);
static_assert( !is_explicitly_convertible_to_v<sw_float_2, vec<half, 4>>);
static_assert( !is_explicitly_convertible_to_v<sw_double_2, vec<half, 4>>);
static_assert( !is_explicitly_convertible_to_v<sw_half_2, vec<half, 4>>);
static_assert( !is_explicitly_convertible_to_v<sw_half_2, vec<half, 4>>);
static_assert( is_explicitly_convertible_to_v<sw_half_2, vec<half, 2>>);
static_assert( !is_explicitly_convertible_to_v<sw_float_2, vec<half, 2>>);
static_assert( !is_explicitly_convertible_to_v<sw_double_2, vec<half, 2>>);
static_assert( is_explicitly_convertible_to_v<sw_half_2, vec<half, 2>>);
static_assert( is_explicitly_convertible_to_v<sw_half_2, vec<half, 2>>);

static_assert( is_explicitly_convertible_to_v<vec<half, 1>, half>);
#if __SYCL_DEVICE_ONLY__
static_assert( is_explicitly_convertible_to_v<vec<half, 1>, float>);
static_assert( is_explicitly_convertible_to_v<vec<half, 1>, double>);
#else
static_assert( !is_explicitly_convertible_to_v<vec<half, 1>, float>);
static_assert( !is_explicitly_convertible_to_v<vec<half, 1>, double>);
#endif

static_assert( is_explicitly_convertible_to_v<vec<float, 1>, half>);
static_assert( is_explicitly_convertible_to_v<vec<float, 1>, float>);
static_assert( is_explicitly_convertible_to_v<vec<float, 1>, double>);
Loading