-
Notifications
You must be signed in to change notification settings - Fork 787
[SYCL] Add operator overloading for aggregate types in annotated_ref #11971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SYCL] Add operator overloading for aggregate types in annotated_ref #11971
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments below.
I'd also like @rolandschulz's opinion on whether this is the right way to define the operators.
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
// remove_ann_ref<T> is an exposition only type alias which | ||
// for annotated_ref<T, ...> is T and for any other type is that type. | ||
template <class A, class B> | ||
auto friend operatorOP(const A& a, const B& b) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be consistent in how we pass arguments. This won't work with volatile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot do pass-by-value when A
or B
is an annotated_ref
. The copy constructor of annotated_ref
is explicitly marked as deleted. We can only do pass-by-value when A
or B
are raw types. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right - I forgot that. I see two options:
- pass by universal reference. That works for both volatile and ann_ref.
- go back to 3 seperate overloads for ann_ref+ann_ref, ann_ref+value, value+ann_ref. And pass ann_ref by const& and value by value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the PR as discussed. Still pending on adding test
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
Defines a hidden friend operator `OP` overload for types `A` and `B`. | ||
|
||
When `A` is an `annotated_ref<T, PropertyListT>`, `remove_ann_ref<A>` returns `T`, otherwise | ||
returns `A`. Same applied to `B`. This operator is invoked only when at least one of the `A` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"This operator is ..." this sentence is odd for a spec. It just describes how ADL for hidden friends work. Normally we don't explain C++ in the SYCL spec. But maybe a note is warranted because it is non-obvious.
nit: "invoked only" nicer: "participates in overload resolution"
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
template <typename O> | ||
auto friend operatorOP(O&& a, const annotated_ref& b) -> | ||
decltype(std::forward<O>(a) OP std::declval<T>()); | ||
template <typename O, typename = std::enable_if_t<!is_ann_ref_v<O>>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here: "available only if ...". In both cases it might be clearer if one would say it has lower priority than the other overload (which we achieve by disabling it). But we don't use that wording in other places. @gmlueck which wording do you prefer?
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp
Outdated
Show resolved
Hide resolved
sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp
Outdated
Show resolved
Hide resolved
sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp
Show resolved
Hide resolved
@@ -29,6 +29,111 @@ int main() { | |||
auto *d = malloc_shared<int>(4, Q); | |||
auto d_ptr = annotated_ptr{d}; | |||
|
|||
template <typename T> struct MyStruct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need more tests:
- test that operators are SFINAE friendly
- test that operators are hidden friends (expected error doesn't contain annotated_ref)
- test that the return value is correct (e.g.
decltype(O(a) op std::declval<T>())
ordecltype((std::forward<O>(a) op std::declval<T>()))
instead ofdecltype(std::forward<O>(a) op std::declval<T>())
) - test that operators work for a type which doesn't have operators defined but is convertible to a type which does
- that that the operators work if the type has the operators defined in a bad way (e.g. binary operators as members)
- any other corner case we found while prototyping and I forgot in this list
sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc
Outdated
Show resolved
Hide resolved
fa83d3f
to
32d1a46
Compare
026c687
to
4e19a89
Compare
a53eddc
to
7d31af8
Compare
7d31af8
to
c724e14
Compare
bcd110a
to
6c0da61
Compare
int a; | ||
}; | ||
g g0, g1; | ||
// TODO: these notes shouldn't be emitted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be fixed outside this PR. The problem is that both vec (+swizzle) and annotated_arg don't define the their binary operators as hidden friends. For vec the spec is clear that it should be a hidden friend. For annotated_arg we should make this clear.
@intel/llvm-gatekeepers Hi can you help to merge this? The E2E failure seems unrelated. Thanks! |
Refactor annotated_arg operator forwarding regarding to #11971 and #12140 1. add binary and unary operator forwarding. We don't need inc/dec and compound here since SYCL kernel arg are const member and cannot be modified 2. replace the old impl with hidden friend operators --------- Co-authored-by: Wang, Di5 <[email protected]>
Added several operator overloading for aggregate types for annotated_ref class.
This https://godbolt.org/z/h5cTTr17K would be a good example to show why this is not working without this fix.
This PR includes several changes:
This covers cases in which the sequence of conversions will be correct when implicit conversion is involved. i.e
without this fix,