@@ -20,22 +20,28 @@ namespace sycl {
20
20
__SYCL_INLINE_VER_NAMESPACE (_V1) {
21
21
namespace ext ::intel::esimd::detail {
22
22
23
- template <class T >
24
- struct element_type_traits <T, std::enable_if_t <std::is_same_v<T, sycl::half>>> {
25
- // Can't use sycl::detail::half_impl::StorageT as RawT for both host and
26
- // device as it still maps to struct on/ host (even though the struct is a
27
- // trivial wrapper around uint16_t), and for ESIMD we need a type which can be
28
- // an element of clang vector.
23
+ // Standalone definitions to use w/o instantiating element_type_traits.
24
+ #ifdef __SYCL_DEVICE_ONLY__
25
+ // Can't use sycl::detail::half_impl::StorageT as RawT for both host and
26
+ // device as it still maps to struct on/ host (even though the struct is a
27
+ // trivial wrapper around uint16_t), and for ESIMD we need a type which can be
28
+ // an element of clang vector.
29
+ using half_raw_type = sycl::detail::half_impl::StorageT;
30
+ // On device, _Float16 is native Cpp type, so it is the enclosing C++ type
31
+ using half_enclosing_cpp_type = half_raw_type;
32
+ #else
33
+ using half_raw_type = uint16_t ;
34
+ using half_enclosing_cpp_type = float ;
35
+ #endif // __SYCL_DEVICE_ONLY__
36
+
37
+ template <> struct element_type_traits <sycl::half> {
38
+ using RawT = half_raw_type;
39
+ using EnclosingCppT = half_enclosing_cpp_type;
29
40
#ifdef __SYCL_DEVICE_ONLY__
30
- using RawT = sycl::detail::half_impl::StorageT;
31
- // On device, _Float16 is native Cpp type, so it is the enclosing C++ type
32
- using EnclosingCppT = RawT;
33
41
// On device, operations on half are translated to operations on _Float16,
34
42
// which is natively supported by the device compiler
35
43
static inline constexpr bool use_native_cpp_ops = true ;
36
44
#else
37
- using RawT = uint16_t ;
38
- using EnclosingCppT = float ;
39
45
// On host, we can't use native Cpp '+', '-' etc. over uint16_t to emulate the
40
46
// operations on half type.
41
47
static inline constexpr bool use_native_cpp_ops = false ;
@@ -47,8 +53,8 @@ struct element_type_traits<T, std::enable_if_t<std::is_same_v<T, sycl::half>>> {
47
53
// ------------------- Type conversion traits
48
54
49
55
template <int N> struct vector_conversion_traits <sycl::half, N> {
50
- using StdT = __cpp_t <sycl::half> ;
51
- using RawT = __raw_t <sycl::half> ;
56
+ using StdT = half_enclosing_cpp_type ;
57
+ using RawT = half_raw_type ;
52
58
53
59
static ESIMD_INLINE vector_type_t <RawT, N>
54
60
convert_to_raw (vector_type_t <StdT, N> Val)
@@ -57,7 +63,7 @@ template <int N> struct vector_conversion_traits<sycl::half, N> {
57
63
;
58
64
#else
59
65
{
60
- vector_type_t <__raw_t <sycl::half> , N> Output = 0 ;
66
+ vector_type_t <half_raw_type , N> Output = 0 ;
61
67
62
68
for (int i = 0 ; i < N; i += 1 ) {
63
69
// 1. Convert Val[i] to float (x) using c++ static_cast
@@ -89,46 +95,49 @@ template <int N> struct vector_conversion_traits<sycl::half, N> {
89
95
#endif // __SYCL_DEVICE_ONLY__
90
96
};
91
97
92
- // WrapperElementTypeProxy (a friend of sycl::half) must be used to access
93
- // private fields of the sycl::half.
94
- template <>
95
- ESIMD_INLINE __raw_t <sycl::half>
96
- WrapperElementTypeProxy::bitcast_to_raw_scalar<sycl::half>(sycl::half Val) {
98
+ // Proxy class to access bit representation of a wrapper type both on host and
99
+ // device. Declared as friend to the wrapper types (e.g. sycl::half).
100
+ // Specific type traits implementations (scalar_conversion_traits) can use
101
+ // concrete wrapper type specializations of the static functions in this class
102
+ // to access private fields in the wrapper type (e.g. sycl::half).
103
+ // TODO add this functionality to sycl type implementation? With C++20,
104
+ // std::bit_cast should be a good replacement.
105
+ class WrapperElementTypeProxy {
106
+ public:
107
+ static ESIMD_INLINE half_raw_type bitcast_to_raw_scalar (sycl::half Val) {
97
108
#ifdef __SYCL_DEVICE_ONLY__
98
- return Val.Data ;
109
+ return Val.Data ;
99
110
#else
100
- return Val.Data .Buf ;
111
+ return Val.Data .Buf ;
101
112
#endif // __SYCL_DEVICE_ONLY__
102
- }
113
+ }
103
114
104
- template <>
105
- ESIMD_INLINE sycl::half
106
- WrapperElementTypeProxy::bitcast_to_wrapper_scalar<sycl::half>(
107
- __raw_t <sycl::half> Val) {
115
+ static ESIMD_INLINE sycl::half bitcast_to_wrapper_scalar (half_raw_type Val) {
108
116
#ifndef __SYCL_DEVICE_ONLY__
109
- return sycl::half (::sycl::detail::host_half_impl::half (Val));
117
+ return sycl::half (::sycl::detail::host_half_impl::half (Val));
110
118
#else
111
- sycl::half Res;
112
- Res.Data = Val;
113
- return Res;
119
+ sycl::half Res;
120
+ Res.Data = Val;
121
+ return Res;
114
122
#endif // __SYCL_DEVICE_ONLY__
115
- }
123
+ }
124
+ };
116
125
117
126
template <> struct scalar_conversion_traits <sycl::half> {
118
- using RawT = __raw_t <sycl::half> ;
127
+ using RawT = half_raw_type ;
119
128
120
129
static ESIMD_INLINE RawT bitcast_to_raw (sycl::half Val) {
121
- return WrapperElementTypeProxy::bitcast_to_raw_scalar<sycl::half> (Val);
130
+ return WrapperElementTypeProxy::bitcast_to_raw_scalar (Val);
122
131
}
123
132
124
133
static ESIMD_INLINE sycl::half bitcast_to_wrapper (RawT Val) {
125
- return WrapperElementTypeProxy::bitcast_to_wrapper_scalar<sycl::half> (Val);
134
+ return WrapperElementTypeProxy::bitcast_to_wrapper_scalar (Val);
126
135
}
127
136
};
128
137
129
138
#ifdef __SYCL_DEVICE_ONLY__
130
139
template <>
131
- struct is_esimd_arithmetic_type <__raw_t <sycl::half> , void > : std::true_type {};
140
+ struct is_esimd_arithmetic_type <half_raw_type , void > : std::true_type {};
132
141
#endif // __SYCL_DEVICE_ONLY__
133
142
134
143
// Misc
0 commit comments