Skip to content

Commit a2e1669

Browse files
[SYCL] Fix bitselect builtin for integer types (#12598)
This regressed after #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 e4113f1 commit a2e1669

File tree

4 files changed

+187
-2
lines changed

4 files changed

+187
-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: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,64 @@ 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+
auto Equal = [](auto x, auto y) {
124+
for (size_t i = 0; i < x.size(); ++i)
125+
if (x[i] != y[i])
126+
return false;
127+
128+
return true;
129+
};
130+
131+
assert(Equal(Result, Expected));
132+
133+
sycl::buffer<bool, 1> ResultBuf{1};
134+
deviceQueue.submit([&](sycl::handler &cgh) {
135+
sycl::accessor Result{ResultBuf, cgh};
136+
cgh.single_task([=]() {
137+
auto R = std::apply(F, ArgsTuple);
138+
static_assert(std::is_same_v<decltype(Expected), decltype(R)>);
139+
Result[0] = Equal(R, Expected);
140+
});
141+
});
142+
assert(sycl::host_accessor{ResultBuf}[0]);
143+
};
144+
145+
sycl::marray<char, 2> a{0b1100, 0b0011};
146+
sycl::marray<char, 2> b{0b0011, 0b1100};
147+
sycl::marray<char, 2> c{0b1010, 0b1010};
148+
sycl::marray<char, 2> r{0b0110, 0b1001};
149+
150+
auto BitSelect = [](auto... xs) { return sycl::bitselect(xs...); };
151+
Test(BitSelect, r, a, b, c);
152+
// Input values/results above are positive, so use the same values for
153+
// signed/unsigned char tests.
154+
[&](auto... xs) {
155+
Test(BitSelect, sycl::marray<signed char, 2>{xs}...);
156+
}(r, a, b, c);
157+
[&](auto... xs) {
158+
Test(BitSelect, sycl::marray<unsigned char, 2>{xs}...);
159+
}(r, a, b, c);
160+
161+
auto Select = [](auto... xs) { return sycl::select(xs...); };
162+
sycl::marray<bool, 2> c2{false, true};
163+
sycl::marray<char, 2> r2{a[0], b[1]};
164+
Test(Select, r2, a, b, c2);
165+
[&](auto... xs) {
166+
Test(Select, sycl::marray<signed char, 2>{xs}..., c2);
167+
}(r2, a, b);
168+
[&](auto... xs) {
169+
Test(Select, sycl::marray<unsigned char, 2>{xs}..., c2);
170+
}(r2, a, b);
171+
}
114172

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

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)