19 #if defined(__ESIMD_DBG_HOST) && !defined(__SYCL_DEVICE_ONLY__)
20 #define __esimd_dbg_print(a) std::cout << ">>> " << #a << "\n"
22 #define __esimd_dbg_print(a)
23 #endif // defined(__ESIMD_DBG_HOST) && !defined(__SYCL_DEVICE_ONLY__)
28 namespace __ESIMD_NS {
31 template <
typename Ty,
int N>
class simd;
32 template <
typename BaseTy,
typename RegionTy>
class simd_view;
46 std::conditional_t<N == 8, uint64_t, void>>>>;
49 template <
typename Ty,
int N>
class simd_mask_impl;
50 template <
typename RawT,
int N,
class Derived,
class SFINAE =
void>
57 using simd_mask_elem_type =
unsigned short;
58 template <
int N>
using simd_mask_type = simd_mask_impl<simd_mask_elem_type, N>;
64 struct invalid_element_type;
66 template <
class T>
struct is_clang_vector_type : std::false_type {
67 static inline constexpr
int length = 0;
71 template <
class T,
int N>
74 static inline constexpr
int length = N;
75 using element_type =
T;
78 static inline constexpr
bool is_clang_vector_type_v =
79 is_clang_vector_type<T>::value;
84 using remove_cvref_t = csd::remove_cv_t<csd::remove_reference_t<T>>;
87 template <
class...>
struct make_esimd_void {
90 template <
class... Tys>
91 using __esimd_void_t =
typename make_esimd_void<Tys...>::type;
93 template <
class Ty,
class =
void>
94 struct is_esimd_arithmetic_type : std::false_type {};
97 struct is_esimd_arithmetic_type<
99 decltype(std::declval<Ty>() + std::declval<Ty>()),
100 decltype(std::declval<Ty>() - std::declval<Ty>()),
101 decltype(std::declval<Ty>() * std::declval<Ty>()),
102 decltype(std::declval<Ty>() / std::declval<Ty>())>>
105 template <
typename Ty>
106 static inline constexpr
bool is_esimd_arithmetic_type_v =
107 is_esimd_arithmetic_type<Ty>::value;
110 template <
typename Ty>
112 std::true_type, std::false_type> {};
114 template <
typename Ty>
115 static inline constexpr
bool is_vectorizable_v = is_vectorizable<Ty>::value;
117 template <
typename T>
118 static inline constexpr
bool is_esimd_scalar_v =
121 template <
typename T>
122 using is_esimd_scalar =
typename std::bool_constant<is_esimd_scalar_v<T>>;
125 template <
typename Ty,
int N>
struct raw_vector_type {
126 static_assert(!std::is_const<Ty>::value,
"const element type not supported");
127 static_assert(is_vectorizable_v<Ty>,
"element type not supported");
128 static_assert(N > 0,
"zero-element vector not supported");
130 static constexpr
int length = N;
134 template <
typename Ty,
int N>
135 using vector_type_t =
typename raw_vector_type<Ty, N>::type;
139 template <
typename T>
140 struct is_simd_obj_impl_derivative :
public std::false_type {};
143 template <
typename RawT,
int N,
class Derived>
144 struct is_simd_obj_impl_derivative<
simd_obj_impl<RawT, N, Derived>>
145 :
public std::true_type {};
147 template <
class T,
class SFINAE =
void>
struct element_type_traits;
149 using __raw_t =
typename __ESIMD_DNS::element_type_traits<T>::RawT;
151 using __cpp_t =
typename __ESIMD_DNS::element_type_traits<T>::EnclosingCppT;
154 template <
typename T,
int N,
template <
typename,
int>
class Derived>
155 struct is_simd_obj_impl_derivative<Derived<
T, N>>
157 std::is_base_of_v<simd_obj_impl<__raw_t<T>, N, Derived<T, N>>,
159 std::true_type, std::false_type> {};
162 template <
typename T>
163 inline constexpr
bool is_simd_obj_impl_derivative_v =
164 is_simd_obj_impl_derivative<T>::value;
169 template <
class SimdT,
int Ndst>
struct resize_a_simd_type;
172 template <
typename T,
int Nsrc,
int Ndst,
template <
typename,
int>
class SimdT>
173 struct resize_a_simd_type<
simd_obj_impl<__raw_t<
T>, Nsrc, SimdT<
T, Nsrc>>,
179 template <
typename T,
int Nsrc,
int Ndst,
template <
typename,
int>
class SimdT>
180 struct resize_a_simd_type<SimdT<
T, Nsrc>, Ndst> {
181 using type = SimdT<T, Ndst>;
185 template <
class SimdT,
int Ndst>
186 using resize_a_simd_type_t =
typename resize_a_simd_type<SimdT, Ndst>::type;
192 template <
class SimdT,
typename NewElemT>
struct convert_simd_elem_type;
195 template <
typename OldElemT,
int N,
typename NewElemT,
196 template <
typename,
int>
class SimdT>
197 struct convert_simd_elem_type<
198 simd_obj_impl<__raw_t<OldElemT>, N, SimdT<OldElemT, N>>, NewElemT> {
203 template <
typename OldElemT,
int N,
typename NewElemT,
204 template <
typename,
int>
class SimdT>
205 struct convert_simd_elem_type<SimdT<OldElemT, N>, NewElemT> {
206 using type = SimdT<NewElemT, N>;
210 template <
class SimdT,
typename NewElemT>
211 using convert_simd_elem_type_t =
212 typename convert_simd_elem_type<SimdT, NewElemT>::type;
218 template <
class SimdT,
typename T,
int N>
219 using construct_a_simd_type_t =
220 convert_simd_elem_type_t<resize_a_simd_type_t<SimdT, N>,
T>;
226 using simd_mask_storage_t = vector_type_t<simd_mask_elem_type, N>;
230 template <
typename Ty>
struct is_any_simd_view_type : std::false_type {};
232 template <
typename BaseTy,
typename RegionTy>
233 struct is_any_simd_view_type<simd_view<BaseTy, RegionTy>> : std::true_type {};
235 template <
typename Ty>
236 static inline constexpr
bool is_any_simd_view_type_v =
237 is_any_simd_view_type<Ty>::value;
244 template <
typename Ty>
245 static inline constexpr
bool is_simd_like_type_v =
246 is_any_simd_view_type_v<Ty> || is_simd_obj_impl_derivative_v<Ty>;
252 template <
typename Ty>
struct is_simd_type : std::false_type {};
253 template <
typename ElTy,
int N>
254 struct is_simd_type<
simd<ElTy, N>> : std::true_type {};
255 template <
typename Ty>
256 static inline constexpr
bool is_simd_type_v = is_simd_type<Ty>::value;
258 template <
typename Ty>
struct is_simd_mask_type : std::false_type {};
260 struct is_simd_mask_type<simd_mask_impl<simd_mask_elem_type, N>>
262 template <
typename Ty>
263 static inline constexpr
bool is_simd_mask_type_v = is_simd_mask_type<Ty>::value;
268 template <
typename Ty>
struct is_simd_view_type_impl : std::false_type {};
270 template <
class BaseT,
class RegionT>
271 struct is_simd_view_type_impl<simd_view<BaseT, RegionT>>
276 struct is_simd_view_type : is_simd_view_type_impl<remove_cvref_t<Ty>> {};
278 template <
typename Ty>
279 static inline constexpr
bool is_simd_view_type_v = is_simd_view_type<Ty>::value;
282 template <
typename T>
283 static inline constexpr
bool is_simd_or_view_type_v =
284 is_simd_view_type_v<T> || is_simd_type_v<T>;
289 struct cant_deduce_element_type;
291 template <
class T,
class SFINAE =
void>
struct element_type {
292 using type = cant_deduce_element_type;
295 template <
typename T>
297 using type = remove_cvref_t<T>;
300 template <
typename T>
302 using type =
typename T::element_type;
305 template <
typename T>
307 using type =
typename is_clang_vector_type<T>::element_type;
310 template <
typename T>
using element_type_t =
typename element_type<T>::type;
315 template <
class T>
struct simd_like_obj_info {
316 using element_type =
T;
317 static inline constexpr
int vector_length = 0;
320 template <
class T,
int N>
struct simd_like_obj_info<
simd<
T, N>> {
321 using element_type =
T;
322 static inline constexpr
int vector_length = N;
325 template <
class T,
int N>
struct simd_like_obj_info<simd_mask_impl<
T, N>> {
326 using element_type = simd_mask_elem_type;
327 static inline constexpr
int vector_length = N;
330 template <
class BaseT,
class RegionT>
331 struct simd_like_obj_info<simd_view<BaseT, RegionT>> {
332 using element_type =
typename RegionT::element_type;
336 template <
typename T>
337 using get_vector_element_type =
typename simd_like_obj_info<T>::element_type;
339 template <
typename T>
340 static inline constexpr
int get_vector_length =
341 simd_like_obj_info<T>::vector_length;
345 template <
typename To,
typename From>
346 std::enable_if_t<is_clang_vector_type_v<To> && is_clang_vector_type_v<From>, To>
347 ESIMD_INLINE
convert(From Val) {
348 if constexpr (std::is_same_v<To, From>) {
351 return __builtin_convertvector(Val, To);
356 template <
typename U> constexpr
bool is_type() {
return false; }
358 template <
typename U,
typename T,
typename... Ts> constexpr
bool is_type() {
359 using UU =
typename csd::remove_const_t<U>;
360 using TT =
typename csd::remove_const_t<T>;
361 return std::is_same<UU, TT>::value || is_type<UU, Ts...>();
365 template <
typename ToEltTy,
typename FromEltTy,
int FromN,
366 typename = csd::enable_if_t<is_vectorizable<ToEltTy>::value>>
367 struct bitcast_helper {
368 static inline constexpr
int nToElems() {
369 constexpr
int R1 =
sizeof(ToEltTy) /
sizeof(FromEltTy);
370 constexpr
int R2 =
sizeof(FromEltTy) /
sizeof(ToEltTy);
371 constexpr
int ToN = (R2 > 0) ? (FromN * R2) : (FromN / R1);
377 template <
typename ToEltTy,
typename FromEltTy,
int FromN,
378 typename = csd::enable_if_t<is_vectorizable<ToEltTy>::value>>
380 std::is_same<FromEltTy, ToEltTy>::value, vector_type_t<FromEltTy, FromN>,
381 vector_type_t<ToEltTy,
382 bitcast_helper<ToEltTy, FromEltTy, FromN>::nToElems()>>
383 bitcast(vector_type_t<FromEltTy, FromN> Val) {
385 if constexpr (std::is_same<FromEltTy, ToEltTy>::value)
389 constexpr
int ToN = bitcast_helper<ToEltTy, FromEltTy, FromN>::nToElems();
390 using VTy = vector_type_t<ToEltTy, ToN>;
391 return reinterpret_cast<VTy
>(Val);
399 template <
int N>
using mask_type_t = detail::simd_mask_storage_t<N>;