Skip to content

Commit f752698

Browse files
againullpvchupin
authored andcommitted
[SYCL] Change the way of accessing single element in sycl::vec
Returning scalars from sycl::vec class as a swizzled vec causes problems with template resolution and ambiguity in overload resolution. This commit implements workaround for this problem. Scalars are returned by value for const vec and by reference for vec. Assumed that it is possible to get a reference the element of the vector, test is added to check that behaviour is not changed. Signed-off-by: Artur Gainullin <[email protected]>
1 parent 722006c commit f752698

File tree

3 files changed

+104
-24
lines changed

3 files changed

+104
-24
lines changed

sycl/include/CL/sycl/swizzles.def

+34-24
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,45 @@
6464
return __SYCL_ACCESS_RETURN; \
6565
}
6666

67+
#define __SYCL_SCALAR_ACCESS(_COND, _NAME, _INDEX) \
68+
template <int N = getNumElements()> \
69+
typename std::enable_if<(_COND), DataT &>::type _NAME() { \
70+
return (*__SYCL_ACCESS_RETURN)[_INDEX]; \
71+
} \
72+
template <int N = getNumElements()> \
73+
typename std::enable_if<(_COND), const DataT &>::type _NAME() const { \
74+
return (*__SYCL_ACCESS_RETURN)[_INDEX]; \
75+
}
76+
6777
//__swizzled_vec__ XYZW_ACCESS() const;
68-
__SYCL_ACCESS(N <= 4, x, 0)
69-
__SYCL_ACCESS(N == 2 || N == 3 || N == 4, y, 1)
70-
__SYCL_ACCESS(N == 3 || N == 4, z, 2)
71-
__SYCL_ACCESS(N == 4, w, 3)
78+
__SYCL_SCALAR_ACCESS(N <= 4, x, 0)
79+
__SYCL_SCALAR_ACCESS(N == 2 || N == 3 || N == 4, y, 1)
80+
__SYCL_SCALAR_ACCESS(N == 3 || N == 4, z, 2)
81+
__SYCL_SCALAR_ACCESS(N == 4, w, 3)
7282

7383
//__swizzled_vec__ RGBA_ACCESS() const;
74-
__SYCL_ACCESS(N == 4, r, 0)
75-
__SYCL_ACCESS(N == 4, g, 1)
76-
__SYCL_ACCESS(N == 4, b, 2)
77-
__SYCL_ACCESS(N == 4, a, 3)
84+
__SYCL_SCALAR_ACCESS(N == 4, r, 0)
85+
__SYCL_SCALAR_ACCESS(N == 4, g, 1)
86+
__SYCL_SCALAR_ACCESS(N == 4, b, 2)
87+
__SYCL_SCALAR_ACCESS(N == 4, a, 3)
7888

7989
//__swizzled_vec__ INDEX_ACCESS() const;
80-
__SYCL_ACCESS(N > 0, s0, 0)
81-
__SYCL_ACCESS(N > 1, s1, 1)
82-
__SYCL_ACCESS(N > 2, s2, 2)
83-
__SYCL_ACCESS(N > 2, s3, 3)
84-
__SYCL_ACCESS(N > 4, s4, 4)
85-
__SYCL_ACCESS(N > 4, s5, 5)
86-
__SYCL_ACCESS(N > 4, s6, 6)
87-
__SYCL_ACCESS(N > 4, s7, 7)
88-
__SYCL_ACCESS(N == 16, s8, 8)
89-
__SYCL_ACCESS(N == 16, s9, 9)
90-
__SYCL_ACCESS(N == 16, sA, 10)
91-
__SYCL_ACCESS(N == 16, sB, 11)
92-
__SYCL_ACCESS(N == 16, sC, 12)
93-
__SYCL_ACCESS(N == 16, sD, 13)
94-
__SYCL_ACCESS(N == 16, sE, 14)
95-
__SYCL_ACCESS(N == 16, sF, 15)
90+
__SYCL_SCALAR_ACCESS(N > 0, s0, 0)
91+
__SYCL_SCALAR_ACCESS(N > 1, s1, 1)
92+
__SYCL_SCALAR_ACCESS(N > 2, s2, 2)
93+
__SYCL_SCALAR_ACCESS(N > 2, s3, 3)
94+
__SYCL_SCALAR_ACCESS(N > 4, s4, 4)
95+
__SYCL_SCALAR_ACCESS(N > 4, s5, 5)
96+
__SYCL_SCALAR_ACCESS(N > 4, s6, 6)
97+
__SYCL_SCALAR_ACCESS(N > 4, s7, 7)
98+
__SYCL_SCALAR_ACCESS(N == 16, s8, 8)
99+
__SYCL_SCALAR_ACCESS(N == 16, s9, 9)
100+
__SYCL_SCALAR_ACCESS(N == 16, sA, 10)
101+
__SYCL_SCALAR_ACCESS(N == 16, sB, 11)
102+
__SYCL_SCALAR_ACCESS(N == 16, sC, 12)
103+
__SYCL_SCALAR_ACCESS(N == 16, sD, 13)
104+
__SYCL_SCALAR_ACCESS(N == 16, sE, 14)
105+
__SYCL_SCALAR_ACCESS(N == 16, sF, 15)
96106

97107
#ifdef SYCL_SIMPLE_SWIZZLES
98108
//__swizzled_vec__ XYZW_SWIZZLE() const;

sycl/include/CL/sycl/types.hpp

+18
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,24 @@ template <typename Type, int NumElements> class vec {
605605
return this;
606606
}
607607

608+
// ext_vector_type is used as an underlying type for sycl::vec on device.
609+
// The problem is that for clang vector types the return of operator[] is a
610+
// temporary and not a reference to the element in the vector. In practice
611+
// reinterpret_cast<DataT *>(&m_Data)[i]; is working. According to
612+
// http://llvm.org/docs/GetElementPtr.html#can-gep-index-into-vector-elements
613+
// this is not disallowed now. But could probably be disallowed in the future.
614+
// That is why tests are added to check that behavior of the compiler has
615+
// not changed.
616+
//
617+
// Implement operator [] in the same way for host and device.
618+
// TODO: change host side implementation when underlying type for host side
619+
// will be changed to std::array.
620+
const DataT &operator[](int i) const {
621+
return reinterpret_cast<const DataT *>(&m_Data)[i];
622+
}
623+
624+
DataT &operator[](int i) { return reinterpret_cast<DataT *>(&m_Data)[i]; }
625+
608626
// Begin hi/lo, even/odd, xyzw, and rgba swizzles.
609627
private:
610628
// Indexer used in the swizzles.def
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: env SYCL_DEVICE_TYPE=HOST %t.out | FileCheck %s
3+
// RUN: %CPU_RUN_PLACEHOLDER %t.out %CPU_CHECK_PLACEHOLDER
4+
// RUN: %GPU_RUN_PLACEHOLDER %t.out %GPU_CHECK_PLACEHOLDER
5+
// RUN: %ACC_RUN_PLACEHOLDER %t.out %ACC_CHECK_PLACEHOLDER
6+
//==------- scalar_vec_access.cpp - SYCL scalar access to vec test ---------==//
7+
//
8+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
9+
// See https://llvm.org/LICENSE.txt for license information.
10+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
// CHECK-NOT: Error: unexpected behavior because of accessing element of the vector by reference
15+
16+
#include <CL/sycl.hpp>
17+
#include <iostream>
18+
19+
typedef float float4_t __attribute__((ext_vector_type(4)));
20+
21+
int main() {
22+
23+
cl::sycl::queue Q;
24+
25+
Q.submit([=](cl::sycl::handler &cgh) {
26+
cl::sycl::stream out(1024, 100, cgh);
27+
cgh.single_task<class K>([=]() {
28+
// Test that it is possible to get a reference to single element of the
29+
// vector type. This behavior could possibly change in the future, this
30+
// test is necessary to track that.
31+
float4_t my_float4 = {0.0, 1.0, 2.0, 3.0};
32+
float f[4];
33+
for (int i = 0; i < 4; ++i) {
34+
f[i] = reinterpret_cast<float *>(&my_float4)[i];
35+
if (f[i] != i)
36+
out << "Error: unexpected behavior because of accessing element of "
37+
"the vector by reference"
38+
<< cl::sycl::endl;
39+
}
40+
41+
// Test that there is no template resolution error
42+
cl::sycl::float4 a = {1.0, 2.0, 3.0, 4.0};
43+
out << cl::sycl::native::recip(a.x()) << cl::sycl::endl;
44+
});
45+
});
46+
47+
// Test that there is no ambiguity in overload resolution.
48+
cl::sycl::float4 a = {1.0, 2.0, 3.0, 4.0};
49+
std::cout << a.x() << std::endl;
50+
51+
return 0;
52+
}

0 commit comments

Comments
 (0)