RFC: Allow non-member operator overloads for SVE types

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
TL;DR: This message is an RFC about allowing non-member operator
overloads to be defined for SVE types, much like enumerators.
The associated patch is https://reviews.llvm.org/D77056

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SVE types are defined to be opaque built-in types that by default
can only be used via intrinsics.  One consequence of this is that
the types provide no built-in versions of the unary and binary
arithmetic operators.

Instead, we'd like to allow users to define non-member operators
for SVE types, in much the same way as for enumeration types.
This specifically means:

* replacing "enumeration" in sections [over.match.oper] and [over.oper]
  with wording that includes both enumerations and SVE types.

* extending the enumeration handling of operator= in [over.built]
  to include SVE types.

An alternative would be to build the operators into the compiler.
However, we didn't want to do that for several reasons:

* Some of the operators would not be performance-portable.
  (E.g. %, and the 8-bit and 16-bit integer versions of /.)
  The SVE ACLE is supposed to be a low-level, almost asm-level
  interface to the architecture, so synthesising this kind of
  operation seems out-of-place.

* SVE types cannot be used in structures, so unlike with normal vector
  types, the user doesn't have the option of using a wrapper class to
  opt out of the standard handling.

* If in future we do want to provide a core group of operators in a
  standard header file/module, we could use this extension to write it.
  And if we still wanted to implement the bodies of the overloads directly
  in the compiler, we could use function attributes to achieve that.

Eli pointed out in the patch review that, unlike classes and enumerators,
these built-in types don't have an obvious owner, so there was a higher
risk of accidental ODR violations.  The current version of the patch
therefore follows Eli's suggestion of requiring the operators to be
defined in a namespace or as static functions, unless the operator
also has a class or enumerator argument.

Any thoughts?  Does this seem reasonable?

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
   Before I say anything, I'd like to mention that I am generally in favor of having arithmetic operators defined for vector types. As a person with a background in 3d graphics, I know firsthand how irritating it can be to use named functions for arithmetic operations instead of operators. I realize the value that this feature provides.

   That said, there is a third option here: we could just not allow the operator overloads for SVE types. The unpublished ACLE spec update cited in the patch says that it's optional, we could just #define  __ARM_FEATURE_SVE_NONMEMBER_OPERATORS 0 and be done with it. This would provide the following advantages:

   1) Less divergence from the C++ standard. I'm sure this isn't the only place where we diverge.
   2) Less special case code in the compiler. Looking at the patch, it doesn't seem to be that big of a change. However, every special case we add is an increased maintenance burden.

   Leaving the operator support out has some issues as well:

   1) Awkward user code. Having to write code like auto res = add(mul(div(v1, v2), v3), neg(v4)) is painful.
   2) C++ programmers expect to be able to overload operators. I submit that most developers writing ACLE code might be able to accept that they are not writing "regular" C++ and might accept that the rules are different. They can just pretend that they're writing c code.

   Personally, I think allowing the operators is probably the way to go. The Pros seem to mainly effect the developers of Clang, and the Cons seem to mainly effect the users of Clang. I'd prefer if you did not have to define the operators in some special namespace, as I think that'll be very awkward in user code.

Thanks,
   Christopher Tetreault

-----Original Message-----
From: cfe-dev <[hidden email]> On Behalf Of Richard Sandiford via cfe-dev
Sent: Tuesday, March 31, 2020 9:12 AM
To: [hidden email]
Subject: [EXT] [cfe-dev] RFC: Allow non-member operator overloads for SVE types

TL;DR: This message is an RFC about allowing non-member operator overloads to be defined for SVE types, much like enumerators.
The associated patch is https://reviews.llvm.org/D77056

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SVE types are defined to be opaque built-in types that by default can only be used via intrinsics.  One consequence of this is that the types provide no built-in versions of the unary and binary arithmetic operators.

Instead, we'd like to allow users to define non-member operators for SVE types, in much the same way as for enumeration types.
This specifically means:

* replacing "enumeration" in sections [over.match.oper] and [over.oper]
  with wording that includes both enumerations and SVE types.

* extending the enumeration handling of operator= in [over.built]
  to include SVE types.

An alternative would be to build the operators into the compiler.
However, we didn't want to do that for several reasons:

* Some of the operators would not be performance-portable.
  (E.g. %, and the 8-bit and 16-bit integer versions of /.)
  The SVE ACLE is supposed to be a low-level, almost asm-level
  interface to the architecture, so synthesising this kind of
  operation seems out-of-place.

* SVE types cannot be used in structures, so unlike with normal vector
  types, the user doesn't have the option of using a wrapper class to
  opt out of the standard handling.

* If in future we do want to provide a core group of operators in a
  standard header file/module, we could use this extension to write it.
  And if we still wanted to implement the bodies of the overloads directly
  in the compiler, we could use function attributes to achieve that.

Eli pointed out in the patch review that, unlike classes and enumerators, these built-in types don't have an obvious owner, so there was a higher risk of accidental ODR violations.  The current version of the patch therefore follows Eli's suggestion of requiring the operators to be defined in a namespace or as static functions, unless the operator also has a class or enumerator argument.

Any thoughts?  Does this seem reasonable?

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
> Before I say anything, I'd like to mention that I am generally in favor of having arithmetic operators defined for vector types.

For the rest of 'vector' types, we would almost definitely want to implement the operators in clang directly rather than allowing overloading.  While I appreciate the attractiveness of operator overloads on these types, it would be implementation divergence from GCC. (ICC Interestingly chose the alternate direction).


-----Original Message-----
From: cfe-dev <[hidden email]> On Behalf Of Chris Tetreault via cfe-dev
Sent: Tuesday, March 31, 2020 9:56 AM
To: Richard Sandiford <[hidden email]>
Cc: [hidden email]
Subject: Re: [cfe-dev] RFC: Allow non-member operator overloads for SVE types

   Before I say anything, I'd like to mention that I am generally in favor of having arithmetic operators defined for vector types. As a person with a background in 3d graphics, I know firsthand how irritating it can be to use named functions for arithmetic operations instead of operators. I realize the value that this feature provides.

   That said, there is a third option here: we could just not allow the operator overloads for SVE types. The unpublished ACLE spec update cited in the patch says that it's optional, we could just #define  __ARM_FEATURE_SVE_NONMEMBER_OPERATORS 0 and be done with it. This would provide the following advantages:

   1) Less divergence from the C++ standard. I'm sure this isn't the only place where we diverge.
   2) Less special case code in the compiler. Looking at the patch, it doesn't seem to be that big of a change. However, every special case we add is an increased maintenance burden.

   Leaving the operator support out has some issues as well:

   1) Awkward user code. Having to write code like auto res = add(mul(div(v1, v2), v3), neg(v4)) is painful.
   2) C++ programmers expect to be able to overload operators. I submit that most developers writing ACLE code might be able to accept that they are not writing "regular" C++ and might accept that the rules are different. They can just pretend that they're writing c code.

   Personally, I think allowing the operators is probably the way to go. The Pros seem to mainly effect the developers of Clang, and the Cons seem to mainly effect the users of Clang. I'd prefer if you did not have to define the operators in some special namespace, as I think that'll be very awkward in user code.

Thanks,
   Christopher Tetreault

-----Original Message-----
From: cfe-dev <[hidden email]> On Behalf Of Richard Sandiford via cfe-dev
Sent: Tuesday, March 31, 2020 9:12 AM
To: [hidden email]
Subject: [EXT] [cfe-dev] RFC: Allow non-member operator overloads for SVE types

TL;DR: This message is an RFC about allowing non-member operator overloads to be defined for SVE types, much like enumerators.
The associated patch is https://reviews.llvm.org/D77056

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SVE types are defined to be opaque built-in types that by default can only be used via intrinsics.  One consequence of this is that the types provide no built-in versions of the unary and binary arithmetic operators.

Instead, we'd like to allow users to define non-member operators for SVE types, in much the same way as for enumeration types.
This specifically means:

* replacing "enumeration" in sections [over.match.oper] and [over.oper]
  with wording that includes both enumerations and SVE types.

* extending the enumeration handling of operator= in [over.built]
  to include SVE types.

An alternative would be to build the operators into the compiler.
However, we didn't want to do that for several reasons:

* Some of the operators would not be performance-portable.
  (E.g. %, and the 8-bit and 16-bit integer versions of /.)
  The SVE ACLE is supposed to be a low-level, almost asm-level
  interface to the architecture, so synthesising this kind of
  operation seems out-of-place.

* SVE types cannot be used in structures, so unlike with normal vector
  types, the user doesn't have the option of using a wrapper class to
  opt out of the standard handling.

* If in future we do want to provide a core group of operators in a
  standard header file/module, we could use this extension to write it.
  And if we still wanted to implement the bodies of the overloads directly
  in the compiler, we could use function attributes to achieve that.

Eli pointed out in the patch review that, unlike classes and enumerators, these built-in types don't have an obvious owner, so there was a higher risk of accidental ODR violations.  The current version of the patch therefore follows Eli's suggestion of requiring the operators to be defined in a namespace or as static functions, unless the operator also has a class or enumerator argument.

Any thoughts?  Does this seem reasonable?

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
In reply to this post by Fangrui Song via cfe-dev
Thanks for the comments.

Chris Tetreault <[hidden email]> writes:
>    Personally, I think allowing the operators is probably the way to go. The Pros seem to mainly effect the developers of Clang, and the Cons seem to mainly effect the users of Clang. I'd prefer if you did not have to define the operators in some special namespace, as I think that'll be very awkward in user code.

Declaring them static at global scope is also OK.  I imagine a common
use case would be to have header files with static inline functions.

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
In reply to this post by Fangrui Song via cfe-dev
"Keane, Erich via cfe-dev" <[hidden email]> writes:
>> Before I say anything, I'd like to mention that I am generally in
>> favor of having arithmetic operators defined for vector types.
>
> For the rest of 'vector' types, we would almost definitely want to
> implement the operators in clang directly rather than allowing
> overloading.  While I appreciate the attractiveness of operator
> overloads on these types, it would be implementation divergence from
> GCC. (ICC Interestingly chose the alternate direction).

Yeah, this isn't something I would suggest for normal vector types.
With those, anyone who wants to provide their own operators can wrap
the vector in a class.

SVE types like __SVInt8_t are different because, at the semantic level,
they aren't vector types in the way that clang and GCC understand them.
They're instead just opaque blobs of unspecified size that are manipulated
via intrinsic functions.  Their vectorness only becomes apparent during
code generation.

So clang and GCC are consistent in not providing built-in operators
for __SVInt8_t & co.  (I'm not sure you were suggesting otherwise,
I just wanted to clarify.)

GCC has an -msve-vector-bits=N option that lets you specify the
number of bits in an SVE register.  When this is used, types like
__SVInt8_t remain opaque types of unspecified size, to ensure that
the types have the same semantic identity regardless of whether the
vector size is known at compile time.  But GCC does allow implicit
conversion between these sizeless types and "normal" fixed-length
vectors of an appropriate type and size, such as those created by
__attribute__((vector_size(N/8))).  This makes it possible to use
normal fixed-length vectors with SVE intrinsics.  We're planning
to support this for clang too.

The proposal here would only affect opaque not-really-vector types
like __SVInt8_t.  Normal N-bit vectors would be unaffected and
would continue to use the built-in operators.

Similarly, if in future clang and/or GCC supported a truly
cross-platform variable-length vector extension as part of the
core language, it would probably make sense to allow implicit
conversion between those cross-platform types and the corresponding
opaque SVE types.  Here too I imagine the cross-platform types would
use built-in operators.

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: RFC: Allow non-member operator overloads for SVE types

Fangrui Song via cfe-dev
Hi,
wanted to share a quick user perspective.
Background: I've been using SIMD for a long time and wrote a performance-portable wrapper.

SVE looks very interesting, but we strongly believe platform-specific implementations are too expensive.
A cross-platform API is possible, but as Chris mentioned, Add/Div functions are much less ergonomic than infix operators.

Unfortunately we can't overload operators for SVE types because they are built-in, nor can we
wrap them in classes because they are sizeless.

GCC also does not define logical operators on float vectors, although they are useful for abs/signbit/copysign.

Thus we're hoping the compiler can provide built-in operators for all SVE types.

On Wed, Apr 1, 2020 at 2:39 PM Richard Sandiford via cfe-dev <[hidden email]> wrote:
"Keane, Erich via cfe-dev" <[hidden email]> writes:
>> Before I say anything, I'd like to mention that I am generally in
>> favor of having arithmetic operators defined for vector types.
>
> For the rest of 'vector' types, we would almost definitely want to
> implement the operators in clang directly rather than allowing
> overloading.  While I appreciate the attractiveness of operator
> overloads on these types, it would be implementation divergence from
> GCC. (ICC Interestingly chose the alternate direction).

Yeah, this isn't something I would suggest for normal vector types.
With those, anyone who wants to provide their own operators can wrap
the vector in a class.

SVE types like __SVInt8_t are different because, at the semantic level,
they aren't vector types in the way that clang and GCC understand them.
They're instead just opaque blobs of unspecified size that are manipulated
via intrinsic functions.  Their vectorness only becomes apparent during
code generation.

So clang and GCC are consistent in not providing built-in operators
for __SVInt8_t & co.  (I'm not sure you were suggesting otherwise,
I just wanted to clarify.)

GCC has an -msve-vector-bits=N option that lets you specify the
number of bits in an SVE register.  When this is used, types like
__SVInt8_t remain opaque types of unspecified size, to ensure that
the types have the same semantic identity regardless of whether the
vector size is known at compile time.  But GCC does allow implicit
conversion between these sizeless types and "normal" fixed-length
vectors of an appropriate type and size, such as those created by
__attribute__((vector_size(N/8))).  This makes it possible to use
normal fixed-length vectors with SVE intrinsics.  We're planning
to support this for clang too.

The proposal here would only affect opaque not-really-vector types
like __SVInt8_t.  Normal N-bit vectors would be unaffected and
would continue to use the built-in operators.

Similarly, if in future clang and/or GCC supported a truly
cross-platform variable-length vector extension as part of the
core language, it would probably make sense to allow implicit
conversion between those cross-platform types and the corresponding
opaque SVE types.  Here too I imagine the cross-platform types would
use built-in operators.

Thanks,
Richard
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev