Skip to content

Commit d2fddd8

Browse files
committed
Add support for unbounded arrays
1 parent 3e4c73c commit d2fddd8

File tree

5 files changed

+66
-37
lines changed

5 files changed

+66
-37
lines changed

clang/lib/CodeGen/CodeGenTypes.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,14 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
488488
return Ty;
489489
}
490490
}
491+
// An incomplete array AST type is typically lowered to an array of length zero in LLVM IR.
492+
// For SYCL devices, this is incompatible with SPIRV which does not accept arrays of length zero
493+
// so we explicitly intercept this case to instead lower to an array of length 1 instead.
494+
if (Context.getLangOpts().SYCLIsDevice)
495+
if (T->isIncompleteArrayType()) {
496+
return llvm::ArrayType::get(ConvertType(cast<ArrayType>(T)->getElementType()), 1);
497+
}
498+
}
491499

492500
// RecordTypes are cached and processed specially.
493501
if (const RecordType *RT = dyn_cast<RecordType>(Ty))

sycl/include/sycl/ext/oneapi/experimental/work_group_memory.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,17 @@ inline constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
2222

2323
class work_group_memory_impl {
2424
public:
25-
work_group_memory_impl() : wgm_size{0}, buffer_size{0} {}
25+
work_group_memory_impl() : buffer_size{0} {}
2626
work_group_memory_impl(const work_group_memory_impl &rhs) = default;
2727
work_group_memory_impl &
2828
operator=(const work_group_memory_impl &rhs) = default;
29-
work_group_memory_impl(size_t wgm_size, size_t buffer_size)
30-
: wgm_size{wgm_size}, buffer_size{buffer_size} {}
31-
size_t wgm_size;
29+
work_group_memory_impl(size_t buffer_size)
30+
: buffer_size{buffer_size} {}
31+
private:
3232
size_t buffer_size;
33+
friend class sycl::handler;
3334
};
3435

35-
inline size_t getWorkGroupMemoryOwnSize(detail::work_group_memory_impl *wgm) {
36-
return wgm->wgm_size;
37-
}
3836
} // namespace detail
3937

4038
namespace ext::oneapi::experimental {
@@ -55,13 +53,12 @@ class __SYCL_SPECIAL_CLASS __SYCL_TYPE(work_group_memory) work_group_memory
5553
template <typename T = DataT,
5654
typename = std::enable_if_t<!sycl::detail::is_unbounded_array_v<T>>>
5755
work_group_memory(handler &)
58-
: sycl::detail::work_group_memory_impl(sizeof(work_group_memory),
56+
: sycl::detail::work_group_memory_impl(
5957
sizeof(DataT)) {}
6058
template <typename T = DataT,
6159
typename = std::enable_if_t<sycl::detail::is_unbounded_array_v<T>>>
6260
work_group_memory(size_t num, handler &)
6361
: sycl::detail::work_group_memory_impl(
64-
sizeof(work_group_memory),
6562
num * sizeof(std::remove_extent_t<DataT>)) {}
6663
template <access::decorated IsDecorated = access::decorated::no>
6764
multi_ptr<value_type, access::address_space::local_space, IsDecorated>
@@ -70,7 +67,7 @@ class __SYCL_SPECIAL_CLASS __SYCL_TYPE(work_group_memory) work_group_memory
7067
IsDecorated, value_type>(ptr);
7168
}
7269
DataT *operator&() const { return reinterpret_cast<DataT *>(ptr); }
73-
operator DataT &() const { return *reinterpret_cast<DataT *>(ptr); }
70+
operator DataT &() const { return *(this->operator&()); }
7471
template <typename T = DataT,
7572
typename = std::enable_if_t<!std::is_array_v<T>>>
7673
const work_group_memory &operator=(const DataT &value) const {

sycl/include/sycl/handler.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,6 @@ class graph_impl;
171171
} // namespace ext::oneapi::experimental::detail
172172
namespace detail {
173173

174-
class work_group_memory_impl;
175-
size_t getWorkGroupMemoryOwnSize(work_group_memory_impl *);
176174
class handler_impl;
177175
class kernel_impl;
178176
class queue_impl;
@@ -720,8 +718,7 @@ class __SYCL_EXPORT handler {
720718
const ext::oneapi::experimental::work_group_memory<DataT, PropertyListT>
721719
&Arg) {
722720
addArg(detail::kernel_param_kind_t::kind_work_group_memory, &Arg,
723-
detail::getWorkGroupMemoryOwnSize(
724-
static_cast<detail::work_group_memory_impl *>(&Arg)),
721+
0,
725722
ArgIndex);
726723
}
727724

sycl/test-e2e/WorkGroupMemory/swap_test.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,29 @@ void swap_array_1d(T (&a)[N], T (&b)[N], size_t batch_size) {
186186
for (int i = 0; i < N; ++i) {
187187
assert(a[i] == old_b[i] && b[i] == old_a[i] && "Incorrect swap!");
188188
}
189+
190+
// Same as above but use an unbounded array as temporary storage
191+
{
192+
sycl::buffer<T, 1> buf_a{a, N};
193+
sycl::buffer<T, 1> buf_b{b, N};
194+
q.submit([&](sycl::handler &cgh) {
195+
sycl::accessor acc_a{buf_a, cgh};
196+
sycl::accessor acc_b{buf_b, cgh};
197+
syclexp::work_group_memory<T[]> temp{N, cgh};
198+
sycl::nd_range<1> ndr{size, wgsize};
199+
cgh.parallel_for(ndr, [=](sycl::nd_item<> it) {
200+
const auto i = it.get_global_id();
201+
auto ptr = &temp;
202+
(*ptr)[i] = acc_a[i];
203+
acc_a[i] = acc_b[i];
204+
acc_b[i] = (*ptr)[i];
205+
});
206+
});
207+
}
208+
// Four swaps same as no swap
209+
for (int i = 0; i < N; ++i) {
210+
assert(a[i] == old_a[i] && b[i] == old_b[i] && "Incorrect swap!");
211+
}
189212
}
190213

191214
template <typename T, size_t N>
@@ -283,6 +306,33 @@ void swap_array_2d(T (&a)[N][N], T (&b)[N][N], size_t batch_size) {
283306
"Incorrect swap!");
284307
}
285308
}
309+
310+
// Same as above but use an unbounded array as temporary storage
311+
{
312+
sycl::buffer<T, 2> buf_a{a[0], sycl::range{N, N}};
313+
sycl::buffer<T, 2> buf_b{b[0], sycl::range{N, N}};
314+
q.submit([&](sycl::handler &cgh) {
315+
sycl::accessor acc_a{buf_a, cgh};
316+
sycl::accessor acc_b{buf_b, cgh};
317+
syclexp::work_group_memory<T[][N]> temp{N, cgh};
318+
sycl::nd_range<2> ndr{size, wgsize};
319+
cgh.parallel_for(ndr, [=](sycl::nd_item<2> it) {
320+
const auto i = it.get_global_id()[0];
321+
const auto j = it.get_global_id()[1];
322+
temp[i][j] = acc_a[i][j];
323+
acc_a[i][j] = acc_b[i][j];
324+
syclexp::work_group_memory<T[][N]> temp2{temp};
325+
acc_b[i][j] = temp2[i][j];
326+
});
327+
});
328+
}
329+
for (int i = 0; i < N; ++i) {
330+
for (int j = 0; j < N; ++j) {
331+
// Four swaps are the same as no swap
332+
assert(a[i][j] == old_a[i][j] && b[i][j] == old_b[i][j] &&
333+
"Incorrect swap!");
334+
}
335+
}
286336
}
287337

288338
// Coherency test that checks that work group memory is truly shared by

sycl/test-e2e/WorkGroupMemory/unbounded_array_test.cpp

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)