Skip to content

Commit 17fe53c

Browse files
committed
Disallow SYCL 2020 properties and add runtime properties
Runtime properties for the new property lists need to be seperately defined from the ones defined in SYCL 2020. These changes remove the support for SYCL 2020 properties in the compile-time property_list and adds the notion of runtime properties as a separate system. Signed-off-by: Steffen Larsen <[email protected]>
1 parent 9601c4c commit 17fe53c

12 files changed

+310
-179
lines changed

sycl/include/CL/sycl/detail/property_helper.hpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,14 @@ enum PropWithDataKind {
4949
PropWithDataKindSize = 5
5050
};
5151

52-
// Base class for all properties to expose a unique ID.
53-
template <int ID> class IdentifyablePropertyBase {
54-
public:
55-
static constexpr int PropertyID = ID;
56-
};
57-
5852
// Base class for dataless properties, needed to check that the type of an
5953
// object passed to the property_list is a property.
6054
class DataLessPropertyBase {};
6155

6256
// Helper class for the dataless properties. Every such property is supposed
6357
// to inherit from it. The ID template parameter should be one from
6458
// DataLessPropKind.
65-
template <int ID>
66-
class DataLessProperty : DataLessPropertyBase,
67-
public IdentifyablePropertyBase<ID> {
59+
template <int ID> class DataLessProperty : DataLessPropertyBase {
6860
public:
6961
static constexpr int getKind() { return ID; }
7062
};
@@ -85,11 +77,7 @@ class PropertyWithDataBase {
8577
// Helper class for the properties with data. Every such property is supposed
8678
// to inherit from it. The ID template parameter should be one from
8779
// PropWithDataKind.
88-
template <int ID>
89-
class PropertyWithData
90-
: public PropertyWithDataBase,
91-
public IdentifyablePropertyBase<
92-
ID + static_cast<int>(DataLessPropKind::DataLessPropKindSize)> {
80+
template <int ID> class PropertyWithData : public PropertyWithDataBase {
9381
public:
9482
PropertyWithData() : PropertyWithDataBase(ID) {}
9583
static int getKind() { return ID; }
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
//==---------- properties.hpp --- SYCL extension property tooling ----------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// HOW-TO: Add new compile-time property
10+
// 1. Add a new enumerator to `sycl::ext::oneapi::detail::PropKind`
11+
// representing the new property. Increment
12+
// `sycl::ext::oneapi::detail::PropKind::PropKindSize`
13+
// 2. Define property class with `value_t` that must be `property_value` with
14+
// the first template argument being the property class itself.
15+
// 3. Add an `inline constexpr` variable in the same namespace as the property.
16+
// The variable should have the same type as `value_t` of the property class
17+
// and should be named as the property class with `_v` appended, e.g. for a
18+
// property `foo`, there should be a definition
19+
// `inline constexpr foo::value_t foo_v`.
20+
// 4. Specialize `sycl::ext::oneapi::detail::PropertyToKind` for the new
21+
// property class. The specialization should have a `Kind` member with the
22+
// value equal to the enumerator added in 1.
23+
// 5. Specialize `sycl::ext::oneapi::detail::IsCompileTimeProperty` for the new
24+
// property class. This specialization should derive from `std::true_type`.
25+
// 6. Specialize `sycl::is_property` and `sycl::is_property_of` for the
26+
// property class.
27+
/******************************** EXAMPLE **************************************
28+
---------- sycl/include/sycl/ext/oneapi/property_list/properties.hpp -----------
29+
// (1.)
30+
enum PropKind : uint32_t {
31+
...
32+
Bar,
33+
PropKindSize = N + 1, // N was the previous value
34+
};
35+
---------------------- path/to/new/property/file.hpp ---------------------------
36+
namespace sycl {
37+
namespace ext {
38+
namespace oneapi {
39+
40+
// (2.)
41+
struct bar {
42+
using value_t = property_value<bar>;
43+
};
44+
45+
// (3.)
46+
inline constexpr bar::value_t bar_v;
47+
48+
namespace detail {
49+
50+
// (4.)
51+
template <> struct PropertyToKind<bar> {
52+
static constexpr PropKind Kind = PropKind::Bar;
53+
};
54+
55+
// (5.)
56+
template <> struct IsCompileTimeProperty<bar> : std::true_type {};
57+
58+
} // namespace detail
59+
} // namespace oneapi
60+
} // namespace ext
61+
62+
// (6.)
63+
template <> struct is_property<ext::oneapi::bar> : std::true_type {};
64+
// Replace SYCL_OBJ with the SYCL object to support the property.
65+
template <> struct is_property_of<ext::oneapi::bar, SYCL_OBJ>
66+
: std::true_type {};
67+
68+
} // namespace sycl
69+
*******************************************************************************/
70+
71+
// HOW-TO: Add new runtime property
72+
// 1. Add a new enumerator to `sycl::ext::oneapi::detail::PropKind`
73+
// representing the new property. Increment
74+
// `sycl::ext::oneapi::detail::PropKind::PropKindSize`
75+
// 2. Define property class.
76+
// 3. Overload the `==` and `!=` operators for the new property class. The
77+
// comparison should compare all data members of the property class.
78+
// 4. Specialize `sycl::ext::oneapi::detail::PropertyToKind` for the new
79+
// property class. The specialization should have a `Kind` member with the
80+
// value equal to the enumerator added in 1.
81+
// 5. Specialize `sycl::ext::oneapi::detail::IsRuntimeProperty` for the new
82+
// property class. This specialization should derive from `std::true_type`.
83+
// 6. Specialize `sycl::is_property` and `sycl::is_property_of` for the
84+
// property class.
85+
/******************************* EXAMPLE ***************************************
86+
---------- sycl/include/sycl/ext/oneapi/property_list/properties.hpp -----------
87+
// (1.)
88+
enum PropKind : uint32_t {
89+
...
90+
Foo,
91+
PropKindSize = N + 1, // N was the previous value
92+
};
93+
---------------------- path/to/new/property/file.hpp ---------------------------
94+
namespace sycl {
95+
namespace ext {
96+
namespace oneapi {
97+
98+
// (2.)
99+
struct foo {
100+
foo(int v) : value(v) {}
101+
int value;
102+
};
103+
104+
// (3.)
105+
inline bool operator==(const foo &lhs, const foo &rhs) {
106+
return lhs.value == rhs.value;
107+
}
108+
inline bool operator!=(const foo &lhs, const foo &rhs) {
109+
return !(lhs == rhs);
110+
}
111+
112+
namespace detail {
113+
114+
// (4.)
115+
template <> struct PropertyToKind<foo> {
116+
static constexpr PropKind Kind = PropKind::Foo;
117+
};
118+
119+
// (5.)
120+
template <> struct IsRuntimeProperty<foo> : std::true_type {};
121+
} // namespace detail
122+
} // namespace oneapi
123+
} // namespace ext
124+
125+
// (6.)
126+
template <> struct is_property<ext::oneapi::foo> : std::true_type {};
127+
// Replace SYCL_OBJ with the SYCL object to support the property.
128+
template <> struct is_property_of<ext::oneapi::foo, SYCL_OBJ>
129+
: std::true_type {};
130+
131+
} // namespace sycl
132+
*******************************************************************************/
133+
134+
#pragma once
135+
136+
__SYCL_INLINE_NAMESPACE(cl) {
137+
namespace sycl {
138+
namespace ext {
139+
namespace oneapi {
140+
namespace detail {
141+
142+
// List of all properties.
143+
enum PropKind : uint32_t {
144+
PropKindSize = 0,
145+
};
146+
147+
// This trait must be specialized for all properties and must have a unique
148+
// constexpr PropKind member named Kind.
149+
template <typename PropertyT> struct PropertyToKind {};
150+
151+
// Get unique ID for property.
152+
template <typename PropertyT> struct PropertyID {
153+
static constexpr int value =
154+
static_cast<int>(PropertyToKind<PropertyT>::Kind);
155+
};
156+
157+
// Trait for identifying runtime properties.
158+
template <typename PropertyT> struct IsRuntimeProperty : std::false_type {};
159+
160+
// Trait for identifying compile-time properties.
161+
template <typename PropertyT> struct IsCompileTimeProperty : std::false_type {};
162+
163+
} // namespace detail
164+
} // namespace oneapi
165+
} // namespace ext
166+
} // namespace sycl
167+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/sycl/ext/oneapi/property_list/property_list.hpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <CL/sycl/detail/property_helper.hpp>
1212
#include <CL/sycl/types.hpp>
13+
#include <sycl/ext/oneapi/property_list/properties.hpp>
1314
#include <sycl/ext/oneapi/property_list/property_utils.hpp>
1415
#include <sycl/ext/oneapi/property_list/property_value.hpp>
1516

@@ -64,7 +65,7 @@ template <typename... Ts> struct RuntimePropertyStorage<std::tuple<Ts...>> {
6465
};
6566
template <typename T, typename... Ts>
6667
struct RuntimePropertyStorage<std::tuple<T, Ts...>>
67-
: detail::conditional_t<IsRuntimePropertyWithData<T>::value,
68+
: detail::conditional_t<IsRuntimeProperty<T>::value,
6869
PrependTuple<T, typename RuntimePropertyStorage<
6970
std::tuple<Ts...>>::type>,
7071
RuntimePropertyStorage<std::tuple<Ts...>>> {};
@@ -112,7 +113,7 @@ struct ExtractProperties<std::tuple<PropertyT, PropertiesTs...>> {
112113
template <typename PropertiesT> class property_list {
113114
static_assert(detail::IsTuple<PropertiesT>::value,
114115
"Properties must be in a tuple.");
115-
static_assert(detail::AllProperties<PropertiesT>::value,
116+
static_assert(detail::AllPropertyValues<PropertiesT>::value,
116117
"Unrecognized property in property list.");
117118
static_assert(detail::IsSorted<PropertiesT>::value,
118119
"Properties in property list are not sorted.");
@@ -126,30 +127,21 @@ template <typename PropertiesT> class property_list {
126127
std::tuple<PropertyValueTs...>{props...})) {}
127128

128129
template <typename PropertyT>
129-
static constexpr detail::enable_if_t<
130-
detail::IntrospectiveIsProperty<PropertyT>::value, bool>
130+
static constexpr detail::enable_if_t<detail::IsProperty<PropertyT>::value,
131+
bool>
131132
has_property() {
132133
return detail::ContainsProperty<PropertyT, PropertiesT>::value;
133134
}
134135

135136
template <typename PropertyT>
136-
typename detail::enable_if_t<
137-
detail::IsRuntimePropertyWithData<PropertyT>::value, PropertyT>
137+
typename detail::enable_if_t<detail::IsRuntimeProperty<PropertyT>::value,
138+
PropertyT>
138139
get_property() const {
139140
static_assert(has_property<PropertyT>(),
140141
"Property list does not contain the requested property.");
141142
return std::get<PropertyT>(Storage);
142143
}
143144

144-
template <typename PropertyT>
145-
typename detail::enable_if_t<
146-
detail::IsRuntimeDatalessProperty<PropertyT>::value, PropertyT>
147-
get_property() const {
148-
static_assert(has_property<PropertyT>(),
149-
"Property list does not contain the requested property.");
150-
return {};
151-
}
152-
153145
template <typename PropertyT>
154146
static constexpr auto get_property(
155147
typename std::enable_if_t<detail::IsCompileTimeProperty<PropertyT>::value>

sycl/include/sycl/ext/oneapi/property_list/property_utils.hpp

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#pragma once
1010

1111
#include <CL/sycl/detail/property_helper.hpp>
12+
#include <sycl/ext/oneapi/property_list/properties.hpp>
1213

1314
#include <tuple>
1415

@@ -53,58 +54,42 @@ struct AllUnique<std::tuple<Ts...>> : std::true_type {};
5354
template <typename T> struct AllUnique<std::tuple<T>> : std::true_type {};
5455
template <typename L, typename R, typename... Rest>
5556
struct AllUnique<std::tuple<L, R, Rest...>>
56-
: detail::conditional_t<L::PropertyID != R::PropertyID,
57+
: detail::conditional_t<PropertyID<L>::value != PropertyID<R>::value,
5758
AllUnique<std::tuple<R, Rest...>>,
5859
std::false_type> {};
5960

6061
//******************************************************************************
6162
// Property identification
6263
//******************************************************************************
6364

64-
// Checks if a type is a runtime property with data.
65-
template <typename T> struct IsRuntimePropertyWithData {
66-
static constexpr bool value =
67-
is_property<T>::value && std::is_base_of<PropertyWithDataBase, T>::value;
68-
};
65+
// Checks if a type is a compile-time property values.
66+
// Note: This is specialized for property_value elsewhere.
67+
template <typename PropertyT>
68+
struct IsCompileTimePropertyValue : std::false_type {};
6969

70-
// Checks if a type is a dataless runtime property.
71-
template <typename T> struct IsRuntimeDatalessProperty {
70+
// Checks if a type is either a runtime property or if it is a compile-time
71+
// property
72+
template <typename T> struct IsProperty {
7273
static constexpr bool value =
73-
is_property<T>::value && std::is_base_of<DataLessPropertyBase, T>::value;
74+
IsRuntimeProperty<T>::value || IsCompileTimeProperty<T>::value;
7475
};
7576

76-
// Checks if a type is a runtime property.
77-
template <typename T> struct IsRuntimeProperty {
78-
static constexpr bool value =
79-
is_property<T>::value &&
80-
(std::is_base_of<DataLessPropertyBase, T>::value ||
81-
std::is_base_of<PropertyWithDataBase, T>::value);
82-
};
83-
84-
// Checks if a type is either a runtime property (with or without data) or if
85-
// it is a compile-time property (inside a property_value)
86-
template <typename T> struct IntrospectiveIsProperty : is_property<T> {};
87-
template <typename PropertyT, typename... PropertyValueTs>
88-
struct IntrospectiveIsProperty<property_value<PropertyT, PropertyValueTs...>>
89-
: is_property<PropertyT> {};
90-
91-
// Checks that a type is a compile-time property. value is true if either T is
92-
// a non-runtime property or if it is a property_value containing a non-runtime
93-
// property.
94-
template <typename T> struct IsCompileTimeProperty {
77+
// Checks if a type is a valid property value, i.e either runtime property or
78+
// property_value with a valid compile-time property
79+
template <typename T> struct IsPropertyValue {
9580
static constexpr bool value =
96-
IntrospectiveIsProperty<T>::value && !IsRuntimeProperty<T>::value;
81+
IsRuntimeProperty<T>::value || IsCompileTimePropertyValue<T>::value;
9782
};
9883

9984
// Checks that all types in a tuple are valid properties.
100-
template <typename T> struct AllProperties {};
85+
template <typename T> struct AllPropertyValues {};
10186
template <typename... Ts>
102-
struct AllProperties<std::tuple<Ts...>> : std::true_type {};
87+
struct AllPropertyValues<std::tuple<Ts...>> : std::true_type {};
10388
template <typename T, typename... Ts>
104-
struct AllProperties<std::tuple<T, Ts...>>
105-
: detail::conditional_t<IntrospectiveIsProperty<T>::value,
106-
AllProperties<std::tuple<Ts...>>, std::false_type> {
107-
};
89+
struct AllPropertyValues<std::tuple<T, Ts...>>
90+
: detail::conditional_t<IsPropertyValue<T>::value,
91+
AllPropertyValues<std::tuple<Ts...>>,
92+
std::false_type> {};
10893

10994
//******************************************************************************
11095
// Property type sorting
@@ -143,7 +128,8 @@ template <typename... LTs, typename... RTs>
143128
struct Merge<std::tuple<LTs...>, std::tuple<RTs...>> {
144129
using l_head = GetFirstType<LTs...>;
145130
using r_head = GetFirstType<RTs...>;
146-
static constexpr bool left_has_min = l_head::PropertyID < r_head::PropertyID;
131+
static constexpr bool left_has_min =
132+
PropertyID<l_head>::value < PropertyID<r_head>::value;
147133
using l_split = HeadSplit<std::tuple<LTs...>, left_has_min>;
148134
using r_split = HeadSplit<std::tuple<RTs...>, !left_has_min>;
149135
using min = typename SelectNonVoid<typename l_split::htype,
@@ -209,7 +195,7 @@ template <typename T, typename... Ts> struct MergeAll<std::tuple<T, Ts...>> {
209195

210196
// Performs merge-sort on types with PropertyID.
211197
template <typename... Ts> struct Sorted {
212-
static_assert(detail::AllProperties<std::tuple<Ts...>>::value,
198+
static_assert(detail::AllPropertyValues<std::tuple<Ts...>>::value,
213199
"Unrecognized property in property list.");
214200
using split = typename CreateTuplePairs<Ts...>::type;
215201
using type = typename MergeAll<split>::type;
@@ -222,7 +208,7 @@ struct IsSorted<std::tuple<Ts...>> : std::true_type {};
222208
template <typename T> struct IsSorted<std::tuple<T>> : std::true_type {};
223209
template <typename L, typename R, typename... Rest>
224210
struct IsSorted<std::tuple<L, R, Rest...>>
225-
: detail::conditional_t<L::PropertyID <= R::PropertyID,
211+
: detail::conditional_t<PropertyID<L>::value <= PropertyID<R>::value,
226212
IsSorted<std::tuple<R, Rest...>>, std::false_type> {
227213
};
228214

0 commit comments

Comments
 (0)