Skip to content

Commit 925ff76

Browse files
[NFC][SYCL] More consistent usage of detail::properties_t helper (#16142)
This also moves `filter|merge_properties` to `properties.hpp` to make this change a tiny bit easier/smaller, but that is a more suitable location for them anyway - it's strange to define operations on `properties` in a header that is included from a header implementing that same `properties` class.
1 parent 8b719e9 commit 925ff76

File tree

5 files changed

+126
-124
lines changed

5 files changed

+126
-124
lines changed

sycl/include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ annotated_arg(T, Args...)
6666
-> annotated_arg<T, typename detail::DeducedProperties<Args...>::type>;
6767

6868
template <typename T, typename old, typename... ArgT>
69-
annotated_arg(annotated_arg<T, old>,
70-
properties<detail::properties_type_list<ArgT...>>)
69+
annotated_arg(annotated_arg<T, old>, detail::properties_t<ArgT...>)
7170
-> annotated_arg<
7271
T, detail::merged_properties_t<old, detail::properties_t<ArgT...>>>;
7372

sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,7 @@ annotated_ptr(T *, Args...)
236236
-> annotated_ptr<T, typename detail::DeducedProperties<Args...>::type>;
237237

238238
template <typename T, typename old, typename... ArgT>
239-
annotated_ptr(annotated_ptr<T, old>,
240-
properties<detail::properties_type_list<ArgT...>>)
239+
annotated_ptr(annotated_ptr<T, old>, detail::properties_t<ArgT...>)
241240
-> annotated_ptr<
242241
T, detail::merged_properties_t<old, detail::properties_t<ArgT...>>>;
243242
#endif // __cpp_deduction_guides

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

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,30 @@ namespace sycl {
2121
inline namespace _V1 {
2222
namespace ext::oneapi::experimental {
2323

24+
template <typename properties_type_list_ty> class __SYCL_EBO properties;
25+
2426
namespace detail {
2527

28+
// NOTE: Meta-function to implement CTAD rules isn't allowed to return
29+
// `properties<something>` and it's impossible to return a pack as well. As
30+
// such, we're forced to have an extra level of `detail::properties_type_list`
31+
// for the purpose of providing CTAD rules.
32+
template <typename... property_tys> struct properties_type_list;
33+
34+
// This is used in a separate `properties` specialization to report friendlier
35+
// errors.
36+
template <typename... property_tys> struct invalid_properties_type_list {};
37+
38+
// Helper for reconstructing a properties type. This assumes that
39+
// PropertyValueTs is sorted and contains only valid properties.
40+
//
41+
// It also allows us to hide details of `properties` implementation from the
42+
// code that uses/defines them (with the exception of ESIMD which is extremely
43+
// hacky in its own esimd::properties piggybacking on these ones).
44+
template <typename... PropertyValueTs>
45+
using properties_t =
46+
properties<detail::properties_type_list<PropertyValueTs...>>;
47+
2648
template <typename... property_tys>
2749
inline constexpr bool properties_are_unique = []() constexpr {
2850
if constexpr (sizeof...(property_tys) == 0) {
@@ -66,9 +88,6 @@ constexpr bool properties_are_valid_for_ctad = []() constexpr {
6688
}
6789
}();
6890

69-
template <typename... property_tys> struct properties_type_list;
70-
template <typename... property_tys> struct invalid_properties_type_list {};
71-
7291
template <typename... property_tys> struct properties_sorter {
7392
// Not using "auto" due to MSVC bug in v19.36 and older. v19.37 and later is
7493
// able to compile "auto" just fine. See https://godbolt.org/z/eW3rjjs7n.
@@ -118,8 +137,6 @@ template <> struct properties_sorter<> {
118137

119138
} // namespace detail
120139

121-
template <typename properties_type_list_ty> class __SYCL_EBO properties;
122-
123140
// Empty property list.
124141
template <> class __SYCL_EBO properties<detail::properties_type_list<>> {
125142
template <typename T>
@@ -183,10 +200,6 @@ class __SYCL_EBO
183200
}
184201
};
185202

186-
// NOTE: Meta-function to implement CTAD rules isn't allowed to return
187-
// `properties<something>` and it's impossible to return a pack as well. As
188-
// such, we're forced to have an extra level of `detail::properties_type_list`
189-
// for the purpose of providing CTAD rules.
190203
template <typename... property_tys>
191204
class __SYCL_EBO properties<detail::properties_type_list<property_tys...>>
192205
: private property_tys... {
@@ -287,11 +300,85 @@ using empty_properties_t = decltype(properties{});
287300

288301
namespace detail {
289302

290-
// Helper for reconstructing a properties type. This assumes that
291-
// PropertyValueTs is sorted and contains only valid properties.
292-
template <typename... PropertyValueTs>
293-
using properties_t =
294-
properties<detail::properties_type_list<PropertyValueTs...>>;
303+
template <template <typename> typename predicate, typename... property_tys>
304+
struct filter_properties_impl {
305+
static constexpr auto idx_info = []() constexpr {
306+
constexpr int N = sizeof...(property_tys);
307+
std::array<int, N> indexes{};
308+
int num_matched = 0;
309+
int idx = 0;
310+
(((predicate<property_tys>::value ? indexes[num_matched++] = idx++ : idx++),
311+
...));
312+
313+
return std::pair{indexes, num_matched};
314+
}();
315+
316+
// Helper to convert constexpr indices values to an std::index_sequence type.
317+
// Values -> type is the key here.
318+
template <int... Idx>
319+
static constexpr auto idx_seq(std::integer_sequence<int, Idx...>) {
320+
return std::integer_sequence<int, idx_info.first[Idx]...>{};
321+
}
322+
323+
using selected_idx_seq =
324+
decltype(idx_seq(std::make_integer_sequence<int, idx_info.second>{}));
325+
326+
// Using prop_list_ty so that we don't need to explicitly spell out
327+
// `properties` template parameters' implementation-details.
328+
template <typename prop_list_ty, int... Idxs>
329+
static constexpr auto apply_impl(const prop_list_ty &props,
330+
std::integer_sequence<int, Idxs...>) {
331+
return properties{props.template get_property<
332+
typename nth_type_t<Idxs, property_tys...>::key_t>()...};
333+
}
334+
335+
template <typename prop_list_ty>
336+
static constexpr auto apply(const prop_list_ty &props) {
337+
return apply_impl(props, selected_idx_seq{});
338+
}
339+
};
340+
341+
template <template <typename> typename predicate, typename... property_tys>
342+
constexpr auto filter_properties(const properties_t<property_tys...> &props) {
343+
return filter_properties_impl<predicate, property_tys...>::apply(props);
344+
}
345+
346+
template <typename... lhs_property_tys> struct merge_filter {
347+
template <typename rhs_property_ty>
348+
struct predicate
349+
: std::bool_constant<!((std::is_same_v<typename lhs_property_tys::key_t,
350+
typename rhs_property_ty::key_t> ||
351+
...))> {};
352+
};
353+
354+
template <typename... lhs_property_tys, typename... rhs_property_tys>
355+
constexpr auto merge_properties(const properties_t<lhs_property_tys...> &lhs,
356+
const properties_t<rhs_property_tys...> &rhs) {
357+
auto rhs_unique_props =
358+
filter_properties<merge_filter<lhs_property_tys...>::template predicate>(
359+
rhs);
360+
if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>,
361+
std::decay_t<decltype(rhs_unique_props)>>) {
362+
// None of RHS properties share keys with LHS, no conflicts possible.
363+
return properties{
364+
lhs.template get_property<typename lhs_property_tys::key_t>()...,
365+
rhs.template get_property<typename rhs_property_tys::key_t>()...};
366+
} else {
367+
// Ensure no conflicts, then merge.
368+
constexpr auto has_conflict = [](auto *lhs_prop) constexpr {
369+
using lhs_property_ty = std::remove_pointer_t<decltype(lhs_prop)>;
370+
return (((std::is_same_v<typename lhs_property_ty::key_t,
371+
typename rhs_property_tys::key_t> &&
372+
(!std::is_same_v<lhs_property_ty, rhs_property_tys> ||
373+
!std::is_empty_v<lhs_property_ty>)) ||
374+
...));
375+
};
376+
static_assert(
377+
!((has_conflict(static_cast<lhs_property_tys *>(nullptr)) || ...)),
378+
"Failed to merge property lists due to conflicting properties.");
379+
return merge_properties(lhs, rhs_unique_props);
380+
}
381+
}
295382

296383
template <typename LHSPropertiesT, typename RHSPropertiesT>
297384
using merged_properties_t = decltype(merge_properties(

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

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ namespace sycl {
2121
inline namespace _V1 {
2222
namespace ext::oneapi::experimental {
2323
namespace detail {
24-
template <typename... property_tys> struct properties_type_list;
2524

2625
//******************************************************************************
2726
// Misc
@@ -178,88 +177,6 @@ struct ConditionalPropertyMetaInfo
178177
: std::conditional_t<Condition, PropertyMetaInfo<PropT>,
179178
IgnoredPropertyMetaInfo> {};
180179

181-
template <template <typename> typename predicate, typename... property_tys>
182-
struct filter_properties_impl {
183-
static constexpr auto idx_info = []() constexpr {
184-
constexpr int N = sizeof...(property_tys);
185-
std::array<int, N> indexes{};
186-
int num_matched = 0;
187-
int idx = 0;
188-
(((predicate<property_tys>::value ? indexes[num_matched++] = idx++ : idx++),
189-
...));
190-
191-
return std::pair{indexes, num_matched};
192-
}();
193-
194-
// Helper to convert constexpr indices values to an std::index_sequence type.
195-
// Values -> type is the key here.
196-
template <int... Idx>
197-
static constexpr auto idx_seq(std::integer_sequence<int, Idx...>) {
198-
return std::integer_sequence<int, idx_info.first[Idx]...>{};
199-
}
200-
201-
using selected_idx_seq =
202-
decltype(idx_seq(std::make_integer_sequence<int, idx_info.second>{}));
203-
204-
// Using prop_list_ty so that we don't need to explicitly spell out
205-
// `properties` template parameters' implementation-details.
206-
template <typename prop_list_ty, int... Idxs>
207-
static constexpr auto apply_impl(const prop_list_ty &props,
208-
std::integer_sequence<int, Idxs...>) {
209-
return properties{props.template get_property<
210-
typename nth_type_t<Idxs, property_tys...>::key_t>()...};
211-
}
212-
213-
template <typename prop_list_ty>
214-
static constexpr auto apply(const prop_list_ty &props) {
215-
return apply_impl(props, selected_idx_seq{});
216-
}
217-
};
218-
219-
template <template <typename> typename predicate, typename... property_tys>
220-
constexpr auto filter_properties(
221-
const properties<properties_type_list<property_tys...>> &props) {
222-
return filter_properties_impl<predicate, property_tys...>::apply(props);
223-
}
224-
225-
template <typename... lhs_property_tys> struct merge_filter {
226-
template <typename rhs_property_ty>
227-
struct predicate
228-
: std::bool_constant<!((std::is_same_v<typename lhs_property_tys::key_t,
229-
typename rhs_property_ty::key_t> ||
230-
...))> {};
231-
};
232-
233-
template <typename... lhs_property_tys, typename... rhs_property_tys>
234-
constexpr auto merge_properties(
235-
const properties<properties_type_list<lhs_property_tys...>> &lhs,
236-
const properties<properties_type_list<rhs_property_tys...>> &rhs) {
237-
auto rhs_unique_props =
238-
filter_properties<merge_filter<lhs_property_tys...>::template predicate>(
239-
rhs);
240-
if constexpr (std::is_same_v<std::decay_t<decltype(rhs)>,
241-
std::decay_t<decltype(rhs_unique_props)>>) {
242-
// None of RHS properties share keys with LHS, no conflicts possible.
243-
return properties{
244-
lhs.template get_property<typename lhs_property_tys::key_t>()...,
245-
rhs.template get_property<typename rhs_property_tys::key_t>()...};
246-
} else {
247-
// Ensure no conflicts, then merge.
248-
constexpr auto has_conflict = [](auto *lhs_prop) constexpr {
249-
using lhs_property_ty = std::remove_pointer_t<decltype(lhs_prop)>;
250-
return (((std::is_same_v<typename lhs_property_ty::key_t,
251-
typename rhs_property_tys::key_t> &&
252-
(!std::is_same_v<lhs_property_ty, rhs_property_tys> ||
253-
!std::is_empty_v<lhs_property_ty>)) ||
254-
...));
255-
};
256-
static_assert(
257-
!((has_conflict(static_cast<lhs_property_tys *>(nullptr)) || ...)),
258-
"Failed to merge property lists due to conflicting properties.");
259-
return merge_properties(lhs, rhs_unique_props);
260-
}
261-
}
262-
263180
} // namespace detail
264181
} // namespace ext::oneapi::experimental
265182
} // namespace _V1

0 commit comments

Comments
 (0)