From baba5eecdbc010a193d08cf7887d0b8831084bc6 Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris Date: Mon, 31 Aug 2026 14:01:24 -0700 Subject: [PATCH] [SYCL][NFC] Promote new-style property engine base to sycl::detail --- .../sycl/detail/properties/property.hpp | 177 ++++++++++++++++++ .../experimental/cluster_group_prop.hpp | 2 +- .../sycl/ext/oneapi/properties/property.hpp | 155 +++------------ .../ext/oneapi/properties/property_value.hpp | 8 +- .../abi/sycl_classes_abi_neutral_test.cpp | 6 +- 5 files changed, 210 insertions(+), 138 deletions(-) create mode 100644 sycl/include/sycl/detail/properties/property.hpp diff --git a/sycl/include/sycl/detail/properties/property.hpp b/sycl/include/sycl/detail/properties/property.hpp new file mode 100644 index 0000000000000..9a5f30db7f90b --- /dev/null +++ b/sycl/include/sycl/detail/properties/property.hpp @@ -0,0 +1,177 @@ +//==---------- property.hpp --- SYCL compile-time property engine ----------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Shared, namespace-neutral core of the "new-style" compile-time property +// engine: the `PropKind` registry and the property key/value base classes that +// property definitions are built on. This lives in `sycl::detail` so that both +// the `sycl::ext::oneapi::experimental` extensions and the `sycl::khr` KHR +// properties layer can define their properties on top of a single registry. +// +// NOTE: This header deliberately contains only the property-*definition* +// infrastructure -- the pieces that appear inside a property type's definition +// but never in a public API's mangled signature. The property list container +// (`properties`), `property_value`, the list traits (`is_property_list`, +// `is_property_value`), and the applicability/customization traits +// (`is_property_key_of`, `PropertyMetaInfo`, ...) remain in the facades +// (see ) so that moving this engine +// does not change any mangled symbol name. See the "HOW-TO" comments in that +// facade header for how to define a new property. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include // for uint32_t +#include // for is_same_v + +#include + +namespace sycl { +inline namespace _V1 { +// Forward declaration of the experimental property list container so the +// property key/value base classes can befriend it across namespaces (the +// container accesses the protected `get_property_impl`). +namespace ext::oneapi::experimental { +template class __SYCL_EBO properties; +} // namespace ext::oneapi::experimental + +namespace detail { + +// List of all properties. +// +// This is a scoped enumeration so that its enumerators do not leak into the +// enclosing `sycl::detail` namespace, where they would otherwise collide with +// the enumerators of the old-style property enums (DataLessPropKind / +// PropWithDataKind in ). +enum class PropKind : uint32_t { + DeviceImageScope = 0, + HostAccess = 1, + WorkGroupSize = 2, + WorkGroupSizeHint = 3, + SubGroupSize = 4, + DeviceHas = 5, + Alignment = 6, + CacheConfig = 7, + UseRootSync = 8, + GRFSize = 9, + GRFSizeAutomatic = 10, + ESIMDL1CacheHint = 11, + ESIMDL2CacheHint = 12, + ESIMDL3CacheHint = 13, + UsmKind = 14, + CacheControlReadHint = 15, + CacheControlReadAssertion = 16, + CacheControlWrite = 17, + BuildOptions = 18, + BuildLog = 19, + FloatingPointControls = 20, + DataPlacement = 21, + ContiguousMemory = 22, + FullGroup = 23, + Naive = 24, + WorkGroupProgress = 25, + SubGroupProgress = 26, + WorkItemProgress = 27, + NDRangeKernel = 28, + SingleTaskKernel = 29, + IndirectlyCallable = 30, + CallsIndirectly = 31, + InputDataPlacement = 32, + OutputDataPlacement = 33, + IncludeFiles = 34, + RegisteredNames = 35, + ClusterLaunch = 36, + MaxWorkGroupSize = 37, + MaxLinearWorkGroupSize = 38, + Prefetch = 39, + Deterministic = 40, + InitializeToIdentity = 41, + WorkGroupScratchSize = 42, + Unaliased = 43, + EventMode = 44, + NativeLocalBlockIO = 45, + InitialThreshold = 46, + MaximumSize = 47, + ZeroInit = 48, + FastLink = 49, + EnableIPC = 50, + RegisterHostMemoryReadOnly = 51, + EnableProfiling = 52, + MaximumRegisters = 53, + MaximumRegistersAutomatic = 54, + // PropKindSize must always be the last value. + PropKindSize = 55, +}; + +template struct PropertyToKind { + static constexpr PropKind Kind = PropertyT::Kind; +}; + +struct property_tag {}; + +// This is used to implement has/get_property via inheritance queries. +template struct property_key_tag : property_tag {}; + +template +struct property_base : property_key_tag { + using key_t = property_key_t; + +protected: + constexpr property_t get_property_impl(property_key_tag) const { + return *static_cast(this); + } + + // For key_t access in error reporting specialization. The property list + // container lives in the experimental facade namespace. + template + friend class __SYCL_EBO ext::oneapi::experimental::properties; + +#if !defined(_MSC_VER) + // Temporary, to ensure new code matches previous behavior and to catch any + // silly copy-paste mistakes. MSVC can't compile it, but linux-only is + // enough for this temporary check. + static_assert([]() constexpr -> bool { + if constexpr (std::is_same_v) + // key_t is incomplete at this point for runtime properties. + return true; + else + return Kind == PropertyToKind::Kind; + }()); +#endif +}; + +struct property_key_base_tag {}; +struct compile_time_property_key_base_tag : property_key_base_tag {}; + +template +struct run_time_property_key : property_key_base_tag, + property_base { +protected: + static constexpr PropKind Kind = Kind_; + + template friend struct PropertyToKind; +}; + +template +struct compile_time_property_key : compile_time_property_key_base_tag { +protected: + static constexpr PropKind Kind = Kind_; + + template friend struct PropertyToKind; +}; + +// Get unique ID for property. +template struct PropertyID { + static constexpr int value = + static_cast(PropertyToKind::Kind); +}; + +} // namespace detail +} // namespace _V1 +} // namespace sycl diff --git a/sycl/include/sycl/ext/oneapi/experimental/cluster_group_prop.hpp b/sycl/include/sycl/ext/oneapi/experimental/cluster_group_prop.hpp index 8bfe2ac56df15..32773318fc9cf 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/cluster_group_prop.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/cluster_group_prop.hpp @@ -20,7 +20,7 @@ template struct cluster_size : ::sycl::ext::oneapi::experimental::detail::run_time_property_key< cluster_size, - ::sycl::ext::oneapi::experimental::detail::ClusterLaunch> { + ::sycl::ext::oneapi::experimental::detail::PropKind::ClusterLaunch> { cluster_size(const range &size) : size(size) {} sycl::range get_cluster_size() const { return size; } diff --git a/sycl/include/sycl/ext/oneapi/properties/property.hpp b/sycl/include/sycl/ext/oneapi/properties/property.hpp index 79eeff77841ba..2066498f47131 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property.hpp @@ -7,10 +7,10 @@ //===----------------------------------------------------------------------===// // HOW-TO: Add new compile-time property -// 1. Add a new enumerator to -// `sycl::ext::oneapi::experimental::detail::PropKind` representing the new -// property. Increment -// `sycl::ext::oneapi::experimental::detail::PropKind::PropKindSize`. +// 1. Add a new enumerator to `sycl::detail::PropKind` representing the new +// property (this is the shared engine registry in +// ). Increment +// `sycl::detail::PropKind::PropKindSize`. // 2. Define property key class inherited from // `detail::compile_time_property_key` with `value_t` that must be // `property_value` with the first template argument being the property @@ -71,9 +71,8 @@ template <> struct PropertyMetaInfo { *******************************************************************************/ // HOW-TO: Add new runtime property -// 1. Add a new enumerator to `sycl::ext::oneapi::detail::PropKind` -// representing the new property. Increment -// `sycl::ext::oneapi::experimental::detail::PropKind::PropKindSize` +// 1. Add a new enumerator to `sycl::detail::PropKind` representing the new +// property. Increment `sycl::detail::PropKind::PropKindSize` // 2. Define property class, inheriting from `detail::run_time_property_key`. // 3. Declare the property key as an alias to the property class. The name of // the key class must be the property name suffixed by `_key`, i.e. for a @@ -120,10 +119,10 @@ template <> struct is_property_key_of : std::true_type {}; #pragma once #include // for nullptr_t -#include // for uint32_t #include // for false_type #include +#include namespace sycl { inline namespace _V1 { @@ -140,130 +139,22 @@ inline constexpr bool is_property_list_v = is_property_list::value; namespace detail { -// List of all properties. -enum PropKind : uint32_t { - DeviceImageScope = 0, - HostAccess = 1, - WorkGroupSize = 2, - WorkGroupSizeHint = 3, - SubGroupSize = 4, - DeviceHas = 5, - Alignment = 6, - CacheConfig = 7, - UseRootSync = 8, - GRFSize = 9, - GRFSizeAutomatic = 10, - ESIMDL1CacheHint = 11, - ESIMDL2CacheHint = 12, - ESIMDL3CacheHint = 13, - UsmKind = 14, - CacheControlReadHint = 15, - CacheControlReadAssertion = 16, - CacheControlWrite = 17, - BuildOptions = 18, - BuildLog = 19, - FloatingPointControls = 20, - DataPlacement = 21, - ContiguousMemory = 22, - FullGroup = 23, - Naive = 24, - WorkGroupProgress = 25, - SubGroupProgress = 26, - WorkItemProgress = 27, - NDRangeKernel = 28, - SingleTaskKernel = 29, - IndirectlyCallable = 30, - CallsIndirectly = 31, - InputDataPlacement = 32, - OutputDataPlacement = 33, - IncludeFiles = 34, - RegisteredNames = 35, - ClusterLaunch = 36, - MaxWorkGroupSize = 37, - MaxLinearWorkGroupSize = 38, - Prefetch = 39, - Deterministic = 40, - InitializeToIdentity = 41, - WorkGroupScratchSize = 42, - Unaliased = 43, - EventMode = 44, - NativeLocalBlockIO = 45, - InitialThreshold = 46, - MaximumSize = 47, - ZeroInit = 48, - FastLink = 49, - EnableIPC = 50, - RegisterHostMemoryReadOnly = 51, - EnableProfiling = 52, - MaximumRegisters = 53, - MaximumRegistersAutomatic = 54, - // PropKindSize must always be the last value. - PropKindSize = 55, -}; - -template struct PropertyToKind { - static constexpr PropKind Kind = PropertyT::Kind; -}; - -struct property_tag {}; - -// This is used to implement has/get_property via inheritance queries. -template struct property_key_tag : property_tag {}; - -template -struct property_base : property_key_tag { - using key_t = property_key_t; - -protected: - constexpr property_t get_property_impl(property_key_tag) const { - return *static_cast(this); - } - - // For key_t access in error reporting specialization. - template friend class __SYCL_EBO properties; - -#if !defined(_MSC_VER) - // Temporary, to ensure new code matches previous behavior and to catch any - // silly copy-paste mistakes. MSVC can't compile it, but linux-only is - // enough for this temporary check. - static_assert([]() constexpr -> bool { - if constexpr (std::is_same_v) - // key_t is incomplete at this point for runtime properties. - return true; - else - return Kind == PropertyToKind::Kind; - }()); -#endif -}; - -struct property_key_base_tag {}; -struct compile_time_property_key_base_tag : property_key_base_tag {}; - -template -struct run_time_property_key : property_key_base_tag, - property_base { -protected: - static constexpr PropKind Kind = Kind_; - - template - friend struct PropertyToKind; -}; - -template -struct compile_time_property_key : compile_time_property_key_base_tag { -protected: - static constexpr PropKind Kind = Kind_; - - template - friend struct PropertyToKind; -}; - -// Get unique ID for property. -template struct PropertyID { - static constexpr int value = - static_cast(PropertyToKind::Kind); -}; +// The property-definition infrastructure has been promoted to the shared engine +// in so it can be reused by the KHR +// properties layer. Re-export exactly those names here (rather than a blanket +// `using namespace sycl::detail;`) so existing experimental code that refers to +// them via `experimental::detail::...` keeps working, without pulling the rest +// of `sycl::detail` into this namespace's lookup. +using sycl::detail::compile_time_property_key; +using sycl::detail::compile_time_property_key_base_tag; +using sycl::detail::property_base; +using sycl::detail::property_key_base_tag; +using sycl::detail::property_key_tag; +using sycl::detail::property_tag; +using sycl::detail::PropertyID; +using sycl::detail::PropertyToKind; +using sycl::detail::PropKind; +using sycl::detail::run_time_property_key; // Trait for property compile-time meta names and values. template struct PropertyMetaInfo { diff --git a/sycl/include/sycl/ext/oneapi/properties/property_value.hpp b/sycl/include/sycl/ext/oneapi/properties/property_value.hpp index fd0b718daa3f0..b7758bafc645d 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property_value.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property_value.hpp @@ -73,14 +73,18 @@ template struct is_property_value_of { }(); }; +} // namespace ext::oneapi::experimental + +// PropertyID's primary lives in the shared engine (`sycl::detail`), so this +// specialization for property_value must be declared there. namespace detail { // Specialization of PropertyID for propagating IDs through property_value. template -struct PropertyID> +struct PropertyID< + ext::oneapi::experimental::property_value> : PropertyID {}; } // namespace detail -} // namespace ext::oneapi::experimental } // namespace _V1 } // namespace sycl diff --git a/sycl/test/abi/sycl_classes_abi_neutral_test.cpp b/sycl/test/abi/sycl_classes_abi_neutral_test.cpp index 9ecc45593f6de..ebcead0148105 100644 --- a/sycl/test/abi/sycl_classes_abi_neutral_test.cpp +++ b/sycl/test/abi/sycl_classes_abi_neutral_test.cpp @@ -16,7 +16,7 @@ // member is not crossing ABI boundary. All current exclusions are listed below. // CHECK: 0 | struct sycl::ext::oneapi::experimental::build_options -// CHECK-NEXT: 0 | struct sycl::ext::oneapi::experimental::detail::run_time_property_key +// CHECK-NEXT: 0 | struct sycl::detail::run_time_property_key // CHECK: 0 | class std::vector > opts // CHECK-NEXT: 0 | struct std::_Vector_base, class std::allocator > > (base) // CHECK-NEXT: 0 | struct std::_Vector_base, class std::allocator > >::_Vector_impl _M_impl @@ -25,7 +25,7 @@ // CHECK-NEXT: 0 | {{(struct std::_Vector_base, class std::allocator > >::_Vector_impl_data \(base\)|pointer _M_start)}} // CHECK: 0 | struct sycl::ext::oneapi::experimental::include_files -// CHECK-NEXT: 0 | struct sycl::ext::oneapi::experimental::detail::run_time_property_key +// CHECK-NEXT: 0 | struct sycl::detail::run_time_property_key // CHECK: 0 | class std::vector, class std::basic_string > > record // CHECK-NEXT: 0 | struct std::_Vector_base, class std::basic_string >, class std::allocator, class std::basic_string > > > (base) // CHECK-NEXT: 0 | struct std::_Vector_base, class std::basic_string >, class std::allocator, class std::basic_string > > >::_Vector_impl _M_impl @@ -34,7 +34,7 @@ // CHECK-NEXT: 0 | {{(struct std::_Vector_base, class std::basic_string >, class std::allocator, class std::basic_string > > >::_Vector_impl_data \(base\)|pointer _M_start)}} // CHECK: 0 | struct sycl::ext::oneapi::experimental::registered_names -// CHECK-NEXT: 0 | struct sycl::ext::oneapi::experimental::detail::run_time_property_key +// CHECK-NEXT: 0 | struct sycl::detail::run_time_property_key // CHECK: 0 | class std::vector > names // CHECK-NEXT: 0 | struct std::_Vector_base, class std::allocator > > (base) // CHECK-NEXT: 0 | struct std::_Vector_base, class std::allocator > >::_Vector_impl _M_impl