diff --git a/sycl/include/sycl/ext/oneapi/annotated_arg/annotated_arg.hpp b/sycl/include/sycl/ext/oneapi/annotated_arg/annotated_arg.hpp new file mode 100644 index 0000000000000..f58d1596248c8 --- /dev/null +++ b/sycl/include/sycl/ext/oneapi/annotated_arg/annotated_arg.hpp @@ -0,0 +1,277 @@ +//==----------- annotated_arg.hpp - SYCL annotated_arg extension -----------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace sycl { +__SYCL_INLINE_VER_NAMESPACE(_V1) { +namespace ext { +namespace oneapi { +namespace experimental { + +namespace detail { + +// Type-trait for checking if a type defines `operator[]`. +template +struct HasSubscriptOperator + : std::bool_constant< + !std::is_void().operator[](0))>::value>{}; + +// Deduce a `properties<>` type from given variadic properties +template struct DeducedProperties { + using type = decltype(properties{std::declval()...}); +}; + +// Partial specialization for deducing a `properties<>` type by forwarding the +// given `properties<>` type +template +struct DeducedProperties> { + using type = detail::properties_t; +}; + +} // namespace detail + +// Deduction guide +template +annotated_arg(T, Args...) + -> annotated_arg::type>; + +template +annotated_arg(annotated_arg, properties>) + -> annotated_arg< + T, detail::merged_properties_t>>; + +template +class annotated_arg { + // This should always fail when instantiating the unspecialized version. + static_assert(is_property_list::value, + "Property list is invalid."); +}; + +// Partial specialization for pointer type +template +class __SYCL_SPECIAL_CLASS +__SYCL_TYPE(annotated_arg) annotated_arg> { + using property_list_t = detail::properties_t; + +#ifdef __SYCL_DEVICE_ONLY__ + using global_pointer_t = typename decorated_global_ptr::pointer; +#else + using global_pointer_t = T *; +#endif + + global_pointer_t obj; + + template friend class annotated_arg; + +#ifdef __SYCL_DEVICE_ONLY__ + void __init([[__sycl_detail__::add_ir_attributes_kernel_parameter( + detail::PropertyMetaInfo::name..., + detail::PropertyMetaInfo::value...)]] global_pointer_t _obj) { + obj = _obj; + } +#endif + +public: + static_assert(is_property_list::value, + "Property list is invalid."); + + annotated_arg() noexcept = default; + annotated_arg(const annotated_arg &) = default; + annotated_arg &operator=(annotated_arg &) = default; + + annotated_arg(T *_ptr, + const property_list_t &PropList = properties{}) noexcept + : obj(global_pointer_t(_ptr)) {} + + // Constructs an annotated_arg object from a raw pointer and variadic + // properties. The new property set contains all properties of the input + // variadic properties. The same property in `Props...` and + // `PropertyValueTs...` must have the same property value. + template + annotated_arg(T *_ptr, const PropertyValueTs &...props) noexcept + : obj(global_pointer_t(_ptr)) { + static_assert( + std::is_same< + property_list_t, + detail::merged_properties_t>::value, + "The property list must contain all properties of the input of the " + "constructor"); + } + + // Constructs an annotated_arg object from another annotated_arg object. + // The new property set contains all properties of the input + // annotated_arg object. The same property in `Props...` and `PropertyList2` + // must have the same property value. + template + explicit annotated_arg(const annotated_arg &other) noexcept + : obj(other.obj) { + static_assert(std::is_convertible::value, + "The underlying data type of the input annotated_arg is not " + "compatible"); + + static_assert( + std::is_same< + property_list_t, + detail::merged_properties_t>::value, + "The constructed annotated_arg type must contain all the properties of " + "the input annotated_arg"); + } + + // Constructs an annotated_arg object from another annotated_arg object and a + // property list. The new property set is the union of property lists + // `PropertyListU` and `PropertyListV`. The same property in `PropertyListU` + // and `PropertyListV` must have the same property value. + template + explicit annotated_arg(const annotated_arg &other, + const PropertyListV &proplist) noexcept + : obj(other.obj) { + static_assert(std::is_convertible::value, + "The underlying data type of the input annotated_arg is not " + "compatible"); + + static_assert( + std::is_same>::value, + "The property list of constructed annotated_arg type must be the union " + "of the input property lists"); + } + + operator T *() noexcept { return obj; } + operator T *() const noexcept { return obj; } + + T &operator[](std::ptrdiff_t idx) const noexcept { return obj[idx]; } + + template static constexpr bool has_property() { + return property_list_t::template has_property(); + } + + template static constexpr auto get_property() { + return property_list_t::template get_property(); + } +}; + +// Partial specialization for non-pointer type +template +class __SYCL_SPECIAL_CLASS +__SYCL_TYPE(annotated_arg) annotated_arg> { + using property_list_t = detail::properties_t; + + template friend class annotated_arg; + + T obj; + +#ifdef __SYCL_DEVICE_ONLY__ + void __init([[__sycl_detail__::add_ir_attributes_kernel_parameter( + detail::PropertyMetaInfo::name..., + detail::PropertyMetaInfo::value...)]] T _obj) { + obj = _obj; + } +#endif + +public: + static_assert(is_device_copyable_v, "Type T must be device copyable."); + static_assert(is_property_list::value, + "Property list is invalid."); + static_assert(check_property_list::value, + "The property list contains invalid property."); + + annotated_arg() noexcept = default; + annotated_arg(const annotated_arg &) = default; + annotated_arg &operator=(annotated_arg &) = default; + + annotated_arg(const T &_obj, + const property_list_t &PropList = properties{}) noexcept + : obj(_obj) {} + + // Constructs an annotated_arg object from a raw pointer and variadic + // properties. The new property set contains all properties of the input + // variadic properties. The same property in `Props...` and + // `PropertyValueTs...` must have the same property value. + template + annotated_arg(const T &_obj, PropertyValueTs... props) noexcept : obj(_obj) { + static_assert( + std::is_same< + property_list_t, + detail::merged_properties_t>::value, + "The property list must contain all properties of the input of the " + "constructor"); + } + + // Constructs an annotated_arg object from another annotated_arg object. + // The new property set contains all properties of the input + // annotated_arg object. The same property in `Props...` and `PropertyList2` + // must have the same property value. + template + explicit annotated_arg(const annotated_arg &other) noexcept + : obj(other.obj) { + static_assert(std::is_convertible::value, + "The underlying data type of the input annotated_arg is not " + "compatible"); + + static_assert( + std::is_same< + property_list_t, + detail::merged_properties_t>::value, + "The constructed annotated_arg type must contain all the properties of " + "the input annotated_arg"); + } + + // Constructs an annotated_arg object from another annotated_arg object and a + // property list. The new property set is the union of property lists + // `PropertyListU` and `PropertyListV`. The same property in `PropertyListU` + // and `PropertyListV` must have the same property value. + template + explicit annotated_arg(const annotated_arg &other, + const PropertyListV &proplist) noexcept + : obj(other.obj) { + static_assert(std::is_convertible::value, + "The underlying data type of the input annotated_arg is not " + "compatible"); + + static_assert( + std::is_same>::value, + "The property list of constructed annotated_arg type must be the union " + "of the input property lists"); + } + + operator T() noexcept { return obj; } + operator T() const noexcept { return obj; } + + template + std::enable_if_t::value, + decltype(std::declval().operator[](0))> & + operator[](std::ptrdiff_t idx) const noexcept { + return obj.operator[](idx); + } + + template static constexpr bool has_property() { + return property_list_t::template has_property(); + } + + template static constexpr auto get_property() { + return property_list_t::template get_property(); + } +}; + +} // namespace experimental +} // namespace oneapi +} // namespace ext +} // __SYCL_INLINE_VER_NAMESPACE(_V1) +} // namespace sycl diff --git a/sycl/include/sycl/ext/oneapi/annotated_arg/properties.hpp b/sycl/include/sycl/ext/oneapi/annotated_arg/properties.hpp new file mode 100644 index 0000000000000..eb21a01e6d229 --- /dev/null +++ b/sycl/include/sycl/ext/oneapi/annotated_arg/properties.hpp @@ -0,0 +1,304 @@ +//==-- properties.hpp - SYCL properties associated with annotated_arg/ptr --==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +namespace sycl { +__SYCL_INLINE_VER_NAMESPACE(_V1) { +namespace ext { +namespace oneapi { +namespace experimental { + +template class annotated_arg; + +//===----------------------------------------------------------------------===// +// Common properties of annotated_arg/annotated_ptr +//===----------------------------------------------------------------------===// +struct register_map_key { + using value_t = property_value; +}; + +struct conduit_key { + using value_t = property_value; +}; + +struct stable_key { + using value_t = property_value; +}; + +struct buffer_location_key { + template + using value_t = + property_value>; +}; + +struct awidth_key { + template + using value_t = property_value>; +}; + +struct dwidth_key { + template + using value_t = property_value>; +}; + +struct latency_key { + template + using value_t = property_value>; +}; + +enum class read_write_mode_enum : std::uint16_t { read_write, read, write }; + +struct read_write_mode_key { + template + using value_t = + property_value>; +}; + +struct maxburst_key { + template + using value_t = property_value>; +}; + +struct wait_request_key { + template + using value_t = + property_value>; +}; + +// non-mmhost properties +inline constexpr register_map_key::value_t register_map; +inline constexpr conduit_key::value_t conduit; +inline constexpr stable_key::value_t stable; + +// mmhost properties +template +inline constexpr buffer_location_key::value_t buffer_location; +template inline constexpr awidth_key::value_t awidth; +template inline constexpr dwidth_key::value_t dwidth; +template inline constexpr latency_key::value_t latency; +template inline constexpr maxburst_key::value_t maxburst; +template +inline constexpr wait_request_key::value_t wait_request; +inline constexpr wait_request_key::value_t<1> wait_request_requested; +inline constexpr wait_request_key::value_t<0> wait_request_not_requested; + +template +inline constexpr read_write_mode_key::value_t read_write_mode; +inline constexpr read_write_mode_key::value_t + read_write_mode_read; +inline constexpr read_write_mode_key::value_t + read_write_mode_write; +inline constexpr read_write_mode_key::value_t + read_write_mode_readwrite; + +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; + +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; +template <> struct is_property_key : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +template +struct is_property_key_of> + : std::true_type {}; + +namespace detail { +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::RegisterMap; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::Conduit; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::Stable; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::BufferLocation; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::AddrWidth; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::DataWidth; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::Latency; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::RWMode; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::MaxBurst; +}; +template <> struct PropertyToKind { + static constexpr PropKind Kind = PropKind::WaitRequest; +}; + +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; + +template <> +struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> +struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; +template <> struct IsCompileTimeProperty : std::true_type {}; + +template <> struct PropertyMetaInfo { + static constexpr const char *name = "sycl-register-map"; + static constexpr std::nullptr_t value = nullptr; +}; +template <> struct PropertyMetaInfo { + static constexpr const char *name = "sycl-conduit"; + static constexpr std::nullptr_t value = nullptr; +}; +template <> struct PropertyMetaInfo { + static constexpr const char *name = "sycl-stable"; + static constexpr std::nullptr_t value = nullptr; +}; + +template struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-buffer-location"; + static constexpr int value = N; +}; +template struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-awidth"; + static constexpr int value = W; +}; +template struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-dwidth"; + static constexpr int value = W; +}; +template struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-latency"; + static constexpr int value = N; +}; +template struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-maxburst"; + static constexpr int value = N; +}; +template +struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-wait-request"; + static constexpr int value = Enable; +}; +template +struct PropertyMetaInfo> { + static constexpr const char *name = "sycl-read-write-mode"; + static constexpr read_write_mode_enum value = Mode; +}; + +} // namespace detail + +// 'buffer_location' and mmhost properties are pointers-only +template +struct is_valid_property : std::false_type {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +template +struct is_valid_property> + : std::bool_constant::value> {}; + +// 'register_map', 'conduit', 'stable' are common properties for pointers +// and non pointers; +template +struct is_valid_property : std::true_type {}; +template +struct is_valid_property : std::true_type {}; +template +struct is_valid_property : std::true_type {}; + +template +struct check_property_list : std::true_type {}; + +template +struct check_property_list + : std::conditional_t::value, + check_property_list, std::false_type> { + static_assert(is_valid_property::value, + "Property is invalid for the given type."); +}; + +} // namespace experimental +} // namespace oneapi +} // namespace ext +} // __SYCL_INLINE_VER_NAMESPACE(_V1) +} // namespace sycl diff --git a/sycl/include/sycl/ext/oneapi/properties/property.hpp b/sycl/include/sycl/ext/oneapi/properties/property.hpp index 01df3abf6c296..08f6d41ecffbf 100644 --- a/sycl/include/sycl/ext/oneapi/properties/property.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/property.hpp @@ -173,11 +173,21 @@ enum PropKind : uint32_t { WorkGroupSizeHint = 7, SubGroupSize = 8, DeviceHas = 9, - StreamingInterface = 10, + StreamingInterface = 10, // kernel attribute RegisterMapInterface = 11, Pipelined = 12, + RegisterMap = 13, // kernel argument attribute + Conduit = 14, + Stable = 15, + BufferLocation = 16, + AddrWidth = 17, + DataWidth = 18, + Latency = 19, + RWMode = 20, + MaxBurst = 21, + WaitRequest = 22, // PropKindSize must always be the last value. - PropKindSize = 13, + PropKindSize = 23, }; // This trait must be specialized for all properties and must have a unique diff --git a/sycl/include/sycl/sycl.hpp b/sycl/include/sycl/sycl.hpp index 8b1be0aabc3b1..f9396b7a05b67 100644 --- a/sycl/include/sycl/sycl.hpp +++ b/sycl/include/sycl/sycl.hpp @@ -62,6 +62,8 @@ #endif #include #include +#include +#include #include #include #include diff --git a/sycl/test/extensions/annotated_arg/annotated_arg_for_non_ptr.cpp b/sycl/test/extensions/annotated_arg/annotated_arg_for_non_ptr.cpp new file mode 100644 index 0000000000000..9d3d535bc408e --- /dev/null +++ b/sycl/test/extensions/annotated_arg/annotated_arg_for_non_ptr.cpp @@ -0,0 +1,161 @@ +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s +// expected-no-diagnostics + +#include "sycl/sycl.hpp" +#include + +#include + +// clang-format on + +using namespace sycl; +using namespace ext::oneapi::experimental; + +struct B {}; + +struct A : public B { + int x; + A() {} + A(int x_) : x(x_) {} + + int &operator[](std::ptrdiff_t idx) { return x; } + int &operator[](std::ptrdiff_t idx) const { return const_cast(x); } +}; + +using annotated_arg_t1 = + annotated_arg; + +using annotated_arg_t3 = annotated_arg; + +struct MyIP { + int *a; + + annotated_arg_t1 b; + + MyIP(int *a_, const A &b_) : a(a_), b(b_) {} + + void operator()() const { + b[0] = 10; + + const A &tmp = b; + A tmp2 = b; + + for (int i = 0; i < tmp.x; i++) { + *a += 1; + } + *a += b[0]; + } +}; + +template T foo() { + A obj(5); + return annotated_arg(obj, conduit); +} + +void TestVectorAddWithAnnotatedMMHosts() { + // Create the SYCL device queue + queue q(sycl::ext::intel::fpga_selector_v); + auto raw = malloc_shared(1, q); + + A obj(0); + // default ctor + annotated_arg_t3 a1(obj); + + // copy ctor + auto a2(a1); + auto a3(foo()); + // // assign ctor + auto a4 = a3; + + // Construct from A instance + auto tmp11 = annotated_arg(obj); // empty property list + + // Construct from A instance and a property list + // auto tmp12 = annotated_arg(obj, properties{conduit}); + auto tmp12 = annotated_arg(obj, conduit); + static_assert(std::is_same::value, + "deduction guide failed 1"); + + // Construct from A instance and variadic properties + auto tmp13 = annotated_arg(obj, stable, conduit); // deduction guide + static_assert(std::is_same::value, + "deduction guide failed 2"); + + // property list contains invalid property + // auto tmp14 = annotated_arg(obj, awidth<32>); // ERR + + // Construct from another annotated_arg + // templated copy constructor + annotated_arg arg11(tmp11); + annotated_arg arg14( + tmp11); // convertible type + auto arg12 = annotated_arg(tmp11); + + // default copy constructor + auto arg13 = annotated_arg(tmp12); + static_assert(std::is_same::value, + "deduction guide failed 3"); + + // Construct from another annotated_arg and a property list + // annotated_arg arg21(tmp11, + // properties{stable}); // ERR: the type properties should be the union of + // the inputs + annotated_arg arg22( + tmp12, properties{stable}); + auto arg23 = annotated_arg(tmp12, properties{stable}); // deduction guide + static_assert(std::is_same::value, + "deduction guide failed 4"); + static_assert(std::is_same::value, + "deduction guide failed 5"); + annotated_arg arg24( + tmp12, properties{stable}); // convertible type + + // Property merge + auto arg31 = annotated_arg_t3(obj, conduit); // OK + auto arg32 = annotated_arg(arg31, properties{stable}); // OK + auto arg33 = annotated_arg(arg32, properties{stable, conduit}); // OK + // auto arg34 = annotated_arg(arg32, properties{conduit, latency<22>}); // + // ERR: invalid property + static_assert(std::is_same::value, + "deduction guide failed 6"); + static_assert(std::is_same::value, + "deduction guide failed 7"); + // auto arg35 = annotated_arg(arg32, properties{conduit, dwidth<22>}); // + // ERR: two input property lists are conflict + // annotated_arg + // arg36(arg31, properties{latency<32>, stable}); // ERR: input + // property list is conflict with the declared type + + // Implicit Conversion + const A &x13 = arg32; // OK + A x14 = arg32; // OK + // A& x11 = arg32; // ERR: non-const lvalue reference to type 'A' cannot + // bind to a value of unrelated type + + // operator[] + a1[0] = 5; + + // has/get property + static_assert(annotated_arg_t1::has_property(), + "has property 1"); + static_assert(annotated_arg_t1::get_property() == conduit, + "get property 1"); + static_assert(annotated_arg_t1::has_property() == false, + "has property 2"); + + static_assert(annotated_arg_t3::has_property() == false, + "has property 3"); + // auto stable_prop = annotated_arg_t3::get_property(); // ERR: + // can't get non-existing property + + *raw = 0; + q.submit([&](handler &h) { h.single_task(MyIP{raw, a1}); }).wait(); + + std::cout << raw[0] << std::endl; + free(raw, q); +} + +int main() { + TestVectorAddWithAnnotatedMMHosts(); + return 0; +} diff --git a/sycl/test/extensions/annotated_arg/annotated_arg_for_ptr.cpp b/sycl/test/extensions/annotated_arg/annotated_arg_for_ptr.cpp new file mode 100644 index 0000000000000..12549bbbe4ebf --- /dev/null +++ b/sycl/test/extensions/annotated_arg/annotated_arg_for_ptr.cpp @@ -0,0 +1,159 @@ +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s +// expected-no-diagnostics + +#include "sycl/sycl.hpp" +#include + +#include + +// clang-format on + +using namespace sycl; +using namespace ext::oneapi::experimental; + +using annotated_arg_t1 = + annotated_arg, dwidth<32>))>; + +using annotated_arg_t2 = + annotated_arg; + +using annotated_arg_t3 = annotated_arg))>; + +struct MyIP { + annotated_arg, dwidth<32>))> a; + + int b; + + MyIP(int *a_, int b_) : a(a_), b(b_) {} + + void operator()() const { + int *p = a; + const int *p2 = a; + + for (int i = 0; i < b; i++) { + p[i] = i; + a[i] += 1; + } + } +}; + +template T foo() { + auto raw = new int; + return annotated_arg(raw, awidth<32>); +} + +void TestVectorAddWithAnnotatedMMHosts() { + // Create the SYCL device queue + queue q(sycl::ext::intel::fpga_selector_v); + auto raw = malloc_shared(5, q); + + // default ctor + annotated_arg_t3 a1; + // copy ctor + auto a2(a1); + auto a3(foo()); + // // assign ctor + auto a4 = a1; + + // Construct from raw pointers + auto tmp11 = annotated_arg(raw); // empty property list + // Construct from raw pointers and a property list + auto tmp12 = annotated_arg})>( + raw, properties{awidth<32>}); + auto tmp14 = annotated_arg(raw, properties{awidth<32>}); // deduction guide + static_assert(std::is_same::value, + "deduction guide failed 1"); + // Construct from raw pointers and variadic properties + auto tmp13 = annotated_arg(raw, dwidth<32>, awidth<32>); // deduction guide + static_assert(std::is_same::value, + "deduction guide failed 2"); + auto tmp15 = annotated_arg(raw, awidth<32>); + static_assert(std::is_same::value, + "deduction guide failed 1"); + + // Property list can't have duplicated properties + // auto tmp16 = annotated_arg(raw, awidth<32>, awidth<32>); // ERR + // auto tmp17 = annotated_arg(raw, awidth<32>, awidth<22>); // ERR + + // auto tmp18 = annotated_arg(raw, properties{awidth<32>, dwidth<32>, + // awidth<32>}); // ERR: Duplicate properties in property list auto tmp19 = + // annotated_arg(raw, properties{awidth<32>, awidth<22>}); // ERR + + // Construct from another annotated_arg + // templated copy constructor + annotated_arg, dwidth<32>})> arg11( + tmp11); + auto arg12 = + annotated_arg, awidth<32>})>(tmp11); + + // default copy constructor + auto arg13 = annotated_arg(tmp12); + static_assert(std::is_same::value, + "deduction guide failed 3"); + + // Construct from another annotated_arg and a property list + // annotated_arg, dwidth<32>})> + // arg21(tmp11, properties{dwidth<32>}); // ERR: the type properties should + // be the union of the inputs + annotated_arg, dwidth<32>})> arg22( + tmp12, properties{dwidth<32>}); + auto arg23 = annotated_arg(tmp12, properties{dwidth<32>}); // deduction guide + static_assert(std::is_same::value, + "deduction guide failed 4"); + static_assert(std::is_same::value, + "deduction guide failed 5"); + + // Construct from inconvertible type + // annotated_arg tmp21; + // annotated_arg})> arg24(tmp21, + // properties{dwidth<32>}); // ERR + + // Property merge + auto arg31 = annotated_arg_t3(raw, awidth<32>); // OK + auto arg32 = annotated_arg(arg31, properties{dwidth<32>}); // OK + auto arg33 = annotated_arg(arg32, properties{dwidth<32>, awidth<32>}); // OK + auto arg34 = annotated_arg(arg32, properties{awidth<32>, latency<22>}); // OK + static_assert(std::is_same::value, + "deduction guide failed 6"); + static_assert(std::is_same::value, + "deduction guide failed 7"); + // auto arg34 = annotated_arg(arg32, properties{awidth<32>, dwidth<22>}); // + // ERR: two input property lists are conflict + // annotated_arg, dwidth<32>})> + // arg35(arg31, properties{latency<32>, dwidth<32>}); // ERR: input + // property list is conflict with the declared type + + // Implicit Conversion + int *x11 = arg13; + const int *x13 = arg32; + + // operator[] + arg31[0] = 1; + for (int i = 1; i < 5; i++) { + arg31[i] = arg31[i - 1]; + } + + // has/get property + static_assert(annotated_arg_t1::has_property(), "has property 1"); + static_assert(annotated_arg_t1::get_property() == awidth<32>, + "get property 1"); + static_assert(annotated_arg_t1::has_property() == false, + "has property 2"); + + static_assert(annotated_arg_t3::has_property() == false, + "has property 3"); + // auto dwidth_prop = annotated_arg_t3::get_property(); // ERR + + q.submit([&](handler &h) { h.single_task(MyIP{raw, 5}); }).wait(); + + for (int i = 0; i < 5; i++) { + std::cout << raw[i] << std::endl; + } + + free(raw, q); +} + +int main() { + TestVectorAddWithAnnotatedMMHosts(); + return 0; +} diff --git a/sycl/test/extensions/annotated_arg/annotated_arg_properties.cpp b/sycl/test/extensions/annotated_arg/annotated_arg_properties.cpp new file mode 100644 index 0000000000000..e622e67652808 --- /dev/null +++ b/sycl/test/extensions/annotated_arg/annotated_arg_properties.cpp @@ -0,0 +1,94 @@ +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s +// expected-no-diagnostics + +#include + +using namespace sycl::ext::oneapi::experimental; + +static annotated_arg AnnotatedArg1; +static annotated_arg AnnotatedArg2; +static annotated_arg + AnnotatedArg3; +static annotated_arg, + read_write_mode_read, stable, + conduit))> + AnnotatedArg4; + +struct A {}; + +// Checks is_property_key_of and is_property_value_of for T. +template void checkIsPropertyOf() { + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + static_assert(is_property_key_of::value); + + static_assert(is_property_value_of::value); + static_assert(is_property_value_of::value); + static_assert(is_property_value_of::value); + + static_assert(is_property_value_of), T>::value); + static_assert(is_property_value_of), T>::value); + static_assert(is_property_value_of), T>::value); + static_assert(is_property_value_of), T>::value); + static_assert(is_property_value_of::value); + static_assert(is_property_value_of), T>::value); + static_assert( + is_property_value_of::value); +} + +// Checks is_property_key_of and is_property_value_of are false for non-pointer +// type T. +template void checkIsValidPropertyOfNonPtr() { + static_assert( + is_valid_property::value == + false); + static_assert(is_valid_property)>::value == false); +} + +int main() { + static_assert(is_property_key::value); + static_assert(is_property_key::value); + + checkIsPropertyOf(); + static_assert(!AnnotatedArg1.has_property()); + static_assert(!AnnotatedArg1.has_property()); + + checkIsPropertyOf(); + static_assert(AnnotatedArg2.has_property()); + static_assert(!AnnotatedArg2.has_property()); + static_assert(!AnnotatedArg2.has_property()); + static_assert(AnnotatedArg2.get_property() == register_map); + + checkIsPropertyOf(); + static_assert(!AnnotatedArg3.has_property()); + static_assert(AnnotatedArg3.has_property()); + static_assert(AnnotatedArg3.has_property()); + static_assert(!AnnotatedArg3.has_property()); + static_assert(AnnotatedArg3.get_property() == stable); + static_assert(AnnotatedArg3.get_property() == conduit); + + checkIsPropertyOf(); + static_assert(!AnnotatedArg4.has_property()); + static_assert(AnnotatedArg4.has_property()); + static_assert(AnnotatedArg4.has_property()); + static_assert(AnnotatedArg4.has_property()); + static_assert(AnnotatedArg4.has_property()); + static_assert(AnnotatedArg4.get_property() == conduit); + static_assert(AnnotatedArg4.get_property() == stable); + static_assert(AnnotatedArg4.get_property() == + buffer_location<1>); + static_assert(AnnotatedArg4.get_property() == + read_write_mode_read); + + // Check if a property is valid for a given type + checkIsValidPropertyOfNonPtr(); + return 0; +}