Skip to content

Commit 7868596

Browse files
authored
[SYCL] Change vec::operator! to match SYCL spec (#11750)
Table 143 of the SYCL 2020 specification states that the return for the `!` operator can be a different vector type. This change implements the interface described in the specification. Fixes #11659. --------- Signed-off-by: Michael Aziz <[email protected]>
1 parent 457f94f commit 7868596

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

sycl/include/sycl/types.hpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,10 +1179,22 @@ template <typename Type, int NumElements> class vec {
11791179
return Ret;
11801180
}
11811181

1182+
template <typename T>
1183+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
1184+
using OpNotRet = detail::rel_t<T>;
1185+
#else
1186+
using OpNotRet = T;
1187+
#endif // __INTEL_PREVIEW_BREAKING_CHANGES
1188+
11821189
// operator!
11831190
template <typename T = DataT, int N = NumElements>
1184-
EnableIfNotUsingArray<vec<T, N>> operator!() const {
1185-
return vec<T, N>{(typename vec<DataT, NumElements>::DataType) !m_Data};
1191+
EnableIfNotUsingArray<vec<OpNotRet<T>, N>> operator!() const {
1192+
return vec<T, N>{(typename vec<DataT, NumElements>::DataType) !m_Data}
1193+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
1194+
.template as<vec<OpNotRet<T>, N>>();
1195+
#else
1196+
;
1197+
#endif // __INTEL_PREVIEW_BREAKING_CHANGES
11861198
}
11871199

11881200
// std::byte neither supports ! unary op or casting, so special handling is
@@ -1191,32 +1203,44 @@ template <typename Type, int NumElements> class vec {
11911203
template <typename T = DataT, int N = NumElements>
11921204
typename std::enable_if_t<std::is_same_v<std::byte, T> &&
11931205
(IsUsingArrayOnDevice || IsUsingArrayOnHost),
1194-
vec<T, N>>
1206+
vec<OpNotRet<T>, N>>
11951207
operator!() const {
11961208
vec Ret{};
11971209
for (size_t I = 0; I < NumElements; ++I) {
11981210
Ret.setValue(I, std::byte{!vec_data<DataT>::get(getValue(I))});
11991211
}
1212+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
1213+
return Ret.template as<vec<OpNotRet<T>, N>>();
1214+
#else
12001215
return Ret;
1216+
#endif // __INTEL_PREVIEW_BREAKING_CHANGES
12011217
}
12021218

12031219
template <typename T = DataT, int N = NumElements>
12041220
typename std::enable_if_t<!std::is_same_v<std::byte, T> &&
12051221
(IsUsingArrayOnDevice || IsUsingArrayOnHost),
1206-
vec<T, N>>
1222+
vec<OpNotRet<T>, N>>
12071223
operator!() const {
12081224
vec Ret{};
12091225
for (size_t I = 0; I < NumElements; ++I)
12101226
Ret.setValue(I, !vec_data<DataT>::get(getValue(I)));
1227+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
1228+
return Ret.template as<vec<OpNotRet<T>, N>>();
1229+
#else
12111230
return Ret;
1231+
#endif // __INTEL_PREVIEW_BREAKING_CHANGES
12121232
}
12131233
#else
12141234
template <typename T = DataT, int N = NumElements>
1215-
EnableIfUsingArray<vec<T, N>> operator!() const {
1235+
EnableIfUsingArray<vec<OpNotRet<T>, N>> operator!() const {
12161236
vec Ret{};
12171237
for (size_t I = 0; I < NumElements; ++I)
12181238
Ret.setValue(I, !vec_data<DataT>::get(getValue(I)));
1239+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
1240+
return Ret.template as<vec<OpNotRet<T>, N>>();
1241+
#else
12191242
return Ret;
1243+
#endif // __INTEL_PREVIEW_BREAKING_CHANGES
12201244
}
12211245
#endif
12221246

sycl/test/basic_tests/types.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ std::string vec2string(const sycl::vec<vecType, numOfElems> &vec) {
126126
return str;
127127
}
128128

129+
// vec::operator! might return a different type as described in Table 143 of the
130+
// SYCL 2020 specification. This function checks that the result type matches
131+
// the expected type.
132+
template <typename T, typename Expected> inline void checkVecNotReturnType() {
133+
constexpr int N = 4;
134+
using Vector = sycl::vec<T, N>;
135+
#if defined(__INTEL_PREVIEW_BREAKING_CHANGES)
136+
using ExpectedVector = sycl::vec<Expected, N>;
137+
#else
138+
using ExpectedVector = sycl::vec<T, N>;
139+
#endif
140+
using OpNotResult = decltype(std::declval<Vector>().operator!());
141+
static_assert(std::is_same_v<OpNotResult, ExpectedVector>,
142+
"Incorrect vec::operator! return type");
143+
}
144+
129145
// the math built-in testing ensures that the vec binary ops get tested,
130146
// but the unary ops are only tested by the CTS tests. Here we do some
131147
// basic testing of the unary ops, ensuring they compile correctly.
@@ -145,8 +161,21 @@ template <typename T> void checkVecUnaryOps(T &v) {
145161
std::cout << vec2string(g) << std::endl;
146162
}
147163

148-
T f = !v;
164+
auto f = !v;
149165
std::cout << vec2string(f) << std::endl;
166+
167+
// Check operator! return type
168+
checkVecNotReturnType<int8_t, int8_t>();
169+
checkVecNotReturnType<uint8_t, int8_t>();
170+
checkVecNotReturnType<int16_t, int16_t>();
171+
checkVecNotReturnType<uint16_t, int16_t>();
172+
checkVecNotReturnType<sycl::half, int16_t>();
173+
checkVecNotReturnType<int32_t, int32_t>();
174+
checkVecNotReturnType<uint32_t, int32_t>();
175+
checkVecNotReturnType<float, int32_t>();
176+
checkVecNotReturnType<int64_t, int64_t>();
177+
checkVecNotReturnType<uint64_t, int64_t>();
178+
checkVecNotReturnType<double, int64_t>();
150179
}
151180

152181
void checkVariousVecUnaryOps() {

0 commit comments

Comments
 (0)