21 #if defined(__ESIMD_DBG_HOST) && !defined(__SYCL_DEVICE_ONLY__)
22 #define __esimd_dbg_print(a) std::puts(">>> " #a);
24 #define __esimd_dbg_print(a)
25 #endif // defined(__ESIMD_DBG_HOST) && !defined(__SYCL_DEVICE_ONLY__)
30 inline namespace _V1 {
31 namespace ext::intel::esimd {
34 template <
typename Ty,
int N>
class simd;
35 template <
typename BaseTy,
typename RegionTy>
class simd_view;
42 template <
typename Ty,
int N>
class simd_mask_impl;
43 template <
typename RawT,
int N,
class Derived,
class SFINAE =
void>
50 using simd_mask_elem_type =
unsigned short;
51 template <
int N>
using simd_mask_type = simd_mask_impl<simd_mask_elem_type, N>;
54 static inline constexpr
bool is_esimd_scalar_v = std::is_arithmetic_v<T>;
57 using is_esimd_scalar =
typename std::bool_constant<is_esimd_scalar_v<T>>;
62 struct is_simd_obj_impl_derivative :
public std::false_type {};
65 template <
typename RawT,
int N,
class Derived>
66 struct is_simd_obj_impl_derivative<simd_obj_impl<RawT, N, Derived>>
67 :
public std::true_type {};
70 template <
typename T,
int N,
template <
typename,
int>
class Derived>
71 struct is_simd_obj_impl_derivative<Derived<T, N>>
72 :
public std::conditional_t<
73 std::is_base_of_v<simd_obj_impl<__raw_t<T>, N, Derived<T, N>>,
75 std::true_type, std::false_type> {};
79 inline constexpr
bool is_simd_obj_impl_derivative_v =
80 is_simd_obj_impl_derivative<T>::value;
85 template <
class SimdT,
int Ndst>
struct resize_a_simd_type;
88 template <
typename T,
int Nsrc,
int Ndst,
template <
typename,
int>
class SimdT>
89 struct resize_a_simd_type<simd_obj_impl<__raw_t<T>, Nsrc, SimdT<T, Nsrc>>,
91 using type = simd_obj_impl<__raw_t<T>, Ndst, SimdT<T, Ndst>>;
95 template <
typename T,
int Nsrc,
int Ndst,
template <
typename,
int>
class SimdT>
96 struct resize_a_simd_type<SimdT<T, Nsrc>, Ndst> {
97 using type = SimdT<T, Ndst>;
101 template <
class SimdT,
int Ndst>
102 using resize_a_simd_type_t =
typename resize_a_simd_type<SimdT, Ndst>::type;
108 template <
class SimdT,
typename NewElemT>
struct convert_simd_elem_type;
111 template <
typename OldElemT,
int N,
typename NewElemT,
112 template <
typename,
int>
class SimdT>
113 struct convert_simd_elem_type<
114 simd_obj_impl<__raw_t<OldElemT>, N, SimdT<OldElemT, N>>, NewElemT> {
115 using type = simd_obj_impl<__raw_t<NewElemT>, N, SimdT<NewElemT, N>>;
119 template <
typename OldElemT,
int N,
typename NewElemT,
120 template <
typename,
int>
class SimdT>
121 struct convert_simd_elem_type<SimdT<OldElemT, N>, NewElemT> {
122 using type = SimdT<NewElemT, N>;
126 template <
class SimdT,
typename NewElemT>
127 using convert_simd_elem_type_t =
128 typename convert_simd_elem_type<SimdT, NewElemT>::type;
134 template <
class SimdT,
typename T,
int N>
135 using construct_a_simd_type_t =
136 convert_simd_elem_type_t<resize_a_simd_type_t<SimdT, N>, T>;
142 using simd_mask_storage_t = vector_type_t<simd_mask_elem_type, N>;
146 template <
typename Ty>
struct is_any_simd_view_type : std::false_type {};
148 template <
typename BaseTy,
typename RegionTy>
149 struct is_any_simd_view_type<simd_view<BaseTy, RegionTy>> : std::true_type {};
151 template <
typename Ty>
152 static inline constexpr
bool is_any_simd_view_type_v =
153 is_any_simd_view_type<Ty>::value;
160 template <
typename Ty>
161 static inline constexpr
bool is_simd_like_type_v =
162 is_any_simd_view_type_v<Ty> || is_simd_obj_impl_derivative_v<Ty>;
168 template <
typename Ty>
struct is_simd_type : std::false_type {};
169 template <
typename ElTy,
int N>
170 struct is_simd_type<
simd<ElTy, N>> : std::true_type {};
171 template <
typename Ty>
172 static inline constexpr
bool is_simd_type_v = is_simd_type<Ty>::value;
174 template <
typename Ty>
struct is_simd_mask_type : std::false_type {};
176 struct is_simd_mask_type<simd_mask_impl<simd_mask_elem_type, N>>
178 template <
typename Ty>
179 static inline constexpr
bool is_simd_mask_type_v = is_simd_mask_type<Ty>::value;
184 template <
typename Ty>
struct is_simd_view_type_impl : std::false_type {};
186 template <
class BaseT,
class RegionT>
187 struct is_simd_view_type_impl<simd_view<BaseT, RegionT>>
188 : std::conditional_t<is_simd_type_v<BaseT>, std::true_type,
192 struct is_simd_view_type : is_simd_view_type_impl<remove_cvref_t<Ty>> {};
194 template <
typename Ty>
195 static inline constexpr
bool is_simd_view_type_v = is_simd_view_type<Ty>::value;
198 template <
typename T>
199 static inline constexpr
bool is_simd_or_view_type_v =
200 is_simd_view_type_v<T> || is_simd_type_v<T>;
205 struct cant_deduce_element_type;
207 template <
class T,
class SFINAE =
void>
struct element_type {
208 using type = cant_deduce_element_type;
211 template <
typename T>
213 using type = remove_cvref_t<T>;
216 template <
typename T>
221 template <
typename T>
226 template <
typename T>
using element_type_t =
typename element_type<T>::type;
231 template <
class T>
struct simd_like_obj_info {
233 static constexpr
int vector_length = 0;
236 template <
class T,
int N>
struct simd_like_obj_info<
simd<T, N>> {
238 static constexpr
int vector_length = N;
241 template <
class T,
int N>
struct simd_like_obj_info<simd_mask_impl<T, N>> {
243 static constexpr
int vector_length = N;
246 template <
class BaseT,
class RegionT>
247 struct simd_like_obj_info<simd_view<BaseT, RegionT>> {
249 static constexpr
int vector_length = RegionT::length;
252 template <
typename T>
255 template <
typename T>
256 static inline constexpr
int get_vector_length =
257 simd_like_obj_info<T>::vector_length;
261 template <
typename To,
typename From>
262 std::enable_if_t<is_clang_vector_type_v<To> && is_clang_vector_type_v<From>, To>
263 ESIMD_INLINE
convert(From Val) {
264 if constexpr (std::is_same_v<To, From>) {
267 return __builtin_convertvector(Val, To);
272 template <
typename ToEltTy,
typename FromEltTy,
int FromN,
273 typename = std::enable_if_t<is_vectorizable<ToEltTy>::value>>
274 struct bitcast_helper {
275 static constexpr
int nToElems() {
276 constexpr
int R1 =
sizeof(ToEltTy) /
sizeof(FromEltTy);
277 constexpr
int R2 =
sizeof(FromEltTy) /
sizeof(ToEltTy);
278 constexpr
int ToN = (R2 > 0) ? (FromN * R2) : (FromN / R1);
284 template <
typename ToEltTy,
typename FromEltTy,
int FromN,
285 typename = std::enable_if_t<is_vectorizable<ToEltTy>::value>>
286 ESIMD_INLINE
typename std::conditional_t<
287 std::is_same_v<FromEltTy, ToEltTy>, vector_type_t<FromEltTy, FromN>,
288 vector_type_t<ToEltTy,
289 bitcast_helper<ToEltTy, FromEltTy, FromN>::nToElems()>>
290 bitcast(vector_type_t<FromEltTy, FromN> Val) {
292 if constexpr (std::is_same_v<FromEltTy, ToEltTy>)
296 constexpr
int ToN = bitcast_helper<ToEltTy, FromEltTy, FromN>::nToElems();
297 using VTy = vector_type_t<ToEltTy, ToN>;
298 return reinterpret_cast<VTy
>(Val);
310 struct invalid_computation_type;
312 template <
class T1,
class T2,
class SFINAE =
void>
struct computation_type {
313 using type = invalid_computation_type;
316 template <
class T1,
class T2>
317 struct computation_type<T1, T2,
318 std::enable_if_t<is_valid_simd_elem_type_v<T1> &&
319 is_valid_simd_elem_type_v<T2>>> {
321 template <
class T>
using tr = element_type_traits<T>;
324 std::conditional_t<tr<T>::use_native_cpp_ops,
typename tr<T>::RawT,
325 typename tr<T>::EnclosingCppT>;
326 static constexpr
bool is_wr1 = is_wrapper_elem_type_v<T1>;
327 static constexpr
bool is_wr2 = is_wrapper_elem_type_v<T2>;
328 static constexpr
bool is_fp1 = is_generic_floating_point_v<T1>;
329 static constexpr
bool is_fp2 = is_generic_floating_point_v<T2>;
332 using type = std::conditional_t<
335 decltype(std::declval<T1>() + std::declval<T2>()),
337 std::is_same_v<T1, T2>,
340 std::conditional_t<is_fp1 != is_fp2,
344 std::conditional_t<is_fp1, T1, T2>,
348 decltype(std::declval<native_t<T1>>() +
349 std::declval<native_t<T2>>())>>>;
352 template <
class T1,
class T2>
353 struct computation_type<
355 std::enable_if_t<is_simd_like_type_v<T1> || is_simd_like_type_v<T2>>> {
357 using Ty1 = element_type_t<T1>;
358 using Ty2 = element_type_t<T2>;
359 using EltTy =
typename computation_type<Ty1, Ty2>::type;
361 static constexpr
int N1 = [] {
362 if constexpr (is_simd_like_type_v<T1>) {
368 static constexpr
int N2 = [] {
369 if constexpr (is_simd_like_type_v<T2>) {
375 static_assert((N1 == N2) || (N1 == 0) || (N2 == 0),
"size mismatch");
376 static constexpr
int N = N1 ? N1 : N2;
382 template <
class T1,
class T2 = T1>
383 using computation_type_t =
384 typename computation_type<remove_cvref_t<T1>, remove_cvref_t<T2>>::type;
391 template <
int N>
using mask_type_t = detail::simd_mask_storage_t<N>;