Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sycl][cuda][hip] Expose const addrsp via device_global<T, decltype(properties{device_constant})> #16001

Draft
wants to merge 38 commits into
base: sycl
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8c38eda
[NVPTX] Use "const" cache w/ "device_global"
JackAKirk Oct 15, 2024
b0a8698
Make compat with full device_global impl.
JackAKirk Nov 6, 2024
af10296
fix format
JackAKirk Nov 6, 2024
7682c97
Merge branch 'sycl' into cuda-const-addr-expose
JackAKirk Nov 7, 2024
d64e9f1
Add device code test/Update ext spec with note
JackAKirk Nov 14, 2024
7668ca5
Try to render ascii correctly
JackAKirk Nov 14, 2024
002c1ba
Remove unwanted italic
JackAKirk Nov 14, 2024
b9dcbbd
Try to remove \
JackAKirk Nov 14, 2024
6263635
Another attempt to render __constant__
JackAKirk Nov 14, 2024
b629213
Try to render __constant__
JackAKirk Nov 14, 2024
7f4cf57
Try to render __constant__
JackAKirk Nov 14, 2024
9c15eed
Render __constant__ correctly
JackAKirk Nov 14, 2024
d8aceb1
Check default addrspace used for non cuda/hip
JackAKirk Nov 14, 2024
84f0f11
Improve comment
JackAKirk Nov 14, 2024
3f70ded
Simplify test
JackAKirk Nov 14, 2024
b0d9167
Update sycl/doc/extensions/experimental/sycl_ext_oneapi_device_global…
JackAKirk Nov 15, 2024
0b8cd4e
Barebones impl for testing new prop.
JackAKirk Dec 9, 2024
fc0262d
Merge branch 'sycl' into cuda-const-addr-expose
JackAKirk Dec 9, 2024
cae62f2
Merge branch 'sycl' into cuda-const-addr-expose
JackAKirk Dec 10, 2024
5ee02a1
Fix format
JackAKirk Dec 10, 2024
7dff19b
Fix failure from merge
JackAKirk Dec 10, 2024
a337db6
Fix cp constructor after merge
JackAKirk Dec 10, 2024
6d35831
Add missing `using base_t` statement
JackAKirk Dec 10, 2024
8e031bf
Remove duplicate device_global decl
JackAKirk Dec 10, 2024
1da56bb
Add missing `typename`
JackAKirk Dec 10, 2024
52d9e6f
Fix separate types device_global specializations
JackAKirk Dec 10, 2024
79bb6b6
Fix impl for testing.
JackAKirk Jan 22, 2025
4c8f724
Fix format
JackAKirk Jan 22, 2025
4eb8375
Merge branch 'sycl' into cuda-const-addr-expose
JackAKirk Jan 22, 2025
6e2f772
Fix merge/format
JackAKirk Jan 22, 2025
6ca1274
device_constant -> const T
JackAKirk Jan 22, 2025
0e36f21
Fix template deduction.
JackAKirk Jan 22, 2025
9e53646
Fix device_global_copy test
JackAKirk Jan 22, 2025
9b4de8b
Fix failures
JackAKirk Jan 22, 2025
c14a604
fix
JackAKirk Jan 22, 2025
0a66d92
Windows fix
JackAKirk Jan 23, 2025
27c1351
typedef workaround attempt
JackAKirk Jan 27, 2025
3ef0864
Merge branch 'sycl' into cuda-const-addr-expose
JackAKirk Jan 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,15 @@ def SYCLDeviceGlobal: InheritableAttr {
let SimpleHandler = 1;
}

def SYCLDeviceConstant: InheritableAttr {
let Spellings = [CXX11<"__sycl_detail__", "device_constant">];
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
// Only used internally by SYCL implementation
let Documentation = [SYCLDeviceConstantAttrDocs];
let SimpleHandler = 1;
}

def SYCLGlobalVariableAllowed : InheritableAttr {
let Spellings = [CXX11<"__sycl_detail__", "global_variable_allowed">];
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,26 @@ so we have this attribute in sycl_detail namespace.
}];
}

def SYCLDeviceConstantAttrDocs : Documentation {
let Category = DocCatType;
let Heading = "__sycl_detail__::device_constant";
let Content = [{
This attribute is part of support for SYCL device_global feature.
[[__sycl_detail__::device_constant]] attribute is used for marking that a
device_global should use the device constant address space (if available).
We do not intend to support this as a general attribute that user code can use,
so we have this attribute in sycl_detail namespace.

.. code-block:: c++

template<typename T>
struct [[__sycl_detail__::device_global,
__sycl_detail__::device_constant]] device_global {}

device_global<int> Foo;
}];
}

def SYCLGlobalVariableAllowedAttrDocs : Documentation {
let Category = DocCatType;
let Heading = "__sycl_detail__::global_variable_allowed";
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5831,6 +5831,13 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) {
Scope = RD->getAttr<SYCLScopeAttr>();
if (Scope && Scope->isWorkGroup())
return LangAS::sycl_local;

if (getTriple().isNVPTX() || getTriple().isAMDGPU()) {
const RecordDecl *RD = D->getType()->getAsRecordDecl();
if (RD && RD->hasAttr<SYCLDeviceConstantAttr>()) {
return LangAS::opencl_constant;
}
}
}

if (LangOpts.SYCLIsDevice &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ class device_global {

_T_ is restricted to types that have a trivial destructor. _PropertyListT_ enables properties to be associated with a `device_global`.

[NOTE]
====
If _T_ is `const` then implementations may choose to allocate the `device_global` in a dedicated constant address space as an optimization. When using the {dpcpp} compiler with the CUDA or HIP backend, declaring a `device_global<const T>` is equivalent to declaring a `$$__constant__$$` variable.
====
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem like it corresponds to what is implemented. It could be done in tandem by making all conditional behavior dependent on the new property dependent on the disjunction of that and std::is_const_v<T>. That said, if that is the case we also need to document how that affects the members of the device_global class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't finalised the implementation yet (I'm just testing the draft requested changes atm), so I haven't updated the documentation which you are right is completely out of date. I described this here: #16001 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mention me with a comment like "spec ready for review" when it is ready?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mention me with a comment like "spec ready for review" when it is ready?

Sure, no problem.


When compiling with {cpp} versions before {cpp}20, _T_ must also have a trivial default constructor. In this case, the allocation of type _T_ for a given `device_global` is zero-initialized on a given device prior to the first access to that `device_global` on that device. For the purposes of this definition an access can be a direct access of the `device_global` in kernel code or a copy to or from that `device_global` enqueued to the given device.

When compiling with {cpp}20 or later, _T_ must have a constructor that can be `constexpr` evaluated, and the parameters to the `device_global` constructor are forwarded to the _T_ constructor. In this case, the allocation of type _T_ for a given `device_global` is initialized on a given device prior to the first access to that `device_global` on that device.
Expand Down
185 changes: 105 additions & 80 deletions sycl/include/sycl/ext/oneapi/device_global/device_global.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ namespace sycl {
inline namespace _V1 {
namespace ext::oneapi::experimental {

template <typename T, typename PropertyListT> class device_global;

namespace detail {
// Type-trait for checking if a type defines `operator->`.
template <typename T, typename = void>
Expand All @@ -61,8 +59,8 @@ template <typename T> struct IsDeviceGlobalOrBaseRef : std::false_type {};
template <typename T, typename PropertyListT>
struct IsDeviceGlobalOrBaseRef<device_global_base<T, PropertyListT, void> &>
: std::true_type {};
template <typename T, typename PropertyListT>
struct IsDeviceGlobalOrBaseRef<device_global<T, PropertyListT> &>
template <typename T, typename PropertyListT, typename Cond>
struct IsDeviceGlobalOrBaseRef<device_global<T, PropertyListT, Cond> &>
: std::true_type {};

// Base class for device_global.
Expand Down Expand Up @@ -141,11 +139,10 @@ class device_global_base {

// Specialization of device_global base class for when device_image_scope is in
// the property list.
template <typename T, typename... Props>
template <typename T, typename Props>
class device_global_base<
T, properties_t<Props...>,
std::enable_if_t<properties_t<Props...>::template has_property<
device_image_scope_key>()>> {
T, Props,
std::enable_if_t<Props::template has_property<device_image_scope_key>()>> {
protected:
T val{};
T *get_ptr() noexcept { return &val; }
Expand Down Expand Up @@ -192,7 +189,8 @@ class device_global_base<

} // namespace detail

template <typename T, typename PropertyListT = empty_properties_t>
template <typename T, typename PropertyListT = empty_properties_t,
typename Cond = void>
class
#ifdef __SYCL_DEVICE_ONLY__
// FIXME: Temporary work-around. Remove when fixed.
Expand All @@ -204,112 +202,139 @@ class
"Property list is invalid.");
};

// Common code for device_global with and without
// __sycl_detail__::device_constant attribute
// Inherit the base class' constructors
#define DEVICE_GLOBAL_COMMON() \
using property_list_t = detail::properties_t<Props...>; \
using base_t = detail::device_global_base<T, property_list_t>; \
using element_type = std::remove_extent_t<T>; \
static_assert(std::is_trivially_destructible_v<T>, \
"Type T must be trivially destructible."); \
static_assert(is_property_list<property_list_t>::value, \
"Property list is invalid."); \
using detail::device_global_base<T, property_list_t>::device_global_base; \
\
constexpr device_global(const device_global &DG) \
: base_t(static_cast<const base_t &>(DG)) {} \
device_global(const device_global &&) = delete; \
device_global &operator=(const device_global &) = delete; \
device_global &operator=(const device_global &&) = delete; \
const T &get() const noexcept { \
__SYCL_HOST_NOT_SUPPORTED("get()") \
return *this->get_ptr(); \
} \
\
operator const T &() const noexcept { \
__SYCL_HOST_NOT_SUPPORTED("Implicit conversion of device_global to T") \
return get(); \
} \
\
template <class RelayT = T> \
std::remove_reference_t< \
decltype(std::declval<RelayT>()[std::declval<std::ptrdiff_t>()])> & \
operator[](std::ptrdiff_t idx) noexcept { \
__SYCL_HOST_NOT_SUPPORTED("Subscript operator") \
return (*this->get_ptr())[idx]; \
} \
\
template <class RelayT = T> \
const std::remove_reference_t< \
decltype(std::declval<RelayT>()[std::declval<std::ptrdiff_t>()])> & \
operator[](std::ptrdiff_t idx) const noexcept { \
__SYCL_HOST_NOT_SUPPORTED("Subscript operator") \
return (*this->get_ptr())[idx]; \
} \
\
template <class RelayT = T> \
std::enable_if_t<detail::HasArrowOperator<RelayT>::value || \
std::is_pointer_v<RelayT>, \
RelayT> & \
operator->() noexcept { \
__SYCL_HOST_NOT_SUPPORTED("operator-> on a device_global") \
return *this->get_ptr(); \
} \
\
template <class RelayT = T> \
std::enable_if_t<detail::HasArrowOperator<RelayT>::value || \
std::is_pointer_v<RelayT>, \
const RelayT> & \
operator->() const noexcept { \
__SYCL_HOST_NOT_SUPPORTED("operator-> on a device_global") \
return *this->get_ptr(); \
} \
\
template <typename propertyT> static constexpr bool has_property() { \
return property_list_t::template has_property<propertyT>(); \
} \
\
template <typename propertyT> static constexpr auto get_property() { \
return property_list_t::template get_property<propertyT>(); \
}

template <typename T, typename... Props>
class
#ifdef __SYCL_DEVICE_ONLY__
[[__sycl_detail__::global_variable_allowed, __sycl_detail__::device_global,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if device_global should take an optional argument to select the address space instead of a new device_constant. If we do, you could use some meta-programming to select the address space here, that could limit the impact on the headers.

Copy link
Contributor

@steffenlarsen steffenlarsen Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could even do that with the current property. It should be as simple as doing a std::conditional_t<property_list_t::template has_property<device_constant_key>(), __OPENCL_CONSTANT_AS__ T *, T *>, inheriting the definition of __OPENCL_CONSTANT_AS__ from sycl/include/sycl/access/access.hpp. Assuming the PTX and AMDGCN know how to handle __attribute__((opencl_constant)), that should hopefully avoid the need for the new clang attribute.

As for the member availability, this could be done through either conditionally picking base classes or SFINAE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could even do that with the current property. It should be as simple as doing a std::conditional_t<property_list_t::template has_property<device_constant_key>(), __OPENCL_CONSTANT_AS__ T *, T *>, inheriting the definition of __OPENCL_CONSTANT_AS__ from sycl/include/sycl/access/access.hpp. Assuming the PTX and AMDGCN know how to handle __attribute__((opencl_constant)), that should hopefully avoid the need for the new clang attribute.

As for the member availability, this could be done through either conditionally picking base classes or SFINAE.

Doing address space declarations directly in source code is currently not allowed by SEMA: I get e.g. (same if field is pointer type):

error: field may not be qualified with an address space
  100 |   T __attribute__((opencl_constant)) val{};

I looked into changing this behaviour, but I didn't think there was a simple solution.
My current idea is to partially specialize as

    device_global<
        T, detail::properties_t<Props...>,
        typename std::enable_if_t<(detail::properties_t<Props...>::
                               template has_property<device_constant_key>())>>
    : public detail::device_global_base<T, detail::properties_t<Props...>>

such that when the property device_constant is used we add a clang attribute to the class :

__sycl_detail__::device_constant

That the compiler then uses to manually set the address space to .const only for cuda/hip backends.

This I think in theory should be compatible with the partial specializations of the device_global_base class; to allow simultaneous specializations for the case when device_image_scope property is in the property list (via device_global_base): The only property that can be used in combination with the device_constant property should be device_image_scope I think (I will update the specification doc once the implementation is finalised).

@steffenlarsen @Naghasan Maybe there is a better solution though?

Once this is done there should also probably be a few more tests added to check all valid combined functionality of the device_constant property with the device_image_scope property. There should also be a test checking that the compiler does not allow writing to a device_global with the device_constant property (apart from via sycl::hander::/queue::memcpy etc).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need the attribute, could we maybe make it apply to the field instead of the device-global class then? I.e. that way we can use the conditional solution we previously discussed, but with the new attribute.

As a thought experiment, can we think of a case where a const global variable (including const fields of non-const global variables) would not want the variables to be in the .const namespace for NVPTX and AMDGCN? If not, could we maybe make the address-space decision based on that?

Copy link
Contributor Author

@JackAKirk JackAKirk Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need the attribute, could we maybe make it apply to the field instead of the device-global class then? I.e. that way we can use the conditional solution we previously discussed, but with the new attribute.

Yeah this sounds like it might be a better solution. I'll look into doing this. Thanks for the input

As a thought experiment, can we think of a case where a const global variable (including const fields of non-const global variables) would not want the variables to be in the .const namespace for NVPTX and AMDGCN? If not, could we maybe make the address-space decision based on that?

I am not sure if it can be an issue for NVPTX and AMDGCN backends, but in theory you can run out of .const memory space (It is normally limited to 4kb for NVPTX), and hence a user may want to be careful about which variables to put in .const space. If it is not a real issue in these backends, it could be an issue in other as yet unsupported backends. This is why we do not wan to have device_global<const T> imply .const address space, and instead have the explicit device_global<T, decltype(properties{device_constant})> solution, which will be functionally identical to device_global<const T, decltype(properties{device_constant})>:

device_constant implies const T but const T shouldn't imply .const address space.

__sycl_detail__::device_constant,
__sycl_detail__::add_ir_attributes_global_variable(
"sycl-device-global-size",
__SYCL_DEVICE_GLOBAL_PROP_META_INFO(Props)::name..., sizeof(T),
__SYCL_DEVICE_GLOBAL_PROP_META_INFO(Props)::value...)]]
#endif
device_global<T, detail::properties_t<Props...>>
device_global<T, detail::properties_t<Props...>,
std::enable_if_t<detail::properties_t<
Props...>::template has_property<device_constant_key>()>>
: public detail::device_global_base<T, detail::properties_t<Props...>> {

using property_list_t = detail::properties_t<Props...>;
using base_t = detail::device_global_base<T, property_list_t>;

public:
using element_type = std::remove_extent_t<T>;

#if !__cpp_consteval
static_assert(std::is_trivially_default_constructible_v<T>,
"Type T must be trivially default constructable (until C++20 "
"consteval is supported and enabled.)");
#endif // !__cpp_consteval
static_assert(std::is_trivially_destructible_v<T>,
"Type T must be trivially destructible.");

static_assert(is_property_list<property_list_t>::value,
"Property list is invalid.");
DEVICE_GLOBAL_COMMON()
};

// Inherit the base class' constructors
using detail::device_global_base<T, property_list_t>::device_global_base;
typedef void abvk;

constexpr device_global(const device_global &DG)
: base_t(static_cast<const base_t &>(DG)) {}
template <typename T, typename... Props>
class
#ifdef __SYCL_DEVICE_ONLY__
[[__sycl_detail__::global_variable_allowed, __sycl_detail__::device_global,
__sycl_detail__::add_ir_attributes_global_variable(
"sycl-device-global-size",
__SYCL_DEVICE_GLOBAL_PROP_META_INFO(Props)::name..., sizeof(T),
__SYCL_DEVICE_GLOBAL_PROP_META_INFO(Props)::value...)]]
#endif
device_global<T, detail::properties_t<Props...>,
std::enable_if_t<!(
detail::properties_t<Props...>::template has_property<
device_constant_key>()), abvk>>
: public detail::device_global_base<T, detail::properties_t<Props...>> {
public:
#if !__cpp_consteval
static_assert(std::is_trivially_default_constructible_v<T>,
"Type T must be trivially default constructable (until C++20 "
"consteval is supported and enabled.)");
#endif // !__cpp_consteval

device_global(const device_global &&) = delete;
device_global &operator=(const device_global &) = delete;
device_global &operator=(const device_global &&) = delete;
DEVICE_GLOBAL_COMMON()

T &get() noexcept {
__SYCL_HOST_NOT_SUPPORTED("get()")
return *this->get_ptr();
}

const T &get() const noexcept {
__SYCL_HOST_NOT_SUPPORTED("get()")
return *this->get_ptr();
}

operator T &() noexcept {
__SYCL_HOST_NOT_SUPPORTED("Implicit conversion of device_global to T")
return get();
}

operator const T &() const noexcept {
__SYCL_HOST_NOT_SUPPORTED("Implicit conversion of device_global to T")
return get();
}

device_global &operator=(const T &newValue) noexcept {
__SYCL_HOST_NOT_SUPPORTED("Assignment operator")
*this->get_ptr() = newValue;
return *this;
}

template <class RelayT = T>
std::remove_reference_t<
decltype(std::declval<RelayT>()[std::declval<std::ptrdiff_t>()])> &
operator[](std::ptrdiff_t idx) noexcept {
__SYCL_HOST_NOT_SUPPORTED("Subscript operator")
return (*this->get_ptr())[idx];
}

template <class RelayT = T>
const std::remove_reference_t<
decltype(std::declval<RelayT>()[std::declval<std::ptrdiff_t>()])> &
operator[](std::ptrdiff_t idx) const noexcept {
__SYCL_HOST_NOT_SUPPORTED("Subscript operator")
return (*this->get_ptr())[idx];
}

template <class RelayT = T>
std::enable_if_t<detail::HasArrowOperator<RelayT>::value ||
std::is_pointer_v<RelayT>,
RelayT> &
operator->() noexcept {
__SYCL_HOST_NOT_SUPPORTED("operator-> on a device_global")
return *this->get_ptr();
}

template <class RelayT = T>
std::enable_if_t<detail::HasArrowOperator<RelayT>::value ||
std::is_pointer_v<RelayT>,
const RelayT> &
operator->() const noexcept {
__SYCL_HOST_NOT_SUPPORTED("operator-> on a device_global")
return *this->get_ptr();
}

template <typename propertyT> static constexpr bool has_property() {
return property_list_t::template has_property<propertyT>();
}

template <typename propertyT> static constexpr auto get_property() {
return property_list_t::template get_property<propertyT>();
}
};

} // namespace ext::oneapi::experimental
Expand Down
32 changes: 23 additions & 9 deletions sycl/include/sycl/ext/oneapi/device_global/properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ namespace sycl {
inline namespace _V1 {
namespace ext::oneapi::experimental {

template <typename T, typename PropertyListT> class device_global;
template <typename T, typename PropertyListT, typename Cond>
class device_global;

struct device_image_scope_key
: detail::compile_time_property_key<detail::PropKind::DeviceImageScope> {
using value_t = property_value<device_image_scope_key>;
};

struct device_constant_key
: detail::compile_time_property_key<detail::PropKind::DeviceConstant> {
using value_t = property_value<device_constant_key>;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have this new property and its effects on the device_global class documented anywhere?


enum class host_access_enum : std::uint16_t { read, write, read_write, none };

struct host_access_key
Expand Down Expand Up @@ -54,6 +60,7 @@ struct implement_in_csr_key
};

inline constexpr device_image_scope_key::value_t device_image_scope;
inline constexpr device_constant_key::value_t device_constant;

template <host_access_enum Access>
inline constexpr host_access_key::value_t<Access> host_access;
Expand All @@ -77,17 +84,24 @@ inline constexpr implement_in_csr_key::value_t<Enable> implement_in_csr;
inline constexpr implement_in_csr_key::value_t<true> implement_in_csr_on;
inline constexpr implement_in_csr_key::value_t<false> implement_in_csr_off;

template <typename T, typename PropertyListT>
template <typename T, typename PropertyListT, typename Cond>
struct is_property_key_of<device_image_scope_key,
device_global<T, PropertyListT>> : std::true_type {};
template <typename T, typename PropertyListT>
struct is_property_key_of<host_access_key, device_global<T, PropertyListT>>
device_global<T, PropertyListT, Cond>>
: std::true_type {};
template <typename T, typename PropertyListT, typename Cond>
struct is_property_key_of<device_constant_key,
device_global<T, PropertyListT, Cond>>
: std::true_type {};
template <typename T, typename PropertyListT, typename Cond>
struct is_property_key_of<host_access_key,
device_global<T, PropertyListT, Cond>>
: std::true_type {};
template <typename T, typename PropertyListT>
struct is_property_key_of<init_mode_key, device_global<T, PropertyListT>>
template <typename T, typename PropertyListT, typename Cond>
struct is_property_key_of<init_mode_key, device_global<T, PropertyListT, Cond>>
: std::true_type {};
template <typename T, typename PropertyListT>
struct is_property_key_of<implement_in_csr_key, device_global<T, PropertyListT>>
template <typename T, typename PropertyListT, typename Cond>
struct is_property_key_of<implement_in_csr_key,
device_global<T, PropertyListT, Cond>>
: std::true_type {};

namespace detail {
Expand Down
3 changes: 2 additions & 1 deletion sycl/include/sycl/ext/oneapi/properties/property.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,9 @@ enum PropKind : uint32_t {
Restrict = 80,
EventMode = 81,
NativeLocalBlockIO = 82,
DeviceConstant = 83,
// PropKindSize must always be the last value.
PropKindSize = 83,
PropKindSize = 84,
};

template <typename PropertyT> struct PropertyToKind {
Expand Down
Loading
Loading