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][amd64] Pass and return SIMD values in SIMD registers. #93182

Closed
wants to merge 6 commits into from

Conversation

vargaz
Copy link
Contributor

@vargaz vargaz commented Oct 7, 2023

No description provided.

@vargaz
Copy link
Contributor Author

vargaz commented Oct 11, 2023

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@vargaz
Copy link
Contributor Author

vargaz commented Oct 11, 2023

Can't reproduce the x64 failures.

@vargaz
Copy link
Contributor Author

vargaz commented Oct 12, 2023

/azp run runtime

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

if (*fr >= FLOAT_PARAM_REGS) {
pass_on_stack = TRUE;
} else {
ainfo->storage = ArgSIMDInSSEReg;
Copy link
Member

Choose a reason for hiding this comment

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

Is it intentional this doesn't match the native ABI for the platform?

There are particular rules for when and how certain SIMD types are passed depending on the ABI of the underlying platform (Windows x64, Unix SysV, etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just an experiment right now, it has many problems, including this one.

@vargaz
Copy link
Contributor Author

vargaz commented Oct 18, 2023

/azp run runtime

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@vargaz
Copy link
Contributor Author

vargaz commented Oct 18, 2023

Remaining issues:

  • windows support
  • dyncalls (method invokes)
  • gsharedvt (not really used on amd64 in production)
  • non 16 byte types

@vargaz vargaz changed the title [mono][amd64] Pass SIMD arguments in SIMD registers. [mono][amd64] Pass and return SIMD values in SIMD registers. Oct 18, 2023
@lateralusX
Copy link
Member

lateralusX commented Oct 19, 2023

Remaining issues:

  • windows support
  • dyncalls (method invokes)
  • gsharedvt (not really used on amd64 in production)
  • non 16 byte types

@vargaz What happens if gsharedvt is used, will we fallback and use none SIMD regs as we did before this PR or will just not when having SIMD types in parameters or return type?

@lateralusX
Copy link
Member

Remaining issues:

  • windows support
  • dyncalls (method invokes)
  • gsharedvt (not really used on amd64 in production)
  • non 16 byte types

I will look into windows support for this, working on it in a downstream repro to see how it behaves and will then upstream. Don't think that should block us from progressing on this PR.

@vargaz
Copy link
Contributor Author

vargaz commented Oct 30, 2023

Another significant problem is that the generic instances used by generic sharing like Vector<T_INT> are not marked as simd types, so for T return_t<T> (T t), the return_t<Vector<int>> instance has a different calling convention than the shared return_t<Vector<T_INT>>) instance, which is not going to work.

@lateralusX
Copy link
Member

Another significant problem is that the generic instances used by generic sharing like Vector<T_INT> are not marked as simd types, so for T return_t<T> (T t), the return_t<Vector<int>> instance has a different calling convention than the shared return_t<Vector<T_INT>>) instance, which is not going to work.

I guess it will be possible for caller to detect this scenario and choose calling convention accordingly?

XMOVE can be optimized away which creates problems if the argument is on the stack, since
mono_spill_global_vars () doesn't process call arguments, it only processes the move
instructions before it. If a normal argument is on the stack, it means its volatile/indirect,
so its move is not optimized away, but for simd args, they can become indirect when
the xcall opcode is decomposed which can happen after the xmove was optimized away, so
we end up with code like:

```
ldaddr R19 <- R20
 vcall2
voidcall [..] [s:xmm0 <- R20]
```
@vargaz
Copy link
Contributor Author

vargaz commented Nov 6, 2023

So it looks like gshared support for the simd types cannot really be enabled right now, because gsharing for primitive types works by erasing the difference between primitive types and enums, so a Vector128<T_INT> can be instantiated by both an int an enums whose base type is int, but the simd types don't allow enum element types.
So if gsharing is enabled for vectors, then this code:

public static void foo<T> (Vector128<T> v1, Vector128<T> v2) {
        for (int i = 0; i < 10000000; ++i)
            v1 = v1 + v2;
}

foo<AnEnum> (default(Vector128<AnEnum>), default(Vector128<AnEnum>));

will no longer throw an exception.

@vargaz
Copy link
Contributor Author

vargaz commented Dec 3, 2023

Closing for now.

@vargaz vargaz closed this Dec 3, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Jan 3, 2024
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.

3 participants