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

ARM64-SVE: Allow SVE ops to re-use the same registers #107084

Merged
merged 5 commits into from
Sep 13, 2024

Conversation

a74nh
Copy link
Contributor

@a74nh a74nh commented Aug 28, 2024

Fixes #106866

RMW intrinsics can use the RMW register in other inputs. The only restriction is that those inputs will be overwritten.

Added extra intrinsic testing to cover this. Requires #107036 for all the tests to pass.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 28, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Aug 28, 2024
@a74nh a74nh marked this pull request as ready for review August 28, 2024 13:52
@a74nh
Copy link
Contributor Author

a74nh commented Aug 28, 2024

@dotnet/arm64-contrib @kunalspathak

@a74nh
Copy link
Contributor Author

a74nh commented Aug 30, 2024

Given the discussions over in #107036, I think this PR is correct.

For this case we have:

Generating: N017 (  1,  1) [000033] -----+-----                   t33 =    LCL_VAR   simd16 V07 tmp6         u:2 d0 REG d0 $80
Generating: N019 (  1,  1) [000034] -----+-----                   t34 =    LCL_VAR   simd16 V07 tmp6         u:2 d0 (last use) REG d0 $80
                                                                        /--*  t37    mask
                                                                        +--*  t33    simd16
                                                                        +--*  t34    simd16
Generating: N021 (  6,  6) [000035] -----+-----                   t35 = *  HWINTRINSIC simd16 byte Splice REG d0 $240
							V07 in reg d0 is becoming dead  [000034]
							Live regs: 0000000100000000 {d0} - {d0} => 0000000000000000 {}
							Live vars after [000034]: {V07} -{V07} => {}
IN0004:             splice  z0.b, p0, z0.b, z0.b

Like in the previous PR, we have the same value used twice. But here we are not going to use a MOVPRFX (due to it not being wrapped with conditional select). Therefore we have no requirement to delay free the operands, and can simply allow the same one to be used.

@kunalspathak kunalspathak added the arm-sve Work related to arm64 SVE/SVE2 support label Sep 3, 2024
Copy link
Member

@kunalspathak kunalspathak left a comment

Choose a reason for hiding this comment

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

I am not totally convinced that we should be removing all the asserts without seeing a case that hits it. Its ok to put some of them back for now and relax them as we see cases.

@@ -1106,7 +1106,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
}
else if (isRMW)
{
assert((targetReg == op1Reg) || (targetReg != op2Reg));
Copy link
Member

Choose a reason for hiding this comment

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

as we spoke offline, did you verify if we put this assert back, do we hit them. These asserts were added conservatively with the idea that we understand the scenario under which this cannot be true. I am wondering if we should remove these as we see scenarios that trigger them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Restored this one

src/coreclr/jit/hwintrinsiccodegenarm64.cpp Show resolved Hide resolved
@@ -1124,18 +1123,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
if (HWIntrinsicInfo::IsExplicitMaskedOperation(intrin.id))
{
assert((targetReg == op1Reg) || (targetReg != op1Reg));
Copy link
Member

Choose a reason for hiding this comment

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

these are OK to have.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These ones are hit by the new hwintrinsic tests:

------------------- {'JitStressRegs': '1'} -------------------
Errors:

Assert failure(PID 366410 [0x0005974a], Thread: 366410 [0x5974a]): Assertion failed '(targetReg == op1Reg) || (targetReg != op3Reg)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleTernaryOpTest__Sve_ConditionalExtractAfterLastActiveElementAndReplicate_float:RunSameClassFldScenario():this' during 'Generate code' (IL size 92; hash 0xa42df59e; FullOpts)

    File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:1118
    Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun

Copy link
Member

@tannergooding tannergooding Sep 13, 2024

Choose a reason for hiding this comment

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

We need some kind of assert validating the mov is valid.

Since we're doing mov targetReg, op2Reg, then when targetReg == op1Reg and op1Reg != op2Reg, then the we would overwrite op1 and produce in incorrect results.

So, therefore, we expect that targetReg == op2Reg so no mov is emitted -or- op1/op2 have been marked delayFree

The assert therefore needs to be something like assert((targetReg == op2Reg) || ((targetReg != op1Reg) && (targetReg != op3Reg)). Which validates no move or no overwrite

Copy link
Member

Choose a reason for hiding this comment

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

All paths need some kind of similar assert validating no move or no overwrite, if a move is emitted

Copy link
Member

Choose a reason for hiding this comment

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

All paths need some kind of similar assert validating no move or no overwrite, if a move is emitted

Agree.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done replaced this assert as suggested, and the next one with a similar assert

Copy link
Contributor Author

Choose a reason for hiding this comment

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

confirmed stress tests passing.

@a74nh
Copy link
Contributor Author

a74nh commented Sep 13, 2024

Stress tests working with the latest version

Copy link
Member

@kunalspathak kunalspathak left a comment

Choose a reason for hiding this comment

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

LGTM

@kunalspathak kunalspathak merged commit cf9c995 into dotnet:main Sep 13, 2024
117 checks passed
@kunalspathak
Copy link
Member

/backport to release/9.0

Copy link
Contributor

Started backporting to release/9.0: https://github.com/dotnet/runtime/actions/runs/10855965106

Copy link
Contributor

@kunalspathak backporting to release/9.0 failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Applying: ARM64-SVE: Allow SVE ops to re-use the same registers
Using index info to reconstruct a base tree...
M	src/coreclr/jit/hwintrinsiccodegenarm64.cpp
Falling back to patching base and 3-way merge...
Auto-merging src/coreclr/jit/hwintrinsiccodegenarm64.cpp
CONFLICT (content): Merge conflict in src/coreclr/jit/hwintrinsiccodegenarm64.cpp
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 ARM64-SVE: Allow SVE ops to re-use the same registers
Error: The process '/usr/bin/git' failed with exit code 128

Please backport manually!

Copy link
Contributor

@kunalspathak an error occurred while backporting to release/9.0, please check the run log for details!

Error: git am failed, most likely due to a merge conflict.

kunalspathak pushed a commit to kunalspathak/runtime that referenced this pull request Sep 13, 2024
* ARM64-SVE: Allow SVE ops to re-use the same registers

* Add Sve.IsSupported

* restore an assert

* better asserts
@a74nh a74nh deleted the reg3_github branch September 16, 2024 08:39
jeffschwMSFT added a commit that referenced this pull request Sep 16, 2024
…107818)

* ARM64-SVE: Allow SVE ops to re-use the same registers (#107084)

* ARM64-SVE: Allow SVE ops to re-use the same registers

* Add Sve.IsSupported

* restore an assert

* better asserts

* resolve merge conflicts

---------

Co-authored-by: Alan Hayward <a74nh@users.noreply.github.com>
Co-authored-by: Jeff Schwartz <jeffschw@microsoft.com>
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* ARM64-SVE: Allow SVE ops to re-use the same registers

* Add Sve.IsSupported

* restore an assert

* better asserts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI arm-sve Work related to arm64 SVE/SVE2 support community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JIT SVE: Assertion failed '(targetReg == op1Reg) || (targetReg != op3Reg)' during 'Generate code'
3 participants