Skip to content

Commit 86cb94a

Browse files
committed
[SYCL] Implement SYCL 2020 multi_ptr
This commit adds implementations of SYCL 2020 multi_ptr and address_space_cast. Likewise it adds the legacy decoration for SYCL 1.2.1 style multi_ptr as deprecated. To prevent breaking user code the legacy decoration is made the default. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent 1d8a6d6 commit 86cb94a

30 files changed

+1635
-461
lines changed

sycl/include/CL/__spirv/spirv_ops.hpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,26 @@ extern SYCL_EXTERNAL __attribute__((opencl_global)) void *
319319
__spirv_GenericCastToPtrExplicit_ToGlobal(const void *Ptr,
320320
__spv::StorageClass::Flag S) noexcept;
321321

322+
extern SYCL_EXTERNAL __attribute__((opencl_global)) volatile void *
323+
__spirv_GenericCastToPtrExplicit_ToGlobal(const volatile void *Ptr,
324+
__spv::StorageClass::Flag S) noexcept;
325+
322326
extern SYCL_EXTERNAL __attribute__((opencl_local)) void *
323327
__spirv_GenericCastToPtrExplicit_ToLocal(const void *Ptr,
324328
__spv::StorageClass::Flag S) noexcept;
325329

330+
extern SYCL_EXTERNAL __attribute__((opencl_local)) volatile void *
331+
__spirv_GenericCastToPtrExplicit_ToLocal(const volatile void *Ptr,
332+
__spv::StorageClass::Flag S) noexcept;
333+
334+
extern SYCL_EXTERNAL __attribute__((opencl_private)) void *
335+
__spirv_GenericCastToPtrExplicit_ToPrivate(
336+
const void *Ptr, __spv::StorageClass::Flag S) noexcept;
337+
338+
extern SYCL_EXTERNAL __attribute__((opencl_private)) volatile void *
339+
__spirv_GenericCastToPtrExplicit_ToPrivate(
340+
const volatile void *Ptr, __spv::StorageClass::Flag S) noexcept;
341+
326342
template <typename dataT>
327343
extern __attribute__((opencl_global)) dataT *
328344
__SYCL_GenericCastToPtrExplicit_ToGlobal(const void *Ptr) noexcept {
@@ -331,6 +347,14 @@ __SYCL_GenericCastToPtrExplicit_ToGlobal(const void *Ptr) noexcept {
331347
Ptr, __spv::StorageClass::CrossWorkgroup);
332348
}
333349

350+
template <typename dataT>
351+
extern volatile __attribute__((opencl_global)) dataT *
352+
__SYCL_GenericCastToPtrExplicit_ToGlobal(const volatile void *Ptr) noexcept {
353+
return (__attribute__((opencl_global)) dataT *)
354+
__spirv_GenericCastToPtrExplicit_ToGlobal(
355+
Ptr, __spv::StorageClass::CrossWorkgroup);
356+
}
357+
334358
template <typename dataT>
335359
extern __attribute__((opencl_local)) dataT *
336360
__SYCL_GenericCastToPtrExplicit_ToLocal(const void *Ptr) noexcept {
@@ -339,6 +363,30 @@ __SYCL_GenericCastToPtrExplicit_ToLocal(const void *Ptr) noexcept {
339363
__spv::StorageClass::Workgroup);
340364
}
341365

366+
template <typename dataT>
367+
extern volatile __attribute__((opencl_local)) dataT *
368+
__SYCL_GenericCastToPtrExplicit_ToLocal(const volatile void *Ptr) noexcept {
369+
return (__attribute__((opencl_local)) dataT *)
370+
__spirv_GenericCastToPtrExplicit_ToLocal(Ptr,
371+
__spv::StorageClass::Workgroup);
372+
}
373+
374+
template <typename dataT>
375+
extern __attribute__((opencl_private)) dataT *
376+
__SYCL_GenericCastToPtrExplicit_ToPrivate(const void *Ptr) noexcept {
377+
return (__attribute__((opencl_private)) dataT *)
378+
__spirv_GenericCastToPtrExplicit_ToPrivate(Ptr,
379+
__spv::StorageClass::Function);
380+
}
381+
382+
template <typename dataT>
383+
extern volatile __attribute__((opencl_private)) dataT *
384+
__SYCL_GenericCastToPtrExplicit_ToPrivate(const volatile void *Ptr) noexcept {
385+
return (__attribute__((opencl_private)) dataT *)
386+
__spirv_GenericCastToPtrExplicit_ToPrivate(Ptr,
387+
__spv::StorageClass::Function);
388+
}
389+
342390
template <typename dataT>
343391
__SYCL_CONVERGENT__ extern SYCL_EXTERNAL dataT
344392
__spirv_SubgroupShuffleINTEL(dataT Data, uint32_t InvocationId) noexcept;

sycl/include/sycl/access/access.hpp

Lines changed: 140 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
#pragma once
99

10+
#include <CL/__spirv/spirv_ops.hpp>
1011
#include <sycl/detail/common.hpp>
1112
#include <sycl/detail/defines.hpp>
1213

@@ -54,7 +55,12 @@ enum class address_space : int {
5455
generic_space = 6, // TODO generic_space address space is not supported yet
5556
};
5657

57-
enum class decorated : int { no = 0, yes = 1, legacy = 2 };
58+
enum class decorated : int {
59+
no = 0,
60+
yes = 1,
61+
legacy __SYCL2020_DEPRECATED(
62+
"Legacy 'multi_ptr' is deprecated since SYCL 2020") = 2
63+
};
5864
} // namespace access
5965

6066
using access::target;
@@ -108,6 +114,14 @@ constexpr bool modeWritesNewData(access::mode m) {
108114
return m != access::mode::read;
109115
}
110116

117+
template <access::decorated Decorated> struct NegateDecorated;
118+
template <> struct NegateDecorated<access::decorated::yes> {
119+
static constexpr access::decorated value = access::decorated::no;
120+
};
121+
template <> struct NegateDecorated<access::decorated::no> {
122+
static constexpr access::decorated value = access::decorated::yes;
123+
};
124+
111125
#ifdef __SYCL_DEVICE_ONLY__
112126
#define __OPENCL_GLOBAL_AS__ __attribute__((opencl_global))
113127
#ifdef __ENABLE_USM_ADDR_SPACE__
@@ -199,82 +213,177 @@ template <typename ElementType>
199213
struct DecoratedType<ElementType, access::address_space::local_space> {
200214
using type = __OPENCL_LOCAL_AS__ ElementType;
201215
};
202-
template <class T> struct remove_AS {
203-
typedef T type;
204-
};
205216

206217
#ifdef __SYCL_DEVICE_ONLY__
207218
template <class T> struct deduce_AS {
208219
// Undecorated pointers are considered generic.
209220
// TODO: This assumes that the implementation uses generic as default. If
210221
// address space inference is used this may need to change.
211-
static const access::address_space value =
222+
static constexpr access::address_space value =
212223
access::address_space::generic_space;
213224
};
214225

215-
template <class T> struct remove_AS<__OPENCL_GLOBAL_AS__ T> {
216-
typedef T type;
226+
// Propagate through const qualifier.
227+
template <typename T> struct deduce_AS<const T> {
228+
static constexpr access::address_space value = deduce_AS<T>::value;
217229
};
218230

219-
#ifdef __ENABLE_USM_ADDR_SPACE__
220-
template <class T> struct remove_AS<__OPENCL_GLOBAL_DEVICE_AS__ T> {
221-
typedef T type;
231+
// Propagate through pointer.
232+
template <typename T> struct deduce_AS<T *> {
233+
static constexpr access::address_space value = deduce_AS<T>::value;
234+
};
235+
236+
// Propagate through const qualified pointer.
237+
template <typename T> struct deduce_AS<const T *> {
238+
static constexpr access::address_space value = deduce_AS<T>::value;
222239
};
223240

224-
template <class T> struct remove_AS<__OPENCL_GLOBAL_HOST_AS__ T> {
225-
typedef T type;
241+
// Propagate through reference.
242+
template <typename T> struct deduce_AS<T &> {
243+
static constexpr access::address_space value = deduce_AS<T>::value;
226244
};
227245

246+
// Propagate through const qualified reference.
247+
template <typename T> struct deduce_AS<const T &> {
248+
static constexpr access::address_space value = deduce_AS<T>::value;
249+
};
250+
251+
#ifdef __ENABLE_USM_ADDR_SPACE__
228252
template <class T> struct deduce_AS<__OPENCL_GLOBAL_DEVICE_AS__ T> {
229-
static const access::address_space value =
253+
static constexpr access::address_space value =
230254
access::address_space::ext_intel_global_device_space;
231255
};
232256

233257
template <class T> struct deduce_AS<__OPENCL_GLOBAL_HOST_AS__ T> {
234-
static const access::address_space value =
258+
static constexpr access::address_space value =
235259
access::address_space::ext_intel_global_host_space;
236260
};
237261
#endif // __ENABLE_USM_ADDR_SPACE__
238262

239-
template <class T> struct remove_AS<__OPENCL_PRIVATE_AS__ T> {
240-
typedef T type;
241-
};
242-
243-
template <class T> struct remove_AS<__OPENCL_LOCAL_AS__ T> {
244-
typedef T type;
245-
};
246-
247-
template <class T> struct remove_AS<__OPENCL_CONSTANT_AS__ T> {
248-
typedef T type;
249-
};
250-
251263
template <class T> struct deduce_AS<__OPENCL_GLOBAL_AS__ T> {
252-
static const access::address_space value =
264+
static constexpr access::address_space value =
253265
access::address_space::global_space;
254266
};
255267

256268
template <class T> struct deduce_AS<__OPENCL_PRIVATE_AS__ T> {
257-
static const access::address_space value =
269+
static constexpr access::address_space value =
258270
access::address_space::private_space;
259271
};
260272

261273
template <class T> struct deduce_AS<__OPENCL_LOCAL_AS__ T> {
262-
static const access::address_space value = access::address_space::local_space;
274+
static constexpr access::address_space value =
275+
access::address_space::local_space;
263276
};
264277

265278
template <class T> struct deduce_AS<__OPENCL_CONSTANT_AS__ T> {
266-
static const access::address_space value =
279+
static constexpr access::address_space value =
267280
access::address_space::constant_space;
268281
};
269282
#endif
270283

284+
} // namespace detail
285+
286+
template <typename T> struct remove_decoration { using type = T; };
287+
288+
// Propagate through const qualifier.
289+
template <typename T> struct remove_decoration<const T> {
290+
using type = const typename remove_decoration<T>::type;
291+
};
292+
293+
// Propagate through pointer.
294+
template <typename T> struct remove_decoration<T *> {
295+
using type = typename remove_decoration<T>::type *;
296+
};
297+
298+
// Propagate through const qualified pointer.
299+
template <typename T> struct remove_decoration<const T *> {
300+
using type = const typename remove_decoration<T>::type *;
301+
};
302+
303+
// Propagate through reference.
304+
template <typename T> struct remove_decoration<T &> {
305+
using type = typename remove_decoration<T>::type &;
306+
};
307+
308+
// Propagate through const qualified reference.
309+
template <typename T> struct remove_decoration<const T &> {
310+
using type = const typename remove_decoration<T>::type &;
311+
};
312+
313+
#ifdef __SYCL_DEVICE_ONLY__
314+
template <typename T> struct remove_decoration<__OPENCL_GLOBAL_AS__ T> {
315+
using type = T;
316+
};
317+
318+
#ifdef __ENABLE_USM_ADDR_SPACE__
319+
template <typename T> struct remove_decoration<__OPENCL_GLOBAL_DEVICE_AS__ T> {
320+
using type = T;
321+
};
322+
323+
template <typename T> struct remove_decoration<__OPENCL_GLOBAL_HOST_AS__ T> {
324+
using type = T;
325+
};
326+
327+
#endif // __ENABLE_USM_ADDR_SPACE__
328+
329+
template <typename T> struct remove_decoration<__OPENCL_PRIVATE_AS__ T> {
330+
using type = T;
331+
};
332+
333+
template <typename T> struct remove_decoration<__OPENCL_LOCAL_AS__ T> {
334+
using type = T;
335+
};
336+
337+
template <typename T> struct remove_decoration<__OPENCL_CONSTANT_AS__ T> {
338+
using type = T;
339+
};
340+
#endif // __SYCL_DEVICE_ONLY__
341+
342+
template <typename T>
343+
using remove_decoration_t = typename remove_decoration<T>::type;
344+
345+
namespace detail {
346+
347+
// Helper function for selecting appropriate casts between address spaces.
348+
template <typename ToT, typename FromT> inline ToT cast_AS(FromT from) {
349+
#ifdef __SYCL_DEVICE_ONLY__
350+
constexpr access::address_space ToAS = deduce_AS<ToT>::value;
351+
constexpr access::address_space FromAS = deduce_AS<FromT>::value;
352+
if constexpr (FromAS == access::address_space::generic_space) {
353+
using ToElemT = std::remove_pointer_t<remove_decoration_t<ToT>>;
354+
if constexpr (ToAS == access::address_space::global_space)
355+
return __SYCL_GenericCastToPtrExplicit_ToGlobal<ToElemT>(from);
356+
else if constexpr (ToAS == access::address_space::local_space)
357+
return __SYCL_GenericCastToPtrExplicit_ToLocal<ToElemT>(from);
358+
else if constexpr (ToAS == access::address_space::private_space)
359+
return __SYCL_GenericCastToPtrExplicit_ToPrivate<ToElemT>(from);
360+
#ifdef __ENABLE_USM_ADDR_SPACE__
361+
else if constexpr (ToAS == access::address_space::
362+
ext_intel_global_device_space ||
363+
ToAS ==
364+
access::address_space::ext_intel_global_host_space)
365+
// For extended address spaces we do not currently have a SPIR-V
366+
// conversion function, so we do a C-style cast. This may produce
367+
// warnings.
368+
return (ToT)from;
369+
#endif // __ENABLE_USM_ADDR_SPACE__
370+
else
371+
return reinterpret_cast<ToT>(from);
372+
} else
373+
#endif // __SYCL_DEVICE_ONLY__
374+
{
375+
return reinterpret_cast<ToT>(from);
376+
}
377+
}
378+
379+
} // namespace detail
380+
271381
#undef __OPENCL_GLOBAL_AS__
272382
#undef __OPENCL_GLOBAL_DEVICE_AS__
273383
#undef __OPENCL_GLOBAL_HOST_AS__
274384
#undef __OPENCL_LOCAL_AS__
275385
#undef __OPENCL_CONSTANT_AS__
276386
#undef __OPENCL_PRIVATE_AS__
277-
} // namespace detail
278387

279388
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
280389
} // namespace sycl

sycl/include/sycl/accessor.hpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,26 +1998,26 @@ class __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor :
19981998
#endif
19991999
>() const {
20002000
const size_t LinearIndex = getLinearIndex(id<AdjustedDim>());
2001-
return atomic<DataT, AS>(
2002-
multi_ptr<DataT, AS>(getQualifiedPtr() + LinearIndex));
2001+
return atomic<DataT, AS>(multi_ptr<DataT, AS, access::decorated::legacy>(
2002+
getQualifiedPtr() + LinearIndex));
20032003
}
20042004

20052005
template <int Dims = Dimensions>
20062006
typename detail::enable_if_t<(Dims > 0) && AccessMode == access::mode::atomic,
20072007
atomic<DataT, AS>>
20082008
operator[](id<Dimensions> Index) const {
20092009
const size_t LinearIndex = getLinearIndex(Index);
2010-
return atomic<DataT, AS>(
2011-
multi_ptr<DataT, AS>(getQualifiedPtr() + LinearIndex));
2010+
return atomic<DataT, AS>(multi_ptr<DataT, AS, access::decorated::legacy>(
2011+
getQualifiedPtr() + LinearIndex));
20122012
}
20132013

20142014
template <int Dims = Dimensions>
20152015
typename detail::enable_if_t<Dims == 1 && AccessMode == access::mode::atomic,
20162016
atomic<DataT, AS>>
20172017
operator[](size_t Index) const {
20182018
const size_t LinearIndex = getLinearIndex(id<AdjustedDim>(Index));
2019-
return atomic<DataT, AS>(
2020-
multi_ptr<DataT, AS>(getQualifiedPtr() + LinearIndex));
2019+
return atomic<DataT, AS>(multi_ptr<DataT, AS, access::decorated::legacy>(
2020+
getQualifiedPtr() + LinearIndex));
20212021
}
20222022
template <int Dims = Dimensions, typename = detail::enable_if_t<(Dims > 1)>>
20232023
auto operator[](size_t Index) const {
@@ -2516,23 +2516,25 @@ class __SYCL_SPECIAL_CLASS local_accessor_base :
25162516
operator typename detail::enable_if_t<
25172517
Dims == 0 && AccessMode == access::mode::atomic, atomic<DataT, AS>>()
25182518
const {
2519-
return atomic<DataT, AS>(multi_ptr<DataT, AS>(getQualifiedPtr()));
2519+
return atomic<DataT, AS>(
2520+
multi_ptr<DataT, AS, access::decorated::legacy>(getQualifiedPtr()));
25202521
}
25212522

25222523
template <int Dims = Dimensions>
25232524
typename detail::enable_if_t<(Dims > 0) && AccessMode == access::mode::atomic,
25242525
atomic<DataT, AS>>
25252526
operator[](id<Dimensions> Index) const {
25262527
const size_t LinearIndex = getLinearIndex(Index);
2527-
return atomic<DataT, AS>(
2528-
multi_ptr<DataT, AS>(getQualifiedPtr() + LinearIndex));
2528+
return atomic<DataT, AS>(multi_ptr<DataT, AS, access::decorated::legacy>(
2529+
getQualifiedPtr() + LinearIndex));
25292530
}
25302531

25312532
template <int Dims = Dimensions>
25322533
typename detail::enable_if_t<Dims == 1 && AccessMode == access::mode::atomic,
25332534
atomic<DataT, AS>>
25342535
operator[](size_t Index) const {
2535-
return atomic<DataT, AS>(multi_ptr<DataT, AS>(getQualifiedPtr() + Index));
2536+
return atomic<DataT, AS>(multi_ptr<DataT, AS, access::decorated::legacy>(
2537+
getQualifiedPtr() + Index));
25362538
}
25372539

25382540
template <int Dims = Dimensions, typename = detail::enable_if_t<(Dims > 1)>>

0 commit comments

Comments
 (0)