Skip to content

Commit 61bd6a5

Browse files
[NFC][SYCL] Refactor merged_properties_t (#16093)
New `merge_properties` can work on property lists containing run-time properties as long as their keys don't conflict. That functionality isn't used anywhere as of now though, hence `NFC` tag.
1 parent 27dab62 commit 61bd6a5

File tree

3 files changed

+40
-104
lines changed

3 files changed

+40
-104
lines changed

sycl/include/sycl/ext/oneapi/properties/properties.hpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -343,19 +343,9 @@ template <typename... PropertyValueTs>
343343
using properties_t =
344344
properties<detail::properties_type_list<PropertyValueTs...>>;
345345

346-
// Helper for merging two property lists;
347346
template <typename LHSPropertiesT, typename RHSPropertiesT>
348-
struct merged_properties;
349-
template <typename... LHSPropertiesTs, typename... RHSPropertiesTs>
350-
struct merged_properties<properties_t<LHSPropertiesTs...>,
351-
properties_t<RHSPropertiesTs...>> {
352-
using type = properties<
353-
typename MergeProperties<properties_type_list<LHSPropertiesTs...>,
354-
properties_type_list<RHSPropertiesTs...>>::type>;
355-
};
356-
template <typename LHSPropertiesT, typename RHSPropertiesT>
357-
using merged_properties_t =
358-
typename merged_properties<LHSPropertiesT, RHSPropertiesT>::type;
347+
using merged_properties_t = decltype(merge_properties(
348+
std::declval<LHSPropertiesT>(), std::declval<RHSPropertiesT>()));
359349

360350
template <typename Properties, typename PropertyKey, typename Cond = void>
361351
struct ValueOrDefault {

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

Lines changed: 38 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ template <int N, typename... Ts>
4343
using nth_type_t = typename nth_type<N, Ts...>::type;
4444
#endif
4545

46-
template <typename T, typename PropList> struct PrependProperty {};
47-
template <typename T, typename... Ts>
48-
struct PrependProperty<T, properties_type_list<Ts...>> {
49-
using type = properties_type_list<T, Ts...>;
50-
};
51-
5246
//******************************************************************************
5347
// Property identification
5448
//******************************************************************************
@@ -63,91 +57,6 @@ struct AllPropertyValues<std::tuple<T, Ts...>>
6357
AllPropertyValues<std::tuple<Ts...>>,
6458
std::false_type> {};
6559

66-
//******************************************************************************
67-
// Property type sorting
68-
//******************************************************************************
69-
70-
// Splits a tuple into head and tail if ShouldSplit is true. If ShouldSplit is
71-
// false the head will be void and the tail will be the full tuple.
72-
template <typename T1, bool ShouldSplit> struct HeadSplit {};
73-
template <typename T, typename... Ts>
74-
struct HeadSplit<properties_type_list<T, Ts...>, true> {
75-
using htype = T;
76-
using ttype = properties_type_list<Ts...>;
77-
};
78-
template <typename... Ts> struct HeadSplit<properties_type_list<Ts...>, false> {
79-
using htype = void;
80-
using ttype = properties_type_list<Ts...>;
81-
};
82-
83-
// Selects the one of two types that is not void. This assumes that at least one
84-
// of the two template arguemnts is void.
85-
template <typename LHS, typename RHS> struct SelectNonVoid {};
86-
template <typename LHS> struct SelectNonVoid<LHS, void> {
87-
using type = LHS;
88-
};
89-
template <typename RHS> struct SelectNonVoid<void, RHS> {
90-
using type = RHS;
91-
};
92-
93-
//******************************************************************************
94-
// Property merging
95-
//******************************************************************************
96-
97-
// Merges two sets of properties, failing if two properties are the same but
98-
// with different values.
99-
// NOTE: This assumes that the properties are in sorted order.
100-
template <typename LHSPropertyT, typename RHSPropertyT> struct MergeProperties;
101-
102-
template <>
103-
struct MergeProperties<properties_type_list<>, properties_type_list<>> {
104-
using type = properties_type_list<>;
105-
};
106-
107-
template <typename... LHSPropertyTs>
108-
struct MergeProperties<properties_type_list<LHSPropertyTs...>,
109-
properties_type_list<>> {
110-
using type = properties_type_list<LHSPropertyTs...>;
111-
};
112-
113-
template <typename... RHSPropertyTs>
114-
struct MergeProperties<properties_type_list<>,
115-
properties_type_list<RHSPropertyTs...>> {
116-
using type = properties_type_list<RHSPropertyTs...>;
117-
};
118-
119-
// Identical properties are allowed, but only one will carry over.
120-
template <typename PropertyT, typename... LHSPropertyTs,
121-
typename... RHSPropertyTs>
122-
struct MergeProperties<properties_type_list<PropertyT, LHSPropertyTs...>,
123-
properties_type_list<PropertyT, RHSPropertyTs...>> {
124-
using merge_tails =
125-
typename MergeProperties<properties_type_list<LHSPropertyTs...>,
126-
properties_type_list<RHSPropertyTs...>>::type;
127-
using type = typename PrependProperty<PropertyT, merge_tails>::type;
128-
};
129-
130-
template <typename... LHSPropertyTs, typename... RHSPropertyTs>
131-
struct MergeProperties<properties_type_list<LHSPropertyTs...>,
132-
properties_type_list<RHSPropertyTs...>> {
133-
using l_head = nth_type_t<0, LHSPropertyTs...>;
134-
using r_head = nth_type_t<0, RHSPropertyTs...>;
135-
static_assert(
136-
PropertyID<l_head>::value != PropertyID<r_head>::value,
137-
"Failed to merge property lists due to conflicting properties.");
138-
static constexpr bool left_has_min =
139-
PropertyID<l_head>::value < PropertyID<r_head>::value;
140-
using l_split =
141-
HeadSplit<properties_type_list<LHSPropertyTs...>, left_has_min>;
142-
using r_split =
143-
HeadSplit<properties_type_list<RHSPropertyTs...>, !left_has_min>;
144-
using min = typename SelectNonVoid<typename l_split::htype,
145-
typename r_split::htype>::type;
146-
using merge_tails = typename MergeProperties<typename l_split::ttype,
147-
typename r_split::ttype>::type;
148-
using type = typename PrependProperty<min, merge_tails>::type;
149-
};
150-
15160
//******************************************************************************
15261
// Property value tooling
15362
//******************************************************************************
@@ -349,6 +258,44 @@ constexpr auto filter_properties(
349258
return filter_properties_impl<predicate, property_tys...>::apply(props);
350259
}
351260

261+
template <typename... lhs_property_tys> struct merge_filter {
262+
template <typename rhs_property_ty>
263+
struct predicate
264+
: std::bool_constant<!((std::is_same_v<typename lhs_property_tys::key_t,
265+
typename rhs_property_ty::key_t> ||
266+
...))> {};
267+
};
268+
269+
template <typename... lhs_property_tys, typename... rhs_property_tys>
270+
constexpr auto merge_properties(
271+
const properties<properties_type_list<lhs_property_tys...>> &lhs,
272+
const properties<properties_type_list<rhs_property_tys...>> &rhs) {
273+
auto rhs_unique_props =
274+
filter_properties<merge_filter<lhs_property_tys...>::template predicate>(
275+
rhs);
276+
if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>,
277+
std::decay_t<decltype(rhs_unique_props)>>) {
278+
// None of RHS properties share keys with LHS, no conflicts possible.
279+
return properties{
280+
lhs.template get_property<typename lhs_property_tys::key_t>()...,
281+
rhs.template get_property<typename rhs_property_tys::key_t>()...};
282+
} else {
283+
// Ensure no conflicts, then merge.
284+
constexpr auto has_conflict = [](auto *lhs_prop) constexpr {
285+
using lhs_property_ty = std::remove_pointer_t<decltype(lhs_prop)>;
286+
return (((std::is_same_v<typename lhs_property_ty::key_t,
287+
typename rhs_property_tys::key_t> &&
288+
(!std::is_same_v<lhs_property_ty, rhs_property_tys> ||
289+
!std::is_empty_v<lhs_property_ty>)) ||
290+
...));
291+
};
292+
static_assert(
293+
!((has_conflict(static_cast<lhs_property_tys *>(nullptr)) || ...)),
294+
"Failed to merge property lists due to conflicting properties.");
295+
return merge_properties(lhs, rhs_unique_props);
296+
}
297+
}
298+
352299
} // namespace detail
353300
} // namespace ext::oneapi::experimental
354301
} // namespace _V1

sycl/test/extensions/properties/properties_kernel_negative.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ void check_work_group_size() {
8383
sycl::queue Q;
8484

8585
// expected-error-re@sycl/ext/oneapi/properties/property_utils.hpp:* {{static assertion failed due to requirement {{.+}}: Failed to merge property lists due to conflicting properties.}}
86-
// expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.+}}: Template type is not a property list.}}
8786
// expected-note-re@+1 {{in instantiation of function template specialization {{.+}}}}
8887
Q.single_task(
8988
sycl::ext::oneapi::experimental::properties{

0 commit comments

Comments
 (0)