diff --git a/sycl/doc/extensions/experimental/sycl_ext_oneapi_properties.asciidoc b/sycl/doc/extensions/experimental/sycl_ext_oneapi_properties.asciidoc index 82c6d6fb454c6..4db1aa8fe7ca7 100644 --- a/sycl/doc/extensions/experimental/sycl_ext_oneapi_properties.asciidoc +++ b/sycl/doc/extensions/experimental/sycl_ext_oneapi_properties.asciidoc @@ -99,8 +99,7 @@ The intention is to provide a robust mechanism with which to pass compile-time-c property:: A property is represented by a key and value. Properties can be used to provide extra values to classes or functions. property value:: An object of the property value class. A property value has zero or more property parameters. -For runtime properties the value type is the same as the key type. -For compile time properties the value type is given by the `value_t` type alias of the key type. +The value type is given by the `value_t` type alias of the key type. property key:: A class representing the property key. It is used to query properties. @@ -138,27 +137,33 @@ value to determine which of the extension's APIs the implementation supports. Properties have a value and key type, and by convention, these classes are declared in the root of the -`sycl::ext::oneapi::experimental` namespace. For a runtime property the key and value types are the same and the name of the property value -class has no suffix. A runtime property value typically has a constructor +`sycl::ext::oneapi::experimental` namespace. +The value type is a template specialization of `property_value`. +The property key class contains a `value_t` alias which is templated on the property parameters. + +A runtime property value typically has a constructor which takes the value(s) of the properties and member function(s) which return those values. ```c++ namespace sycl::ext::oneapi::experimental { +// The runtime property key +struct foo_key { + using value_t = property_value; +}; // This is a runtime property value with one integer parameter. // The name of the property value class is the the name of the property without any suffix. -struct foo { - foo(int); +using foo = property_value; +template <> struct property_value { + using key_t = foo_key; + constexpr property_value(int v) : value(v) {} int value; }; -// A runtime property key is an alias to the value type. -using foo_key = foo; } // namespace experimental::oneapi::ext::sycl ``` -For compile-time constant parameters the value type is a template specialization of `property_value`. -The property key class contains a `value_t` alias which is templated on the property parameters. The `property_value` class holds the +For compile-time constant parameters the `property_value` class holds the values of the compile-time parameters as template arguments. The parameters to a compile- time-constant property can be either types or non-type values. The implementation provides a variable with the property value type. The variable has the name of the property without a suffix. diff --git a/sycl/include/sycl/ext/intel/experimental/kernel_execution_properties.hpp b/sycl/include/sycl/ext/intel/experimental/kernel_execution_properties.hpp index 42e8bdc88c035..48873138e5bc2 100644 --- a/sycl/include/sycl/ext/intel/experimental/kernel_execution_properties.hpp +++ b/sycl/include/sycl/ext/intel/experimental/kernel_execution_properties.hpp @@ -26,12 +26,19 @@ inline constexpr cache_config_enum large_slm = inline constexpr cache_config_enum large_data = cache_config_enum::large_data; -struct cache_config { - cache_config(cache_config_enum v) : value(v) {} - cache_config_enum value; +struct cache_config_key { + using value_t = oneapi::experimental::property_value; }; - -using cache_config_key = cache_config; +using cache_config = cache_config_key::value_t; +} // namespace ext::intel::experimental +namespace ext::oneapi::experimental { +template <> struct property_value { + using key_t = intel::experimental::cache_config_key; + property_value(intel::experimental::cache_config_enum v) : value(v) {} + intel::experimental::cache_config_enum value; +}; +} // namespace ext::oneapi::experimental +namespace ext::intel::experimental { inline bool operator==(const cache_config &lhs, const cache_config &rhs) { diff --git a/sycl/include/sycl/ext/oneapi/experimental/annotated_usm/alloc_util.hpp b/sycl/include/sycl/ext/oneapi/experimental/annotated_usm/alloc_util.hpp index 029b8a0eda5ad..d934f897a59dc 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/annotated_usm/alloc_util.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/annotated_usm/alloc_util.hpp @@ -106,8 +106,8 @@ struct ValidAllocPropertyList> is_valid_property::value, "Found invalid compile-time property in the property list."); // check if a runtime property is valid for malloc - static_assert(!detail::IsRuntimeProperty::value || - IsRuntimePropertyValid::value, + static_assert(!detail::IsRuntimePropertyValue::value || + IsRuntimePropertyValid::value, "Found invalid runtime property in the property list."); }; diff --git a/sycl/include/sycl/ext/oneapi/properties/properties.hpp b/sycl/include/sycl/ext/oneapi/properties/properties.hpp index d3cca173c630f..8d74fde575a9d 100644 --- a/sycl/include/sycl/ext/oneapi/properties/properties.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/properties.hpp @@ -77,7 +77,7 @@ template struct RuntimePropertyStorage> { }; template struct RuntimePropertyStorage> - : std::conditional_t::value, + : std::conditional_t::value, PrependTuple>::type>, RuntimePropertyStorage>> {}; @@ -149,9 +149,9 @@ template class properties { template typename std::enable_if_t::value && has_property(), - PropertyT> + typename PropertyT::value_t> get_property() const { - return std::get(Storage); + return std::get(Storage); } template @@ -254,16 +254,15 @@ struct all_props_are_keys_of< template struct all_props_are_keys_of< SyclT, ext::oneapi::experimental::properties>> - : std::bool_constant< - ext::oneapi::experimental::is_property_key_of::value> { -}; + : std::bool_constant::value> {}; template struct all_props_are_keys_of< SyclT, ext::oneapi::experimental::properties>> - : std::bool_constant< - ext::oneapi::experimental::is_property_key_of::value && - all_props_are_keys_of()> {}; + : std::bool_constant::value && + all_props_are_keys_of()> {}; } // namespace detail } // namespace ext::oneapi::experimental diff --git a/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp b/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp index 804dc6f4279cd..c26cd31bb96e9 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp @@ -62,6 +62,8 @@ struct HasValue : std::true_type {}; template struct IsCompileTimePropertyValue : std::false_type {}; +template +struct IsRuntimePropertyValue : std::false_type {}; // Checks if a type is either a runtime property or if it is a compile-time // property template struct IsProperty { @@ -73,7 +75,7 @@ template struct IsProperty { // property_value with a valid compile-time property template struct IsPropertyValue { static constexpr bool value = - IsRuntimeProperty::value || IsCompileTimePropertyValue::value; + IsRuntimePropertyValue::value || IsCompileTimePropertyValue::value; }; // Checks that all types in a tuple are valid properties. diff --git a/sycl/include/sycl/ext/oneapi/properties/property_value.hpp b/sycl/include/sycl/ext/oneapi/properties/property_value.hpp index e208f59d85830..f5847fa8fc055 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property_value.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property_value.hpp @@ -57,15 +57,11 @@ operator!=(const property_value &, return (!std::is_same::value || ...); } -template struct is_property_value { - static constexpr bool value = - detail::IsRuntimeProperty::value && is_property_key::value; -}; -template struct is_property_value_of { - static constexpr bool value = - detail::IsRuntimeProperty::value && is_property_key_of::value; -}; -// Specialization for compile-time-constant properties +template +struct is_property_value : std::false_type {}; +template +struct is_property_value_of : std::false_type {}; +// Specialization for properties template struct is_property_value> : is_property_key {}; @@ -85,6 +81,10 @@ template struct IsCompileTimePropertyValue> : IsCompileTimeProperty {}; +template +struct IsRuntimePropertyValue> + : IsRuntimeProperty {}; + } // namespace detail } // namespace ext::oneapi::experimental } // namespace _V1 diff --git a/sycl/include/sycl/kernel_bundle.hpp b/sycl/include/sycl/kernel_bundle.hpp index b2893854a79d4..7af2ce7304498 100644 --- a/sycl/include/sycl/kernel_bundle.hpp +++ b/sycl/include/sycl/kernel_bundle.hpp @@ -813,12 +813,16 @@ namespace ext::oneapi::experimental { ///////////////////////// // PropertyT syclex::build_options ///////////////////////// -struct build_options { +struct build_options_key { + using value_t = property_value; +}; +using build_options = property_value; +template <> struct property_value { + using key_t = build_options_key; std::vector opts; - build_options(const std::string &optsArg) : opts{optsArg} {} - build_options(const std::vector &optsArg) : opts(optsArg) {} + property_value(const std::string &optsArg) : opts{optsArg} {} + property_value(const std::vector &optsArg) : opts(optsArg) {} }; -using build_options_key = build_options; template <> struct is_property_key : std::true_type {}; @@ -847,12 +851,15 @@ struct IsCompileTimeProperty ///////////////////////// // PropertyT syclex::save_log ///////////////////////// -struct save_log { +struct save_log_key { + using value_t = property_value; +}; +using save_log = property_value; +template <> struct property_value { + using key_t = save_log_key; std::string *log; - save_log(std::string *logArg) : log(logArg) {} + property_value(std::string *logArg) : log(logArg) {} }; -using save_log_key = save_log; - template <> struct is_property_key : std::true_type {}; template <> @@ -917,11 +924,11 @@ build(kernel_bundle &SourceKB, const std::vector &Devices, PropertyListT props = {}) { std::vector BuildOptionsVec; std::string *LogPtr = nullptr; - if constexpr (props.template has_property()) { - BuildOptionsVec = props.template get_property().opts; + if constexpr (props.template has_property()) { + BuildOptionsVec = props.template get_property().opts; } - if constexpr (props.template has_property()) { - LogPtr = props.template get_property().log; + if constexpr (props.template has_property()) { + LogPtr = props.template get_property().log; } return detail::build_from_source(SourceKB, Devices, BuildOptionsVec, LogPtr); } diff --git a/sycl/test/extensions/annotated_usm/fake_properties.hpp b/sycl/test/extensions/annotated_usm/fake_properties.hpp index 06a026e48c9b5..fb5f00450e0ec 100644 --- a/sycl/test/extensions/annotated_usm/fake_properties.hpp +++ b/sycl/test/extensions/annotated_usm/fake_properties.hpp @@ -69,85 +69,70 @@ template <> struct IsCompileTimeProperty : std::true_type {}; // Runtime properties enum foo_enum : unsigned { a, b, c }; -struct foo { - constexpr foo(foo_enum v) : value(v) {} +struct foo_key { + using value_t = property_value; +}; +using foo = property_value; +template <> struct property_value { + using key_t = foo_key; + constexpr property_value(foo_enum v) : value(v) {} foo_enum value; }; -struct foz { +struct foz_key { + using value_t = property_value; +}; +using foz = property_value; +template <> struct property_value { + using key_t = foz_key; float value1; bool value2; }; -struct rt_prop1 {}; -struct rt_prop2 {}; -struct rt_prop3 {}; -struct rt_prop4 {}; -struct rt_prop5 {}; -struct rt_prop6 {}; -struct rt_prop7 {}; -struct rt_prop8 {}; -struct rt_prop9 {}; -struct rt_prop10 {}; -struct rt_prop11 {}; -struct rt_prop12 {}; -struct rt_prop13 {}; -struct rt_prop14 {}; -struct rt_prop15 {}; -struct rt_prop16 {}; -struct rt_prop17 {}; -struct rt_prop18 {}; -struct rt_prop19 {}; -struct rt_prop20 {}; -struct rt_prop21 {}; -struct rt_prop22 {}; -struct rt_prop23 {}; -struct rt_prop24 {}; -struct rt_prop25 {}; -struct rt_prop26 {}; -struct rt_prop27 {}; -struct rt_prop28 {}; -struct rt_prop29 {}; -struct rt_prop30 {}; -struct rt_prop31 {}; -struct rt_prop32 {}; -struct rt_prop33 {}; +#define rt_prop(N) \ + struct rt_prop##N##_key { \ + using value_t = property_value; \ + }; \ + using rt_prop##N = property_value; \ + template <> struct property_value { \ + using key_t = rt_prop##N##_key; \ + } + +rt_prop(1); +rt_prop(2); +rt_prop(3); +rt_prop(4); +rt_prop(5); +rt_prop(6); +rt_prop(7); +rt_prop(8); +rt_prop(9); +rt_prop(10); +rt_prop(11); +rt_prop(12); +rt_prop(13); +rt_prop(14); +rt_prop(15); +rt_prop(16); +rt_prop(17); +rt_prop(18); +rt_prop(19); +rt_prop(20); +rt_prop(21); +rt_prop(22); +rt_prop(23); +rt_prop(24); +rt_prop(25); +rt_prop(26); +rt_prop(27); +rt_prop(28); +rt_prop(29); +rt_prop(30); +rt_prop(31); +rt_prop(32); +rt_prop(33); -using foo_key = foo; -using foz_key = foz; -using rt_prop1_key = rt_prop1; -using rt_prop2_key = rt_prop2; -using rt_prop3_key = rt_prop3; -using rt_prop4_key = rt_prop4; -using rt_prop5_key = rt_prop5; -using rt_prop6_key = rt_prop6; -using rt_prop7_key = rt_prop7; -using rt_prop8_key = rt_prop8; -using rt_prop9_key = rt_prop9; -using rt_prop10_key = rt_prop10; -using rt_prop11_key = rt_prop11; -using rt_prop12_key = rt_prop12; -using rt_prop13_key = rt_prop13; -using rt_prop14_key = rt_prop14; -using rt_prop15_key = rt_prop15; -using rt_prop16_key = rt_prop16; -using rt_prop17_key = rt_prop17; -using rt_prop18_key = rt_prop18; -using rt_prop19_key = rt_prop19; -using rt_prop20_key = rt_prop20; -using rt_prop21_key = rt_prop21; -using rt_prop22_key = rt_prop22; -using rt_prop23_key = rt_prop23; -using rt_prop24_key = rt_prop24; -using rt_prop25_key = rt_prop25; -using rt_prop26_key = rt_prop26; -using rt_prop27_key = rt_prop27; -using rt_prop28_key = rt_prop28; -using rt_prop29_key = rt_prop29; -using rt_prop30_key = rt_prop30; -using rt_prop31_key = rt_prop31; -using rt_prop32_key = rt_prop32; -using rt_prop33_key = rt_prop33; +#undef rt_prop template <> struct is_property_key : std::true_type {}; template <> struct is_property_key : std::true_type {}; diff --git a/sycl/test/extensions/properties/mock_compile_time_properties.hpp b/sycl/test/extensions/properties/mock_compile_time_properties.hpp index 5e3bfed70e1d9..99840bb30a275 100644 --- a/sycl/test/extensions/properties/mock_compile_time_properties.hpp +++ b/sycl/test/extensions/properties/mock_compile_time_properties.hpp @@ -12,6 +12,8 @@ #pragma once +#include + namespace sycl { namespace ext { namespace oneapi { @@ -30,8 +32,13 @@ struct boo_key { template using value_t = property_value; }; -struct foo { - constexpr foo(int v) : value(v) {} +struct foo_key { + using value_t = property_value; +}; +using foo = property_value; +template <> struct property_value { + using key_t = foo_key; + constexpr property_value(int v) : value(v) {} int value; }; @@ -40,13 +47,15 @@ inline bool operator==(const foo &lhs, const foo &rhs) { } inline bool operator!=(const foo &lhs, const foo &rhs) { return !(lhs == rhs); } -struct foz { - constexpr foz(float v1, bool v2) : value1(v1), value2(v2) {} +struct foz_key { + using value_t = property_value; +}; +using foz = property_value; +template <> struct property_value { + using key_t = foz_key; + constexpr property_value(float v1, bool v2) : value1(v1), value2(v2) {} // Define copy constructor to make foz non-trivially copyable - constexpr foz(const foz &f) { - value1 = f.value1; - value2 = f.value2; - } + constexpr property_value(const foz &f) : value1(f.value1), value2(f.value2) {} float value1; bool value2; }; @@ -56,11 +65,16 @@ inline bool operator==(const foz &lhs, const foz &rhs) { } inline bool operator!=(const foz &lhs, const foz &rhs) { return !(lhs == rhs); } -struct fir { +struct fir_key { + using value_t = property_value; +}; +using fir = property_value; +template <> struct property_value { + using key_t = fir_key; // Intentionally not constexpr to test for properties that cannot be constexpr - fir(float v1, bool v2) : value1(v1), value2(v2) {} + property_value(float v1, bool v2) : value1(v1), value2(v2) {} // Define copy constructor to make foz non-trivially copyable - fir(const foz &f) { + property_value(const foz &f) { value1 = f.value1; value2 = f.value2; } @@ -77,10 +91,6 @@ inline constexpr bar_key::value_t bar; template inline constexpr baz_key::value_t baz; template inline constexpr boo_key::value_t boo; -using foo_key = foo; -using foz_key = foz; -using fir_key = fir; - template <> struct is_property_key : std::true_type {}; template <> struct is_property_key : std::true_type {}; template <> struct is_property_key : std::true_type {}; diff --git a/sycl/test/extensions/properties/properties_equality.cpp b/sycl/test/extensions/properties/properties_equality.cpp index 2a06bb0ce9fdf..0e2e730f109ca 100644 --- a/sycl/test/extensions/properties/properties_equality.cpp +++ b/sycl/test/extensions/properties/properties_equality.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning %s +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify %s // expected-no-diagnostics #include diff --git a/sycl/test/extensions/properties/properties_is_property_key.cpp b/sycl/test/extensions/properties/properties_is_property_key.cpp index 11c30d8c1eaa0..bfc04efcac559 100644 --- a/sycl/test/extensions/properties/properties_is_property_key.cpp +++ b/sycl/test/extensions/properties/properties_is_property_key.cpp @@ -33,13 +33,6 @@ int main() { !sycl::ext::oneapi::experimental::is_property_key< decltype(sycl::ext::oneapi::experimental::boo)>::value); - // Check is_property_key for runtime property values. - // NOTE: For runtime properties the key is an alias of the value. - static_assert(sycl::ext::oneapi::experimental::is_property_key< - sycl::ext::oneapi::experimental::foo>::value); - static_assert(sycl::ext::oneapi::experimental::is_property_key< - sycl::ext::oneapi::experimental::foz>::value); - // Check is_property_key for non-property-key types. static_assert(!sycl::ext::oneapi::experimental::is_property_key::value); static_assert(!sycl::ext::oneapi::experimental::is_property_key< @@ -73,11 +66,10 @@ int main() { sycl::queue>::value); // Check is_property_key_of for runtime property keys. - // NOTE: For runtime properties the key is an alias of the value. static_assert(sycl::ext::oneapi::experimental::is_property_key_of< - sycl::ext::oneapi::experimental::foo, sycl::queue>::value); + sycl::ext::oneapi::experimental::foo_key, sycl::queue>::value); static_assert(sycl::ext::oneapi::experimental::is_property_key_of< - sycl::ext::oneapi::experimental::foz, sycl::queue>::value); + sycl::ext::oneapi::experimental::foz_key, sycl::queue>::value); // Check is_property_key_of for non-property-key types. static_assert( diff --git a/sycl/test/extensions/properties/properties_is_property_value.cpp b/sycl/test/extensions/properties/properties_is_property_value.cpp index af07b8c24813c..986d40d5a6ff3 100644 --- a/sycl/test/extensions/properties/properties_is_property_value.cpp +++ b/sycl/test/extensions/properties/properties_is_property_value.cpp @@ -33,13 +33,6 @@ int main() { static_assert(!sycl::ext::oneapi::experimental::is_property_value< sycl::ext::oneapi::experimental::boo_key>::value); - // Check is_property_value for runtime property keys. - // NOTE: For runtime properties the key is an alias of the value. - static_assert(sycl::ext::oneapi::experimental::is_property_value< - sycl::ext::oneapi::experimental::foo_key>::value); - static_assert(sycl::ext::oneapi::experimental::is_property_value< - sycl::ext::oneapi::experimental::foz_key>::value); - // Check is_property_value for non-property-key types. static_assert( !sycl::ext::oneapi::experimental::is_property_value::value); @@ -73,13 +66,6 @@ int main() { static_assert(!sycl::ext::oneapi::experimental::is_property_value_of< sycl::ext::oneapi::experimental::boo_key, sycl::queue>::value); - // Check is_property_value_of for runtime property keys. - // NOTE: For runtime properties the key is an alias of the value. - static_assert(sycl::ext::oneapi::experimental::is_property_value_of< - sycl::ext::oneapi::experimental::foo_key, sycl::queue>::value); - static_assert(sycl::ext::oneapi::experimental::is_property_value_of< - sycl::ext::oneapi::experimental::foz_key, sycl::queue>::value); - // Check is_property_value_of for non-property-key types. static_assert(!sycl::ext::oneapi::experimental::is_property_value_of< int, sycl::queue>::value); diff --git a/sycl/test/extensions/properties/properties_kernel_cache_config.cpp b/sycl/test/extensions/properties/properties_kernel_cache_config.cpp index 910a41b49cfb9..fddf59518bdda 100644 --- a/sycl/test/extensions/properties/properties_kernel_cache_config.cpp +++ b/sycl/test/extensions/properties/properties_kernel_cache_config.cpp @@ -20,15 +20,15 @@ int main() { cache_config{large_slm}); using PS = decltype(Props1); static_assert(sycl::ext::oneapi::experimental::is_property_list_v); - static_assert(PS::has_property()); - assert(Props1.get_property() == large_slm); + static_assert(PS::has_property()); + assert(Props1.get_property() == large_slm); sycl::ext::oneapi::experimental::properties Props2( cache_config{large_data}); using PS = decltype(Props2); static_assert(sycl::ext::oneapi::experimental::is_property_list_v); - static_assert(PS::has_property()); - assert(Props2.get_property() == large_data); + static_assert(PS::has_property()); + assert(Props2.get_property() == large_data); // Check that duplicate cache_config can't be specified. // expected-error-re@sycl/ext/oneapi/properties/properties.hpp:* {{static assertion failed due to requirement {{.+}}: Duplicate properties in property list.}}