Skip to content
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

[Mono] Add arm64 SIMD intrinsic for Vector64/128 Abs #65086

Merged
merged 4 commits into from Feb 10, 2022

Conversation

mkhamoyan
Copy link
Member

This PR contributes to #64072

Add intrinsics for Vector64/128 Abs.

case SN_Abs: {
#ifdef TARGET_ARM64
MonoType *arg_type = get_vector_t_elem_type (fsig->params [0]);
if (!MONO_TYPE_IS_INTRINSICS_VECTOR_PRIMITIVE (arg_type))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this check is necessary. What would happen if you don't have this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to check if type is numeric but I see now that it doesn't check that. Do we have some function to understand if type is numeric?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the impression that it is guaranteed that it should be numeric type, cause the other cases wasn't checking this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It validates that T is actually a supported type for Vector64/128/256 as not every primitive type is supported.

Notably, it can be relaxed from

#define MONO_TYPE_IS_INTRINSICS_VECTOR_PRIMITIVE(t) ((MONO_TYPE_IS_VECTOR_PRIMITIVE(t)) && ((t)->type != MONO_TYPE_I) && ((t)->type != MONO_TYPE_U))

To just:

- #define MONO_TYPE_IS_INTRINSICS_VECTOR_PRIMITIVE(t) ((MONO_TYPE_IS_VECTOR_PRIMITIVE(t)) && ((t)->type != MONO_TYPE_I) && ((t)->type != MONO_TYPE_U))
+ #define MONO_TYPE_IS_INTRINSICS_VECTOR_PRIMITIVE(t) MONO_TYPE_IS_VECTOR_PRIMITIVE(t)

Where MONO_TYPE_IS_VECTOR_PRIMITIVE is:

#define MONO_TYPE_IS_VECTOR_PRIMITIVE(t) ((!m_type_is_byref ((t)) && ((((t)->type >= MONO_TYPE_I1 && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U)))))


For reference; in .NET 6 Vector64/128/256<T> only support:

  • byte and sbyte
  • short and ushort
  • int and uint
  • long and ulong
  • float and double

While Vector<T> supports those plus nint and nuint.
In .NET 7, Vector64/128/256<T> also support nint and nuint bringing them inline.

We do not support bool, char, decimal, or half today (or any of the other types that may be built-in or specially recognized).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the detailed explanation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannergooding So it is not guaranteed that runtime would only be given the supported types?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. A user can go declare Vector<bool> just fine, nothing prevents that. Same with Vector<Guid>, etc

Attempting to use any of the methods/members on Vector<bool> is expected to fail however. So the JIT shouldn't intrinsify them and should let the managed type checks throw the relevant exception

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue #65318 to track the cleanup work.

@@ -635,6 +636,18 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;

switch (id) {
case SN_Abs: {
#ifdef TARGET_ARM64
MonoType *arg_type = get_vector_t_elem_type (fsig->params [0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix indentation.

MonoType *arg_type = get_vector_t_elem_type (fsig->params [0]);
if (!MONO_TYPE_IS_INTRINSICS_VECTOR_PRIMITIVE (arg_type))
return NULL;
gboolean is_float = type_is_float (fsig->params [0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is faster to make type comparison directly here, since you have arg0_type already. If you look at the content of type_is_float, that's exactly what it does but with more calls to get arg0_type.

Suggested change
gboolean is_float = type_is_float (fsig->params [0]);
gboolean is_float = arg0_type == MONO_TYPE_R4 || arg0_type == MONO_TYPE_R8;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

@mkhamoyan mkhamoyan merged commit 3933fc6 into dotnet:main Feb 10, 2022
@mkhamoyan mkhamoyan deleted the merikhamoyan-vector-intrinsics-Abs branch February 10, 2022 14:36
@dotnet dotnet locked as resolved and limited conversation to collaborators Mar 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants