Skip to content

Commit dc6c737

Browse files
[SYCL] Fix bitselect builtin for integer types
This regressed after intel#11956 as return type wasn't correctly converted from SPIR-V intrinsic back to SYCL types. This PR fixes that. In addition, I'm also adding tests for `sycl::select` builtin that was left unaffected only because we couldn't use SPIR-V intrinsic for its implementation.
1 parent d3d6e78 commit dc6c737

File tree

4 files changed

+185
-2
lines changed

4 files changed

+185
-2
lines changed

sycl/include/sycl/detail/builtins/relational_functions.inc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,12 @@ BUILTIN_REL(ONE_ARG, signbit, __spirv_SignBitSet)
118118
#undef BUILTIN_REL
119119

120120
#ifdef __SYCL_DEVICE_ONLY__
121-
DEVICE_IMPL_TEMPLATE(THREE_ARGS, bitselect, builtin_enable_generic_t,
122-
__spirv_ocl_bitselect)
121+
DEVICE_IMPL_TEMPLATE(
122+
THREE_ARGS, bitselect, builtin_enable_generic_t, [](auto... xs) {
123+
using ret_ty = detail::builtin_enable_generic_t<THREE_ARGS_TEMPLATE_TYPE>;
124+
using detail::builtins::convert_result;
125+
return convert_result<ret_ty>(__spirv_ocl_bitselect(xs...));
126+
})
123127
#else
124128
HOST_IMPL_TEMPLATE(THREE_ARGS, bitselect, builtin_enable_generic_t, rel,
125129
default_ret_type)

sycl/test-e2e/Basic/built-ins/marray_relational.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,61 @@ int main() {
111111
TEST2(sycl::any, int, EXPECTED(bool, false), 3, ma7);
112112
TEST(sycl::bitselect, float, EXPECTED(float, 1.0, 1.0), 2, ma8, ma9, ma10);
113113
TEST(sycl::select, float, EXPECTED(float, 1.0, 2.0, 8.0), 3, ma5, ma6, c);
114+
{
115+
// Extra tests for select/bitselect due to special handling required for
116+
// integer return types.
117+
118+
auto Test = [&](auto F, auto Expected, auto... Args) {
119+
std::tuple ArgsTuple{Args...};
120+
auto Result = std::apply(F, ArgsTuple);
121+
static_assert(std::is_same_v<decltype(Expected), decltype(Result)>);
122+
123+
// Note: operator==(vec, vec) return vec.
124+
auto Equal = [](auto x, auto y) {
125+
return std::equal(x.begin(), x.end(), y.begin());
126+
};
127+
128+
assert(Equal(Result, Expected));
129+
130+
sycl::buffer<bool, 1> ResultBuf{1};
131+
deviceQueue.submit([&](sycl::handler &cgh) {
132+
sycl::accessor Result{ResultBuf, cgh};
133+
cgh.single_task([=]() {
134+
auto R = std::apply(F, ArgsTuple);
135+
static_assert(std::is_same_v<decltype(Expected), decltype(R)>);
136+
Result[0] = Equal(R, Expected);
137+
});
138+
});
139+
assert(sycl::host_accessor{ResultBuf}[0]);
140+
};
141+
142+
sycl::marray<char, 2> a{0b1100, 0b0011};
143+
sycl::marray<char, 2> b{0b0011, 0b1100};
144+
sycl::marray<char, 2> c{0b1010, 0b1010};
145+
sycl::marray<char, 2> r{0b0110, 0b1001};
146+
147+
auto BitSelect = [](auto... xs) { return sycl::bitselect(xs...); };
148+
Test(BitSelect, r, a, b, c);
149+
// Input values/results above are positive, so use the same values for
150+
// signed/unsigned char tests.
151+
[&](auto... xs) {
152+
Test(BitSelect, sycl::marray<signed char, 2>{xs}...);
153+
}(r, a, b, c);
154+
[&](auto... xs) {
155+
Test(BitSelect, sycl::marray<unsigned char, 2>{xs}...);
156+
}(r, a, b, c);
157+
158+
auto Select = [](auto... xs) { return sycl::select(xs...); };
159+
sycl::marray<bool, 2> c2{false, true};
160+
sycl::marray<char, 2> r2{a[0], b[1]};
161+
Test(Select, r2, a, b, c2);
162+
[&](auto... xs) {
163+
Test(Select, sycl::marray<signed char, 2>{xs}..., c2);
164+
}(r2, a, b);
165+
[&](auto... xs) {
166+
Test(Select, sycl::marray<unsigned char, 2>{xs}..., c2);
167+
}(r2, a, b);
168+
}
114169

115170
return 0;
116171
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
// RUN: %if preview-breaking-changes-supported %{ %{build} -fpreview-breaking-changes -o %t_preview.out %}
4+
// RUN: %if preview-breaking-changes-supported %{ %{run} %t_preview.out%}
5+
6+
#include <sycl/sycl.hpp>
7+
8+
template <typename... Ts, typename FuncTy>
9+
void TestTypes(FuncTy F) {
10+
(F(Ts{}), ...);
11+
}
12+
13+
int main() {
14+
sycl::queue q;
15+
16+
auto Test = [&](auto F, auto Expected, auto... Args) {
17+
#if defined(__GNUC__) || defined(__clang__)
18+
std::cout << __PRETTY_FUNCTION__ << std::endl;
19+
#endif
20+
std::tuple ArgsTuple{Args...};
21+
auto Result = std::apply(F, ArgsTuple);
22+
static_assert(std::is_same_v<decltype(Expected), decltype(Result)>);
23+
assert(Expected == Result);
24+
25+
sycl::buffer<bool, 1> ResultBuf{1};
26+
q.submit([&](sycl::handler &cgh) {
27+
sycl::accessor Result{ResultBuf, cgh};
28+
cgh.single_task([=]() {
29+
auto R = std::apply(F, ArgsTuple);
30+
static_assert(std::is_same_v<decltype(Expected), decltype(R)>);
31+
Result[0] = Expected == R;
32+
});
33+
});
34+
assert(sycl::host_accessor{ResultBuf}[0]);
35+
};
36+
37+
auto TestBitSelect = [&](auto type_val) {
38+
using T = decltype(type_val);
39+
auto BitSelect = [](auto... xs) { return sycl::bitselect(xs...); };
40+
41+
static_assert(std::is_integral_v<T>,
42+
"Only integer test is implemented here!");
43+
Test(BitSelect, T{0b0110}, T{0b1100}, T{0b0011}, T{0b1010});
44+
};
45+
46+
TestTypes<signed char, unsigned char, char, long, long long, unsigned long,
47+
unsigned long long>(TestBitSelect);
48+
49+
auto TestSelect = [&](auto type_val) {
50+
using T = decltype(type_val);
51+
auto Select = [](auto... xs) { return sycl::select(xs...); };
52+
53+
Test(Select, T{0}, T{1}, T{0}, true);
54+
Test(Select, T{1}, T{1}, T{0}, false);
55+
};
56+
57+
TestTypes<signed char, unsigned char, char>(TestSelect);
58+
59+
return 0;
60+
}

sycl/test-e2e/Basic/built-ins/vec_relational.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,70 @@ int main() {
8888
TEST2(sycl::any, int, EXPECTED(int32_t, 0), 3, va7);
8989
TEST(sycl::bitselect, float, EXPECTED(float, 1.0, 1.0), 2, va8, va9, va10);
9090
TEST(sycl::select, float, EXPECTED(float, 1.0, 2.0, 8.0), 3, va5, va6, c1);
91+
{
92+
// Extra tests for select/bitselect due to special handling required for
93+
// integer return types.
94+
95+
auto Test = [&](auto F, auto Expected, auto... Args) {
96+
std::tuple ArgsTuple{Args...};
97+
auto Result = std::apply(F, ArgsTuple);
98+
static_assert(std::is_same_v<decltype(Expected), decltype(Result)>);
99+
100+
// Note: operator==(vec, vec) return vec.
101+
auto Equal = [](auto x, auto y) {
102+
for (size_t i = 0; i < x.size(); ++i)
103+
if (x[i] != y[i])
104+
return false;
105+
106+
return true;
107+
};
108+
109+
assert(Equal(Result, Expected));
110+
111+
sycl::buffer<bool, 1> ResultBuf{1};
112+
deviceQueue.submit([&](sycl::handler &cgh) {
113+
sycl::accessor Result{ResultBuf, cgh};
114+
cgh.single_task([=]() {
115+
auto R = std::apply(F, ArgsTuple);
116+
static_assert(std::is_same_v<decltype(Expected), decltype(R)>);
117+
Result[0] = Equal(R, Expected);
118+
});
119+
});
120+
assert(sycl::host_accessor{ResultBuf}[0]);
121+
};
122+
123+
// Note that only int8_t/uint8_t are supported by the bitselect/select
124+
// builtins and not all three char data types. Also, use positive numbers
125+
// for the values below so that we could use the same for both
126+
// signed/unsigned tests.
127+
sycl::vec<uint8_t, 2> a{0b1100, 0b0011};
128+
sycl::vec<uint8_t, 2> b{0b0011, 0b1100};
129+
sycl::vec<uint8_t, 2> c{0b1010, 0b1010};
130+
sycl::vec<uint8_t, 2> r{0b0110, 0b1001};
131+
132+
auto BitSelect = [](auto... xs) { return sycl::bitselect(xs...); };
133+
Test(BitSelect, r, a, b, c);
134+
[&](auto... xs) {
135+
Test(BitSelect, xs.template as<sycl::vec<int8_t, 2>>()...);
136+
}(r, a, b, c);
137+
138+
auto Select = [](auto... xs) { return sycl::select(xs...); };
139+
sycl::vec<uint8_t, 2> c2{0x7F, 0xFF};
140+
sycl::vec<uint8_t, 2> r2{a[0], b[1]};
141+
142+
Test(Select, r2, a, b, c2);
143+
[&](auto... xs) {
144+
Test(Select, xs.template as<sycl::vec<int8_t, 2>>()..., c2);
145+
}(r2, a, b);
146+
147+
// Assume that MSB of a signed data type is the leftmost bit (signbit).
148+
auto c3 = c2.template as<sycl::vec<int8_t, 2>>();
149+
150+
Test(Select, r2, a, b, c3);
151+
[&](auto... xs) {
152+
Test(Select, xs.template as<sycl::vec<int8_t, 2>>()..., c3);
153+
}(r2, a, b);
154+
}
91155

92156
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
93157
TEST(sycl::isequal, int32_t, EXPECTED(int32_t, 1, 1), 2, va11.swizzle<0, 1>(),

0 commit comments

Comments
 (0)