Skip to content

[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

Merged
merged 16 commits into from
Dec 7, 2023

Conversation

broxigarchen
Copy link
Contributor

@broxigarchen broxigarchen commented Nov 21, 2023

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:

  1. Propogate operators including all binaries and unary operators, including arithmetic, comparator, and logical.
  2. Using perfecting forwarding for binaries operators, compound operators, and unary operators.

This covers cases in which the sequence of conversions will be correct when implicit conversion is involved. i.e

annotated_ref<int> a;
double b;
auto p = a + b; // expected to be (double)a + b, and p should be double

without this fix,

T operator+(T a) const;
annotated_ref<int> a;
double b;
auto p = a + b; // this become a + (int)b, and p will be int

@broxigarchen broxigarchen requested review from a team as code owners November 21, 2023 19:35
@broxigarchen broxigarchen changed the title [SYCL] add overloading to annotated_ref [SYCL] Add arithmetic overloaded operators for annotated_ref Nov 21, 2023
Copy link
Contributor

@gmlueck gmlueck left a 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.

// 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) ->
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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:

  1. pass by universal reference. That works for both volatile and ann_ref.
  2. 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.

Copy link
Contributor Author

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

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`
Copy link
Contributor

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"

@broxigarchen broxigarchen changed the title [SYCL] Add arithmetic overloaded operators for annotated_ref [SYCL] Add operator overloading for aggregate types in annotated_ref Nov 24, 2023
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>>>
Copy link
Contributor

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?

@@ -29,6 +29,111 @@ int main() {
auto *d = malloc_shared<int>(4, Q);
auto d_ptr = annotated_ptr{d};

template <typename T> struct MyStruct {
Copy link
Contributor

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>()) or decltype((std::forward<O>(a) op std::declval<T>())) instead of decltype(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

int a;
};
g g0, g1;
// TODO: these notes shouldn't be emitted
Copy link
Contributor

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.

@broxigarchen
Copy link
Contributor Author

@intel/llvm-gatekeepers Hi can you help to merge this? The E2E failure seems unrelated. Thanks!

@aelovikov-intel aelovikov-intel merged commit 4ab007d into intel:sycl Dec 7, 2023
againull pushed a commit that referenced this pull request Jan 11, 2024
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants