Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add support for Sve.DuplicateSelectedScalarToVector() - #103228

Merged
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector
Jun 27, 2024
Merged

Add support for Sve.DuplicateSelectedScalarToVector()#103228
kunalspathak merged 10 commits into
dotnet:mainfrom
SwapnilGaikwad:github-sve-duplicateScalarToVector

Conversation

@SwapnilGaikwad

Copy link
Copy Markdown
Contributor

Contribute towards #99957.

@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost

Copy link
Copy Markdown

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jun 10, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime-intrinsics
See info in area-owners.md if you want to be subscribed.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@a74nh@kunalspathak @dotnet/arm64-contrib @arch-arm64-sve

@SwapnilGaikwad

SwapnilGaikwad commented Jun 10, 2024

Copy link
Copy Markdown
ContributorAuthor

There are a few assertion failures, related to STR. Taking a further look.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
Errors:
Assert failure(PID 2894704 [0x002c2b70], Thread: 2894704 [0x2c2b70]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
Errors:
Assert failure(PID 2894838 [0x002c2bf6], Thread: 2894838 [0x2c2bf6]): Assertion failed 'isValidSimm<9>(emitGetInsSC(id))' in 'JIT.HardwareIntrinsics.Arm._Sve.Program:SveDuplicateSelectedScalarToVector_double()' during 'Generate code' (IL size 115; hash 0x749c6f16; FullOpts)
File: /home/user/dotnet/runtime/src/coreclr/jit/emitarm64sve.cpp:14192
Image: /home/user/dotnet/runtime/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@kunalspathak

Copy link
Copy Markdown
Contributor

related to STR.

I have seen them in the past, but yes, if you can find out what is the cause, that will be good.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

All stress tests are passing now.

Stress test results
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.SveDuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

@SwapnilGaikwad
SwapnilGaikwad marked this pull request as ready for review June 11, 2024 14:07

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added few things to check.

Comment threadsrc/coreclr/jit/hwintrinsicarm64.cpp Outdated
break;

case NI_Sve_DuplicateSelectedScalarToVector:
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
immUpperBound = (512 / (genTypeSize(baseType) * BITS_PER_BYTE)) - 1;
immUpperBound = Compiler::getSIMDVectorLength(simdSize, baseType) - 1;

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

We may not able able to use the getSIMDVectorLength() here as the imm for DUP seems special [1].

Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".

I didn't find a better helper method for this so did it explicitly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was actually little confused with that description and then this one:

The immediate element index is in the range of 0 to 63 (bytes), 31 (halfwords), 15 (words), 7 (doublewords) or 3 (quadwords).

With ^ description, it sounded me like getSIMDVectorLength(), no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

It's a bit confusing. Unlike other cases, the index here does not depend on the vector length. A valid index range is fixed based on the element type, e.g., 0 to 63 for vectors of type byte.

ValidateResult(_dataTable.inArrayPtr, {Imm}, _dataTable.outArrayPtr);
}

public void RunBasicScenario_UnsafeRead_InvalidImm()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you confirm what is the behavior here?

From https://docsmirror.github.io/A64/2023-06/dup_z_zi.html, is it validating this portion:

 Selecting an element beyond the accessible vector length causes the destination vector to be set to zero.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Invalid index refers to a value that is permitted but out of bounds on the current system. E.g., bytes permitted index values are between 0 to 63 but on a 256bit SVE length machine, valid indices can be between 256 / 8 - 1 = 0 to 31. Thus, the indices between 32 to 63 would set the destination value to zero.

Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/tests/Common/GenerateHWIntrinsicTests/GenerateHWIntrinsicTests_Arm.cs Outdated
Comment threadsrc/coreclr/jit/emitarm64.cpp Outdated
Comment threadsrc/coreclr/jit/hwintrinsiclistarm64sve.h Outdated
Comment threadsrc/coreclr/jit/hwintrinsiccodegenarm64.cpp Outdated
@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

The tests with short are failing with the following assertion error. Not sure if it's related to the patch.
Do you have any suggestions on how to fix them?

Beginning scenario: RunBasicScenario_UnsafeRead
Assert failure(PID 1069122 [0x00105042], Thread: 1069122 [0x105042]): Assertion failed '(candidates & allRegs(regType)) != RBM_NONE' in 'System.Runtime.Intrinsics.Arm.Sve:DuplicateSelectedScalarToVector(System.Numerics.Vector`1[short],ubyte):System.Numerics.Vector`1[short]' during 'LSRA build intervals' (IL size 8; hash 0x3d7d92ae; Tier0)
File: /home/user/dotnet/runtime/src/coreclr/jit/lsra.cpp:2913
Image: /home/user/dotnet/runtime/dup-artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
Aborted (core dumped)

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

JIT dump for a failing method.

@kunalspathak

Copy link
Copy Markdown
Contributor

JIT dump for a failing method.

@SwapnilGaikwad - Are you sure this one is the right dump? I see the compilation succeed in this dump.

@kunalspathak

Copy link
Copy Markdown
Contributor

Do you have any suggestions on how to fix them?

This is to do with that a node is of type TYP_FLOAT and we assigned it candidates of TYP_MASK or vice-versa. It might not be directly related to your PR, but something that your PR exposed specially after the LSRA work of predicate register is complete. If you share the correct dump, I can quickly tell for which node it is getting wrong, and you can then track in lsraarm64.cpp why that is happening.

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector.
I have updated the gist with the correct dump now.

@kunalspathak

Copy link
Copy Markdown
Contributor

Hi Kunal, apologies. It was dump of the parent test method that emitted a call to Sve.DuplicateSelectedScalarToVector. I have updated the gist with the correct dump now.

DefList: { N004.t0. LCL_VAR; N014.t1. LCL_VAR }
N016 ( 4, 4) [000009] ----------- * CAST int <- ubyte <- int REG NA
<RefPosition #7 @16 RefTypeUse <Ivl:3> BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=100.00>
Interval 4: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #8 @17 RefTypeDef <Ivl:4> CAST BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
DefList: { N004.t0. LCL_VAR; N016.t9. CAST }
N018 ( 17, 20) [000006] ---X------- * HWINTRINSIC simd16 short DuplicateSelectedScalarToVector REG NA
Interval 5: int RefPositions {} physReg:NA Preferences=[x0-xip0 x19-x28] Aversions=[]
<RefPosition #9 @18 RefTypeDef <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 wt=400.00>
<RefPosition #10 @18 RefTypeUse <Ivl:0> BB01 regmask=[allFloat] minReg=1 last wt=100.00>
<RefPosition #11 @18 RefTypeUse <Ivl:4> BB01 regmask=[d0-d15] minReg=1 last wt=100.00>
<RefPosition #12 @18 RefTypeUse <Ivl:5 internal> HWINTRINSIC BB01 regmask=[x0-xip0 x19-x28] minReg=1 last wt=400.00>
Interval 6: simd16 RefPositions {} physReg:NA Preferences=[allFloat] Aversions=[]
<RefPosition #13 @19 RefTypeDef <Ivl:6> HWINTRINSIC BB01 regmask=[allFloat] minReg=1 wt=400.00>

I think the problem is in <Ivl:4>. For def RefPosition #8, the mask created is GPR, but the use RefPosition #11, the mask if d0-d15 which is GPR, which seems wrong. So, you might want to check by putting breakpoint in newRefPositionRaw() for newRP->rpNum == 11 why the mask is not gpr.

@kunalspathak

Copy link
Copy Markdown
Contributor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

@SwapnilGaikwad

Copy link
Copy Markdown
ContributorAuthor

@SwapnilGaikwad - I assume you don't need anything from me for this PR?

Hi @kunalspathak , I haven't exhausted all the debugging possibilities yet. I might come back with questions 🙂 .

@SwapnilGaikwad

SwapnilGaikwad commented Jun 26, 2024

Copy link
Copy Markdown
ContributorAuthor

why the mask is not gpr

Hi @kunalspathak , your suggestion was very useful to identify the issue. The mask was hardcoded to simd registers for op2.

All stress tests pass
===================Running default===================
------------------- {} -------------------
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_float() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_double() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_sbyte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_short() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_int() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_long() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_byte() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ushort() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_uint() : 17
Passed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_DuplicateSelectedScalarToVector_ulong() : 17
===================Running jitstress===================
------------------- {'JitMinOpts': '1'} -------------------
------------------- {'JitStress': '1'} -------------------
------------------- {'JitStress': '2'} -------------------
------------------- {'JitStress': '1', 'TieredCompilation': '1'} -------------------
------------------- {'JitStress': '2', 'TieredCompilation': '1'} -------------------
------------------- {'TailcallStress': '1'} -------------------
------------------- {'ReadyToRun': '0'} -------------------
===================Running jitstressregs===================
------------------- {'JitStressRegs': '1'} -------------------
------------------- {'JitStressRegs': '2'} -------------------
------------------- {'JitStressRegs': '3'} -------------------
------------------- {'JitStressRegs': '4'} -------------------
------------------- {'JitStressRegs': '8'} -------------------
------------------- {'JitStressRegs': '0x10'} -------------------
------------------- {'JitStressRegs': '0x80'} -------------------
------------------- {'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStressRegs': '0x2000'} -------------------
===================Running jitstress2-jitstressregs===================
------------------- {'JitStress': '2', 'JitStressRegs': '1'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '2'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '3'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '4'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '8'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x10'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x80'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x1000'} -------------------
------------------- {'JitStress': '2', 'JitStressRegs': '0x2000'} -------------------

Comment threadsrc/coreclr/jit/lsraarm64.cpp

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good overall. Have a question about the change in codegenarm64.cpp.

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

regNumber rsvdReg = codeGen->rsGetRsvdReg();
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
// For larger imm values (> 9 bits), calculate base + imm in a reserved register first.
codeGen->instGen_Set_Reg_To_Base_Plus_Imm(EA_PTRSIZE, rsvdReg, reg2, imm);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this change related to the DUP? Don't think so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I might actually need it for https://github.com/dotnet/runtime/pull/104065/files#diff-2b2c8b9011607926410624d6f81613fad7b74c6e0516d578675a8b792998fe4fR7893-R7896, but I am curious if you found a repro, for which you had to add change here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

This is not related to DUP directly. However, tests trigger a scenario where we end up in having a store with a larger immediate.

@kunalspathak

Copy link
Copy Markdown
Contributor

Also, how are we exposing DUP (immediate) and DUP (scalar) ?

Spoke offline that we will use these in future when we intrinsify Vector.Create or similar scenario for sve.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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 5b962c3 into dotnet:mainJun 27, 2024
@SwapnilGaikwad
SwapnilGaikwad deleted the github-sve-duplicateScalarToVector branch June 27, 2024 16:18
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.Intrinsicsarm-sveWork related to arm64 SVE/SVE2 supportcommunity-contributionIndicates that the PR has been added by a community membernew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@SwapnilGaikwad@kunalspathak