Skip to content

Commit bad3b38

Browse files
authored
[SYCL] Extends support for SYCL 2020 implicitly device copyable types (#8195)
Extends support for SYCL 2020 implicitly device copyable types and adds new tests to check correct behavior. --------- Signed-off-by: Maronas, Marcos <[email protected]>
1 parent 6a76d50 commit bad3b38

File tree

3 files changed

+167
-10
lines changed

3 files changed

+167
-10
lines changed

sycl/include/sycl/ext/oneapi/properties/properties.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,5 @@ struct is_device_copyable<
232232
std::enable_if_t<!std::is_trivially_copyable<
233233
ext::oneapi::experimental::properties<PropertiesT>>::value>>
234234
: is_device_copyable<PropertiesT> {};
235-
template <typename PropertiesT>
236-
struct is_device_copyable<
237-
const ext::oneapi::experimental::properties<PropertiesT>,
238-
std::enable_if_t<!std::is_trivially_copyable<
239-
const ext::oneapi::experimental::properties<PropertiesT>>::value>>
240-
: is_device_copyable<PropertiesT> {};
241-
242235
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
243236
} // namespace sycl

sycl/include/sycl/types.hpp

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
#include <array>
5959
#include <cmath>
6060
#include <cstring>
61+
#include <optional>
62+
#include <variant>
6163
#ifndef __SYCL_DEVICE_ONLY__
6264
#include <cfenv>
6365
#endif
@@ -2393,6 +2395,12 @@ __SYCL_DECLARE_FLOAT_VECTOR_CONVERTERS(double)
23932395
template <typename T, typename = void>
23942396
struct is_device_copyable : std::false_type {};
23952397
2398+
// NOTE: this specialization is a candidate for all T such that T is trivially
2399+
// copyable, including std::array<T, N>, std::optional<T>, std::variant<T>,
2400+
// sycl::marray<T> and T[N]. Thus, specializations for all these mentioned
2401+
// types are guarded by `std::enable_if_t<!std::is_trivially_copyable<...>>`
2402+
// so that they are candidates only for non-trivially-copyable types.
2403+
// Otherwise, there are several candidates and the compiler can't decide.
23962404
template <typename T>
23972405
struct is_device_copyable<
23982406
T, std::enable_if_t<std::is_trivially_copyable<T>::value>>
@@ -2401,16 +2409,56 @@ struct is_device_copyable<
24012409
template <typename T>
24022410
inline constexpr bool is_device_copyable_v = is_device_copyable<T>::value;
24032411
2412+
// std::array<T, 0> is implicitly device copyable type.
2413+
template <typename T>
2414+
struct is_device_copyable<std::array<T, 0>> : std::true_type {};
2415+
2416+
// std::array<T, N> is implicitly device copyable type if T is device copyable
2417+
template <typename T, std::size_t N>
2418+
struct is_device_copyable<
2419+
std::array<T, N>,
2420+
std::enable_if_t<!std::is_trivially_copyable<std::array<T, N>>::value>>
2421+
: is_device_copyable<T> {};
2422+
2423+
// std::optional<T> is implicitly device copyable type if T is device copyable
2424+
template <typename T>
2425+
struct is_device_copyable<
2426+
std::optional<T>,
2427+
std::enable_if_t<!std::is_trivially_copyable<std::optional<T>>::value>>
2428+
: is_device_copyable<T> {};
2429+
2430+
// std::pair<T1, T2> is implicitly device copyable type if T1 and T2 are device
2431+
// copyable
2432+
template <typename T1, typename T2>
2433+
struct is_device_copyable<
2434+
std::pair<T1, T2>,
2435+
std::enable_if_t<!std::is_trivially_copyable<std::pair<T1, T2>>::value>>
2436+
: detail::bool_constant<is_device_copyable<T1>::value &&
2437+
is_device_copyable<T2>::value> {};
2438+
24042439
// std::tuple<> is implicitly device copyable type.
24052440
template <> struct is_device_copyable<std::tuple<>> : std::true_type {};
24062441
24072442
// std::tuple<Ts...> is implicitly device copyable type if each type T of Ts...
24082443
// is device copyable.
24092444
template <typename T, typename... Ts>
2410-
struct is_device_copyable<std::tuple<T, Ts...>>
2445+
struct is_device_copyable<
2446+
std::tuple<T, Ts...>,
2447+
std::enable_if_t<!std::is_trivially_copyable<std::tuple<T, Ts...>>::value>>
24112448
: detail::bool_constant<is_device_copyable<T>::value &&
24122449
is_device_copyable<std::tuple<Ts...>>::value> {};
24132450
2451+
// std::variant<> is implicitly device copyable type
2452+
template <> struct is_device_copyable<std::variant<>> : std::true_type {};
2453+
2454+
// std::variant<Ts...> is implicitly device copyable type if each type T of
2455+
// Ts... is device copyable
2456+
template <typename... Ts>
2457+
struct is_device_copyable<
2458+
std::variant<Ts...>,
2459+
std::enable_if_t<!std::is_trivially_copyable<std::variant<Ts...>>::value>>
2460+
: is_device_copyable<Ts...> {};
2461+
24142462
// marray is device copyable if element type is device copyable and it is also
24152463
// not trivially copyable (if the element type is trivially copyable, the marray
24162464
// is device copyable by default).
@@ -2420,6 +2468,18 @@ struct is_device_copyable<
24202468
!std::is_trivially_copyable<T>::value>>
24212469
: std::true_type {};
24222470
2471+
// array is device copyable if element type is device copyable
2472+
template <typename T, std::size_t N>
2473+
struct is_device_copyable<
2474+
T[N], std::enable_if_t<!std::is_trivially_copyable<T>::value>>
2475+
: is_device_copyable<T> {};
2476+
2477+
template <typename T>
2478+
struct is_device_copyable<
2479+
T, std::enable_if_t<!std::is_trivially_copyable<T>::value &&
2480+
(std::is_const_v<T> || std::is_volatile_v<T>)>>
2481+
: is_device_copyable<std::remove_cv_t<T>> {};
2482+
24232483
namespace detail {
24242484
template <typename T, typename = void>
24252485
struct IsDeprecatedDeviceCopyable : std::false_type {};
@@ -2433,9 +2493,13 @@ struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020")
24332493
std::is_trivially_destructible<T>::value &&
24342494
!is_device_copyable<T>::value>> : std::true_type {};
24352495
2496+
template <typename T, int N>
2497+
struct __SYCL2020_DEPRECATED("This type isn't device copyable in SYCL 2020")
2498+
IsDeprecatedDeviceCopyable<T[N]> : IsDeprecatedDeviceCopyable<T> {};
2499+
24362500
#ifdef __SYCL_DEVICE_ONLY__
2437-
// Checks that the fields of the type T with indices 0 to (NumFieldsToCheck - 1)
2438-
// are device copyable.
2501+
// Checks that the fields of the type T with indices 0 to (NumFieldsToCheck -
2502+
// 1) are device copyable.
24392503
template <typename T, unsigned NumFieldsToCheck>
24402504
struct CheckFieldsAreDeviceCopyable
24412505
: CheckFieldsAreDeviceCopyable<T, NumFieldsToCheck - 1> {
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// RUN: %clangxx -fsycl -fsyntax-only %s
2+
3+
#include <sycl/sycl.hpp>
4+
#include <variant>
5+
6+
struct ACopyable {
7+
int i;
8+
ACopyable() = default;
9+
ACopyable(int _i) : i(_i) {}
10+
ACopyable(const ACopyable &x) : i(x.i) {}
11+
};
12+
13+
template <> struct sycl::is_device_copyable<ACopyable> : std::true_type {};
14+
15+
int main() {
16+
static_assert(sycl::is_device_copyable_v<std::pair<int, float>>);
17+
static_assert(sycl::is_device_copyable_v<std::pair<ACopyable, float>>);
18+
static_assert(sycl::is_device_copyable_v<std::tuple<int, float, bool>>);
19+
static_assert(sycl::is_device_copyable_v<std::tuple<ACopyable, float, bool>>);
20+
static_assert(sycl::is_device_copyable_v<std::variant<int, float, bool>>);
21+
static_assert(sycl::is_device_copyable_v<std::variant<ACopyable>>);
22+
static_assert(sycl::is_device_copyable_v<std::array<int, 513>>);
23+
static_assert(sycl::is_device_copyable_v<std::array<ACopyable, 513>>);
24+
static_assert(sycl::is_device_copyable_v<std::optional<int>>);
25+
static_assert(sycl::is_device_copyable_v<std::optional<ACopyable>>);
26+
static_assert(sycl::is_device_copyable_v<std::string_view>);
27+
#if __cpp_lib_span >= 202002
28+
static_assert(sycl::is_device_copyable_v<std::span<int>>);
29+
#endif
30+
static_assert(sycl::is_device_copyable_v<const sycl::span<int>>);
31+
32+
// const
33+
static_assert(sycl::is_device_copyable_v<const std::pair<int, float>>);
34+
static_assert(sycl::is_device_copyable_v<const std::pair<ACopyable, float>>);
35+
static_assert(sycl::is_device_copyable_v<const std::tuple<int, float, bool>>);
36+
static_assert(
37+
sycl::is_device_copyable_v<const std::tuple<ACopyable, float, bool>>);
38+
static_assert(
39+
sycl::is_device_copyable_v<const std::variant<int, float, bool>>);
40+
static_assert(sycl::is_device_copyable_v<const std::variant<ACopyable>>);
41+
static_assert(sycl::is_device_copyable_v<const std::array<int, 513>>);
42+
static_assert(sycl::is_device_copyable_v<const std::array<ACopyable, 513>>);
43+
static_assert(sycl::is_device_copyable_v<const std::optional<int>>);
44+
static_assert(sycl::is_device_copyable_v<const std::optional<ACopyable>>);
45+
static_assert(sycl::is_device_copyable_v<const std::string_view>);
46+
#if __cpp_lib_span >= 202002
47+
static_assert(sycl::is_device_copyable_v<const std::span<int>>);
48+
#endif
49+
static_assert(sycl::is_device_copyable_v<const sycl::span<int>>);
50+
51+
// volatile
52+
static_assert(sycl::is_device_copyable_v<volatile std::pair<int, float>>);
53+
static_assert(
54+
sycl::is_device_copyable_v<volatile std::pair<ACopyable, float>>);
55+
static_assert(
56+
sycl::is_device_copyable_v<volatile std::tuple<int, float, bool>>);
57+
static_assert(
58+
sycl::is_device_copyable_v<volatile std::tuple<ACopyable, float, bool>>);
59+
static_assert(
60+
sycl::is_device_copyable_v<volatile std::variant<int, float, bool>>);
61+
static_assert(sycl::is_device_copyable_v<volatile std::variant<ACopyable>>);
62+
static_assert(sycl::is_device_copyable_v<volatile std::array<int, 513>>);
63+
static_assert(
64+
sycl::is_device_copyable_v<volatile std::array<ACopyable, 513>>);
65+
static_assert(sycl::is_device_copyable_v<volatile std::optional<int>>);
66+
static_assert(sycl::is_device_copyable_v<volatile std::optional<ACopyable>>);
67+
static_assert(sycl::is_device_copyable_v<volatile std::string_view>);
68+
#if __cpp_lib_span >= 202002
69+
static_assert(sycl::is_device_copyable_v<volatile std::span<int>>);
70+
#endif
71+
static_assert(sycl::is_device_copyable_v<volatile sycl::span<int>>);
72+
73+
// const volatile
74+
static_assert(
75+
sycl::is_device_copyable_v<const volatile std::pair<int, float>>);
76+
static_assert(
77+
sycl::is_device_copyable_v<const volatile std::pair<ACopyable, float>>);
78+
static_assert(
79+
sycl::is_device_copyable_v<const volatile std::tuple<int, float, bool>>);
80+
static_assert(sycl::is_device_copyable_v<
81+
const volatile std::tuple<ACopyable, float, bool>>);
82+
static_assert(sycl::is_device_copyable_v<
83+
const volatile std::variant<int, float, bool>>);
84+
static_assert(
85+
sycl::is_device_copyable_v<const volatile std::variant<ACopyable>>);
86+
static_assert(
87+
sycl::is_device_copyable_v<const volatile std::array<int, 513>>);
88+
static_assert(
89+
sycl::is_device_copyable_v<const volatile std::array<ACopyable, 513>>);
90+
static_assert(sycl::is_device_copyable_v<const volatile std::optional<int>>);
91+
static_assert(
92+
sycl::is_device_copyable_v<const volatile std::optional<ACopyable>>);
93+
static_assert(sycl::is_device_copyable_v<const volatile std::string_view>);
94+
#if __cpp_lib_span >= 202002
95+
static_assert(sycl::is_device_copyable_v<const volatile std::span<int>>);
96+
#endif
97+
static_assert(sycl::is_device_copyable_v<const volatile sycl::span<int>>);
98+
99+
return 0;
100+
}

0 commit comments

Comments
 (0)