diff --git a/sycl/include/sycl/ext/oneapi/properties/properties.hpp b/sycl/include/sycl/ext/oneapi/properties/properties.hpp index 190a16ce5d4c3..12c0af87a0e87 100644 --- a/sycl/include/sycl/ext/oneapi/properties/properties.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/properties.hpp @@ -343,19 +343,9 @@ template using properties_t = properties>; -// Helper for merging two property lists; template -struct merged_properties; -template -struct merged_properties, - properties_t> { - using type = properties< - typename MergeProperties, - properties_type_list>::type>; -}; -template -using merged_properties_t = - typename merged_properties::type; +using merged_properties_t = decltype(merge_properties( + std::declval(), std::declval())); template struct ValueOrDefault { diff --git a/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp b/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp index 2a1d89a4ebc96..2e10699a65fea 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property_utils.hpp @@ -43,12 +43,6 @@ template using nth_type_t = typename nth_type::type; #endif -template struct PrependProperty {}; -template -struct PrependProperty> { - using type = properties_type_list; -}; - //****************************************************************************** // Property identification //****************************************************************************** @@ -63,91 +57,6 @@ struct AllPropertyValues> AllPropertyValues>, std::false_type> {}; -//****************************************************************************** -// Property type sorting -//****************************************************************************** - -// Splits a tuple into head and tail if ShouldSplit is true. If ShouldSplit is -// false the head will be void and the tail will be the full tuple. -template struct HeadSplit {}; -template -struct HeadSplit, true> { - using htype = T; - using ttype = properties_type_list; -}; -template struct HeadSplit, false> { - using htype = void; - using ttype = properties_type_list; -}; - -// Selects the one of two types that is not void. This assumes that at least one -// of the two template arguemnts is void. -template struct SelectNonVoid {}; -template struct SelectNonVoid { - using type = LHS; -}; -template struct SelectNonVoid { - using type = RHS; -}; - -//****************************************************************************** -// Property merging -//****************************************************************************** - -// Merges two sets of properties, failing if two properties are the same but -// with different values. -// NOTE: This assumes that the properties are in sorted order. -template struct MergeProperties; - -template <> -struct MergeProperties, properties_type_list<>> { - using type = properties_type_list<>; -}; - -template -struct MergeProperties, - properties_type_list<>> { - using type = properties_type_list; -}; - -template -struct MergeProperties, - properties_type_list> { - using type = properties_type_list; -}; - -// Identical properties are allowed, but only one will carry over. -template -struct MergeProperties, - properties_type_list> { - using merge_tails = - typename MergeProperties, - properties_type_list>::type; - using type = typename PrependProperty::type; -}; - -template -struct MergeProperties, - properties_type_list> { - using l_head = nth_type_t<0, LHSPropertyTs...>; - using r_head = nth_type_t<0, RHSPropertyTs...>; - static_assert( - PropertyID::value != PropertyID::value, - "Failed to merge property lists due to conflicting properties."); - static constexpr bool left_has_min = - PropertyID::value < PropertyID::value; - using l_split = - HeadSplit, left_has_min>; - using r_split = - HeadSplit, !left_has_min>; - using min = typename SelectNonVoid::type; - using merge_tails = typename MergeProperties::type; - using type = typename PrependProperty::type; -}; - //****************************************************************************** // Property value tooling //****************************************************************************** @@ -349,6 +258,44 @@ constexpr auto filter_properties( return filter_properties_impl::apply(props); } +template struct merge_filter { + template + struct predicate + : std::bool_constant || + ...))> {}; +}; + +template +constexpr auto merge_properties( + const properties> &lhs, + const properties> &rhs) { + auto rhs_unique_props = + filter_properties::template predicate>( + rhs); + if constexpr (std::is_same_v, + std::decay_t>) { + // None of RHS properties share keys with LHS, no conflicts possible. + return properties{ + lhs.template get_property()..., + rhs.template get_property()...}; + } else { + // Ensure no conflicts, then merge. + constexpr auto has_conflict = [](auto *lhs_prop) constexpr { + using lhs_property_ty = std::remove_pointer_t; + return (((std::is_same_v && + (!std::is_same_v || + !std::is_empty_v)) || + ...)); + }; + static_assert( + !((has_conflict(static_cast(nullptr)) || ...)), + "Failed to merge property lists due to conflicting properties."); + return merge_properties(lhs, rhs_unique_props); + } +} + } // namespace detail } // namespace ext::oneapi::experimental } // namespace _V1 diff --git a/sycl/test/extensions/properties/properties_kernel_negative.cpp b/sycl/test/extensions/properties/properties_kernel_negative.cpp index 5b00fa954fd7e..541d1b248950b 100644 --- a/sycl/test/extensions/properties/properties_kernel_negative.cpp +++ b/sycl/test/extensions/properties/properties_kernel_negative.cpp @@ -83,7 +83,6 @@ void check_work_group_size() { sycl::queue Q; // 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.}} - // expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.+}}: Template type is not a property list.}} // expected-note-re@+1 {{in instantiation of function template specialization {{.+}}}} Q.single_task( sycl::ext::oneapi::experimental::properties{