Skip to content

Commit 63ab1cb

Browse files
[SYCL] Re-implement swizzles from scratch (#17817)
* Removes expression trees support * Applies all previous vec fixes to align with recent spec changes
1 parent 5d1dedd commit 63ab1cb

File tree

7 files changed

+439
-29
lines changed

7 files changed

+439
-29
lines changed

sycl/include/sycl/detail/type_traits.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ template <class T> struct is_fixed_size_group : std::false_type {};
2424

2525
template <class T>
2626
inline constexpr bool is_fixed_size_group_v = is_fixed_size_group<T>::value;
27-
28-
template <typename VecT, typename OperationLeftT, typename OperationRightT,
29-
template <typename> class OperationCurrentT, int... Indexes>
30-
class SwizzleOp;
3127
} // namespace detail
3228

3329
template <int Dimensions> class group;
@@ -154,12 +150,20 @@ template <typename T, size_t N> struct get_elem_type_unqual<marray<T, N>> {
154150
template <typename T, int N> struct get_elem_type_unqual<vec<T, N>> {
155151
using type = T;
156152
};
153+
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
157154
template <typename VecT, typename OperationLeftT, typename OperationRightT,
158155
template <typename> class OperationCurrentT, int... Indexes>
159156
struct get_elem_type_unqual<SwizzleOp<VecT, OperationLeftT, OperationRightT,
160157
OperationCurrentT, Indexes...>> {
161158
using type = typename get_elem_type_unqual<std::remove_cv_t<VecT>>::type;
162159
};
160+
#else
161+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
162+
struct get_elem_type_unqual<detail::hide_swizzle_from_adl::Swizzle<
163+
IsConstVec, DataT, VecSize, Indexes...>> {
164+
using type = DataT;
165+
};
166+
#endif
163167

164168
template <typename ElementType, access::address_space Space,
165169
access::decorated DecorateAddress>

sycl/include/sycl/detail/type_traits/vec_marray_traits.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,37 @@ template <typename DataT, int NumElements> class __SYCL_EBO vec;
3232
template <typename DataT, std::size_t N> class marray;
3333

3434
namespace detail {
35+
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
3536
template <typename VecT, typename OperationLeftT, typename OperationRightT,
3637
template <typename> class OperationCurrentT, int... Indexes>
3738
class SwizzleOp;
39+
#else
40+
namespace hide_swizzle_from_adl {
41+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
42+
class __SYCL_EBO Swizzle;
43+
}
44+
#endif
3845

3946
// Utility for converting a swizzle to a vector or preserve the type if it isn't
4047
// a swizzle.
4148
template <typename T> struct simplify_if_swizzle {
4249
using type = T;
4350
};
4451

52+
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
4553
template <typename VecT, typename OperationLeftT, typename OperationRightT,
4654
template <typename> class OperationCurrentT, int... Indexes>
4755
struct simplify_if_swizzle<SwizzleOp<VecT, OperationLeftT, OperationRightT,
4856
OperationCurrentT, Indexes...>> {
4957
using type = vec<typename VecT::element_type, sizeof...(Indexes)>;
5058
};
59+
#else
60+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
61+
struct simplify_if_swizzle<detail::hide_swizzle_from_adl::Swizzle<
62+
IsConstVec, DataT, VecSize, Indexes...>> {
63+
using type = vec<DataT, sizeof...(Indexes)>;
64+
};
65+
#endif
5166

5267
template <typename T>
5368
using simplify_if_swizzle_t = typename simplify_if_swizzle<T>::type;
@@ -79,10 +94,17 @@ inline constexpr bool is_valid_type_for_ext_vector_v =
7994
is_valid_type_for_ext_vector<T>::value;
8095

8196
template <typename> struct is_swizzle : std::false_type {};
97+
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
8298
template <typename VecT, typename OperationLeftT, typename OperationRightT,
8399
template <typename> class OperationCurrentT, int... Indexes>
84100
struct is_swizzle<SwizzleOp<VecT, OperationLeftT, OperationRightT,
85101
OperationCurrentT, Indexes...>> : std::true_type {};
102+
#else
103+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
104+
struct is_swizzle<detail::hide_swizzle_from_adl::Swizzle<IsConstVec, DataT,
105+
VecSize, Indexes...>>
106+
: std::true_type {};
107+
#endif
86108
template <typename T> constexpr bool is_swizzle_v = is_swizzle<T>::value;
87109

88110
template <typename T>
@@ -108,11 +130,18 @@ struct num_elements<T __attribute__((ext_vector_type(N)))>
108130
: std::integral_constant<std::size_t, N> {};
109131
#endif
110132
#endif
133+
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
111134
template <typename VecT, typename OperationLeftT, typename OperationRightT,
112135
template <typename> class OperationCurrentT, int... Indexes>
113136
struct num_elements<SwizzleOp<VecT, OperationLeftT, OperationRightT,
114137
OperationCurrentT, Indexes...>>
115138
: std::integral_constant<std::size_t, sizeof...(Indexes)> {};
139+
#else
140+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
141+
struct num_elements<detail::hide_swizzle_from_adl::Swizzle<IsConstVec, DataT,
142+
VecSize, Indexes...>>
143+
: std::integral_constant<std::size_t, sizeof...(Indexes)> {};
144+
#endif
116145

117146
template <typename T>
118147
inline constexpr std::size_t num_elements_v = num_elements<T>::value;

sycl/include/sycl/detail/vector_arith.hpp

Lines changed: 193 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616

1717
namespace sycl {
1818
inline namespace _V1 {
19-
20-
template <typename DataT, int NumElem> class __SYCL_EBO vec;
21-
2219
namespace detail {
23-
2420
template <typename T> struct from_incomplete;
2521
template <typename T>
2622
struct from_incomplete<const T> : public from_incomplete<T> {};
@@ -31,6 +27,33 @@ struct from_incomplete<vec<DataT, NumElements>> {
3127
static constexpr size_t size() { return NumElements; }
3228
};
3329

30+
#if !__SYCL_USE_LIBSYCL8_VEC_IMPL
31+
template <bool IsConstVec, typename DataT, int VecSize, int... Indexes>
32+
struct from_incomplete<
33+
hide_swizzle_from_adl::Swizzle<IsConstVec, DataT, VecSize, Indexes...>> {
34+
using element_type = DataT;
35+
static constexpr size_t size() { return sizeof...(Indexes); }
36+
37+
using vec_ty = std::conditional_t<IsConstVec, const vec<DataT, VecSize>,
38+
vec<DataT, VecSize>>;
39+
using result_vec_ty = vec<DataT, size()>;
40+
static constexpr int vec_size = VecSize;
41+
static constexpr bool is_over_const_vec = IsConstVec;
42+
static constexpr bool has_repeating_indexes = []() constexpr {
43+
int Idxs[] = {Indexes...};
44+
for (std::size_t i = 1; i < sizeof...(Indexes); ++i) {
45+
for (std::size_t j = 0; j < i; ++j)
46+
if (Idxs[j] == Idxs[i])
47+
// Repeating index
48+
return true;
49+
}
50+
51+
return false;
52+
}();
53+
static constexpr bool is_assignable = !IsConstVec && !has_repeating_indexes;
54+
};
55+
#endif
56+
3457
template <bool Cond, typename Mixin> struct ApplyIf {};
3558
template <typename Mixin> struct ApplyIf<true, Mixin> : Mixin {};
3659

@@ -477,6 +500,172 @@ template <typename Self> struct VecOperators {
477500
OpAssign<ShiftRight>, IncDec> {};
478501
};
479502

503+
#if !__SYCL_USE_LIBSYCL8_VEC_IMPL
504+
template <typename Self> struct SwizzleOperators {
505+
using element_type = typename from_incomplete<Self>::element_type;
506+
using vec_ty = typename from_incomplete<Self>::result_vec_ty;
507+
static constexpr int N = from_incomplete<Self>::size();
508+
509+
template <typename T>
510+
static constexpr bool is_compatible_scalar =
511+
std::is_convertible_v<T, typename from_incomplete<Self>::element_type> &&
512+
!is_swizzle_v<T>;
513+
514+
// Can't use partial specialization on constexpr variables because it took too
515+
// long for gcc to fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71954 and
516+
// we need to support older versions without the fix.
517+
template <typename OtherSwizzle, typename = void>
518+
struct is_compatible_swizzle_impl : std::false_type {};
519+
520+
template <typename OtherSwizzle>
521+
struct is_compatible_swizzle_impl<
522+
OtherSwizzle, std::enable_if_t<is_swizzle_v<OtherSwizzle>>>
523+
: std::bool_constant<
524+
std::is_same_v<typename from_incomplete<OtherSwizzle>::element_type,
525+
typename from_incomplete<Self>::element_type> &&
526+
from_incomplete<OtherSwizzle>::size() ==
527+
from_incomplete<Self>::size()> {};
528+
529+
template <typename OtherSwizzle>
530+
static constexpr bool is_compatible_swizzle =
531+
is_compatible_swizzle_impl<OtherSwizzle>::value;
532+
533+
template <typename OtherSwizzle, typename = void>
534+
struct is_compatible_swizzle_opposite_const_impl : std::false_type {};
535+
536+
template <typename OtherSwizzle>
537+
struct is_compatible_swizzle_opposite_const_impl<
538+
OtherSwizzle, std::enable_if_t<is_swizzle_v<OtherSwizzle>>>
539+
: std::bool_constant<is_compatible_swizzle<OtherSwizzle> &&
540+
from_incomplete<OtherSwizzle>::is_over_const_vec !=
541+
from_incomplete<Self>::is_over_const_vec> {};
542+
543+
template <typename OtherSwizzle>
544+
static constexpr bool is_compatible_swizzle_opposite_const =
545+
is_compatible_swizzle_opposite_const_impl<OtherSwizzle>::value;
546+
547+
template <typename Op>
548+
using result_t = std::conditional_t<
549+
is_logical<Op>, vec<fixed_width_signed<sizeof(element_type)>, N>, vec_ty>;
550+
551+
// Uglier than possible due to
552+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282.
553+
template <typename Op, typename = void> struct OpMixin;
554+
555+
template <typename Op>
556+
struct OpMixin<Op, std::enable_if_t<std::is_same_v<Op, IncDec>>>
557+
: public IncDecImpl<const Self> {};
558+
559+
#define __SYCL_SWIZZLE_BINOP_MIXIN(OP, OPERATOR) \
560+
template <typename Op> \
561+
struct OpMixin<Op, std::enable_if_t<std::is_same_v<Op, OP>>> { \
562+
friend result_t<OP> operator OPERATOR(const Self & lhs, \
563+
const vec_ty & rhs) { \
564+
return OP{}(vec_ty{lhs}, rhs); \
565+
} \
566+
friend result_t<OP> operator OPERATOR(const vec_ty & lhs, \
567+
const Self & rhs) { \
568+
return OP{}(lhs, vec_ty{rhs}); \
569+
} \
570+
template <typename T> \
571+
friend std::enable_if_t<is_compatible_scalar<T>, result_t<OP>> \
572+
operator OPERATOR(const Self & lhs, const T & rhs) { \
573+
return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
574+
} \
575+
template <typename T> \
576+
friend std::enable_if_t<is_compatible_scalar<T>, result_t<OP>> \
577+
operator OPERATOR(const T & lhs, const Self & rhs) { \
578+
return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
579+
} \
580+
template <typename OtherSwizzle> \
581+
friend std::enable_if_t<is_compatible_swizzle<OtherSwizzle>, result_t<OP>> \
582+
operator OPERATOR(const Self & lhs, const OtherSwizzle & rhs) { \
583+
return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
584+
} \
585+
template <typename OtherSwizzle> \
586+
friend std::enable_if_t< \
587+
is_compatible_swizzle_opposite_const<OtherSwizzle>, result_t<OP>> \
588+
operator OPERATOR(const OtherSwizzle & lhs, const Self & rhs) { \
589+
return OP{}(vec_ty{lhs}, vec_ty{rhs}); \
590+
} \
591+
};
592+
593+
#define __SYCL_SWIZZLE_OPASSIGN_MIXIN(OP, OPERATOR) \
594+
template <typename Op> \
595+
struct OpMixin<OpAssign<Op>, std::enable_if_t<std::is_same_v<Op, OP>>> { \
596+
friend const Self &operator OPERATOR(const Self & lhs, \
597+
const vec_ty & rhs) { \
598+
lhs = OP{}(vec_ty{lhs}, rhs); \
599+
return lhs; \
600+
} \
601+
template <typename T> \
602+
friend std::enable_if_t<is_compatible_scalar<T>, const Self &> \
603+
operator OPERATOR(const Self & lhs, const T & rhs) { \
604+
lhs = OP{}(vec_ty{lhs}, vec_ty{rhs}); \
605+
return lhs; \
606+
} \
607+
template <typename OtherSwizzle> \
608+
friend std::enable_if_t<is_compatible_swizzle<OtherSwizzle>, const Self &> \
609+
operator OPERATOR(const Self & lhs, const OtherSwizzle & rhs) { \
610+
lhs = OP{}(vec_ty{lhs}, vec_ty{rhs}); \
611+
return lhs; \
612+
} \
613+
};
614+
615+
#define __SYCL_SWIZZLE_UOP_MIXIN(OP, OPERATOR) \
616+
template <typename Op> \
617+
struct OpMixin<Op, std::enable_if_t<std::is_same_v<Op, OP>>> { \
618+
friend result_t<OP> operator OPERATOR(const Self & v) { \
619+
return OP{}(vec_ty{v}); \
620+
} \
621+
};
622+
623+
__SYCL_INSTANTIATE_OPERATORS(__SYCL_SWIZZLE_BINOP_MIXIN,
624+
__SYCL_SWIZZLE_OPASSIGN_MIXIN,
625+
__SYCL_SWIZZLE_UOP_MIXIN)
626+
627+
#undef __SYCL_SWIZZLE_UOP_MIXIN
628+
#undef __SYCL_SWIZZLE_OPASSIGN_MIXIN
629+
#undef __SYCL_SWIZZLE_BINOP_MIXIN
630+
631+
template <typename... Op>
632+
struct __SYCL_EBO CombineImpl
633+
: ApplyIf<is_op_available_for_type<Op, element_type>, OpMixin<Op>>... {};
634+
635+
template <typename _Self, typename = void>
636+
struct CombinedImpl
637+
: CombineImpl<std::plus<void>, std::minus<void>, std::multiplies<void>,
638+
std::divides<void>, std::modulus<void>, std::bit_and<void>,
639+
std::bit_or<void>, std::bit_xor<void>, std::equal_to<void>,
640+
std::not_equal_to<void>, std::less<void>,
641+
std::greater<void>, std::less_equal<void>,
642+
std::greater_equal<void>, std::logical_and<void>,
643+
std::logical_or<void>, ShiftLeft, ShiftRight,
644+
std::negate<void>, std::logical_not<void>,
645+
std::bit_not<void>, UnaryPlus> {};
646+
647+
template <typename _Self>
648+
struct CombinedImpl<_Self,
649+
std::enable_if_t<from_incomplete<_Self>::is_assignable>>
650+
: CombineImpl<std::plus<void>, std::minus<void>, std::multiplies<void>,
651+
std::divides<void>, std::modulus<void>, std::bit_and<void>,
652+
std::bit_or<void>, std::bit_xor<void>, std::equal_to<void>,
653+
std::not_equal_to<void>, std::less<void>,
654+
std::greater<void>, std::less_equal<void>,
655+
std::greater_equal<void>, std::logical_and<void>,
656+
std::logical_or<void>, ShiftLeft, ShiftRight,
657+
std::negate<void>, std::logical_not<void>,
658+
std::bit_not<void>, UnaryPlus, OpAssign<std::plus<void>>,
659+
OpAssign<std::minus<void>>, OpAssign<std::multiplies<void>>,
660+
OpAssign<std::divides<void>>, OpAssign<std::modulus<void>>,
661+
OpAssign<std::bit_and<void>>, OpAssign<std::bit_or<void>>,
662+
OpAssign<std::bit_xor<void>>, OpAssign<ShiftLeft>,
663+
OpAssign<ShiftRight>, IncDec> {};
664+
665+
using Combined = CombinedImpl<Self>;
666+
};
667+
#endif
668+
480669
#if __SYCL_USE_LIBSYCL8_VEC_IMPL
481670
template <typename DataT, int NumElements>
482671
class vec_arith : public VecOperators<vec<DataT, NumElements>>::Combined {};

0 commit comments

Comments
 (0)