Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm
, '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

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select - #100743

Merged
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional
Apr 24, 2024
Merged

Arm64/Sve: Predicated Abs, Predicated/UnPredicated Add, Conditional Select#100743
kunalspathak merged 52 commits into
dotnet:mainfrom
kunalspathak:abi_abs_conditional

Conversation

@kunalspathak

@kunalspathakkunalspathak commented Apr 7, 2024

Copy link
Copy Markdown
Contributor

Based on the feedback from @tannergooding in #100134 (comment), I reworked #100134 a little bit and also included the ConditionalSelect I implemented in #100718.

The change in design is that we do not touch the HWIntrinsic node until lowerer. In lowerer, we wrap the node in ConditionalSelect(mask, original_operation, falseVal) and contain the original operation. This lets us easily determine which API should map to the predicate vs. unpredicated version of the instruction.

  • For APIs like Abs which only has predicated version, in lowerer, we wrap it in ConditionalSelect(ptrueAll, Abs, zero). During containment analysis, for ConditionalSelect, we check if 2nd operand is scalable SVE instrinsic and if yes, we mark it as contained. During codegen, the ConditionalSelect that has op2 as contained needs to go through the "predicated" version of the instruction.
  • For APIs like Add that has both predicated and unpredicated versions, they are handled differently. For unpredicated Add, it does not get marked as contained and in codegen, generates unpredicated version. In order to generate predicated version of add, user has to write a code such that Add is wrap inside a conditional, e.g. ConditionalSelect(mask, Add(x,y), b). If yes, then it follows same path as Abs and generates predicate version of the instruction.

There are still some handling needs to be done for RMW, but want to get feedback on the design before I move forward. The sample test case along with the output can be found in https://gist.github.com/kunalspathak/bc4e917ced68bef793d11fcbd050162c
https://gist.github.com/kunalspathak/1fb0b17f0908ba26e46f0cd146ab05b8 .

I still need to handle cases where user writes ConditionalSelect(mask, Abs(x), y). Currently we end of expanding Abs with another ConditionalSelect.

Thanks @tannergooding for the design discussion and helping me understand the concepts.

@ghostghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI new-api-needs-documentation labels Apr 7, 2024
@ghost

ghost commented Apr 7, 2024

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.

Comment threadsrc/coreclr/jit/lowerarmarch.cpp Outdated
@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@tannergooding - can you take another look? I have added bunch of scenarios to use `ConditionalSelect() on unary/binary operations including:

  • Pass op1 as falseValue in ConditionalSelect() done on top of the API
  • Pass op2 as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as falseValue in ConditionalSelect() done on top of the API
  • Pass Zero as maskValue in ConditionalSelect() done on top of the API
  • Pass AllBitSet as maskValue in ConditionalSelect() done on top of the API
  • Make sure maskValue has mix of 0s as well.

I also tested the newly added test cases using https://github.com/a74nh/runtime/blob/api_github/sve_api/stress_tester.py and they all pass.

{
assert(numArgs > 0);
GenTree* op1 = retNode->AsHWIntrinsic()->Op(1);
if (intrinsic == NI_Sve_ConditionalSelect)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not important for this PR, but this is potentially something that should be handled in gtNewSimdCndSelNode instead and then more generally as part of morph to capture values that don't materialize as constants until later.

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.

will do it in follow-up PR.

@a74nh

Copy link
Copy Markdown
Contributor

I'm getting a failure with the abs and add tests:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_Abs_int
14:07:31.270 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_Abs_int()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Assert failure(PID 1134821 [0x001150e5], Thread: 1134821 [0x1150e5]): Assertion failed 'isVectorRegister(reg2)' in 'JIT.HardwareIntrinsics.Arm._Sve.SimpleUnaryOpTest__Sve_Abs_int:RunBasicScenario_UnsafeRead():this' during 'Generate code' (IL size 83; hash 0x0487a6e9; Tier0)
File: /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
Image: /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/linux.arm64.Checked/Tests/Core_Root/corerun
[1] 1134821 abort (core dumped) $CORE_ROOT/corerun Sve_Abs_int

Backtrace:

#0 DBG_DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/arch/arm64/debugbreak.S:7
#1 0x0000ffffed1029d0 in DebugBreak () at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/pal/src/debug/debug.cpp:407
#2 0x0000ffffecdf8440 in assertAbort (why=0xffffecc8c644 "isVectorRegister(reg2)",
file=0xffffecc66283 "/home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp", line=2248)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/error.cpp:288
#3 0x0000ffffed099178 in emitter::emitInsSve_R_R (this=0xaaaaab99a400, ins=INS_sve_movprfx, attr=EA_SCALABLE, reg1=REG_V16, reg2=REG_COUNT,
opt=INS_OPTS_NONE, sopt=INS_SCALABLE_OPTS_NONE) at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/emitarm64sve.cpp:2248
#4 0x0000ffffed0e8bf0 in CodeGen::genHWIntrinsic (this=0xaaaaab999b08, node=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/hwintrinsiccodegenarm64.cpp:444
#5 0x0000ffffecdc3440 in CodeGen::genCodeForBBlist (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegenlinear.cpp:472
#6 0x0000ffffecdb6aa0 in CodeGen::genGenerateMachineCode (this=0xaaaaab999b08)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegencommon.cpp:1877
#7 0x0000ffffecdc1a70 in CodeGenPhase::DoPhase (this=<optimized out>)
at /home/alahay01/dotnet/runtime_sve_api/src/coreclr/jit/codegen.h:1703

Looks like reg2 is invalid in frame 3. reg2=REG_COUNT

@a74nh

Copy link
Copy Markdown
Contributor

Also some (but not all) of the conditional tests are failing:

❯ $CORE_ROOT/corerun ./artifacts/tests/coreclr/linux.arm64.Checked/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/HardwareIntrinsics_Arm_ro.dll Sve_ConditionalSelect_sbyte
14:12:14.806 Running test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()
Supported ISAs:
AdvSimd: True
Aes: True
ArmBase: True
Crc32: True
Dp: True
Rdm: True
Sha1: True
Sha256: True
Sve: True
Beginning scenario: RunBasicScenario_UnsafeRead
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_UnsafeRead failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunBasicScenario_Load
Sve.ConditionalSelect<SByte>(Vector<SByte>, Vector<SByte>, Vector<SByte>): RunBasicScenario_Load failed:
firstOp: (29, 69, 117, 63, 117, 109, 74, 55, 16, 108, 36, 47, 71, 38, 19, 120)
secondOp: (56, 113, 53, 30, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
thirdOp: (44, 17, 40, 89, 16, 50, 66, 38, 4, 12, 56, 112, 105, 17, 76, 72)
result: (-1, -1, 0, 0, 67, 23, 97, 124, 31, 20, 23, 120, 105, 44, 50, 103)
Beginning scenario: RunReflectionScenario_UnsafeRead
Beginning scenario: RunLclVarScenario_UnsafeRead
Beginning scenario: RunClassFldScenario
Beginning scenario: RunStructLclFldScenario
Beginning scenario: RunStructFldScenario
System.Exception: One or more scenarios did not complete as expected.
at JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte() in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/Arm/Sve/Sve_ro/Sve_ro/gen/Sve.ConditionalSelect.sbyte.cs:line 62
at Program.<<Main>$>g__TestExecutor2723|0_2724(StreamWriter tempLogSw, StreamWriter statsCsvSw, <>c__DisplayClass0_0&) in /home/alahay01/dotnet/runtime_sve_api/artifacts/tests/coreclr/obj/linux.arm64.Checked/Managed/JIT/HardwareIntrinsics/HardwareIntrinsics_Arm_ro/generated/XUnitWrapperGenerator/XUnitWrapperGenerator.XUnitWrapperGenerator/FullRunner.g.cs:line 68199
14:12:15.143 Failed test: _Sve_ro::JIT.HardwareIntrinsics.Arm._Sve.Program.Sve_ConditionalSelect_sbyte()

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

Thanks @a74nh - i will take a look.

@kunalspathak

Copy link
Copy Markdown
ContributorAuthor

@a74nh - The Abs failures are known and are fixed in #101515. With that PR and main, all the tests are passing for me as seen in https://gist.github.com/kunalspathak/73e0cfd469a70fd4b5466bada45df2eb. So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

@a74nh

a74nh commented Apr 26, 2024

Copy link
Copy Markdown
Contributor

So perhaps, it could be 256-bit machine difference? Can you try restricting it to 128-bit and check if they still fail for you?

Yes, it looks like the conditionalselect failures are 256bit issues. Works on 256bit machine when I restrict the vector length to 128bit.

matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…elect (dotnet#100743)
* JIT ARM64-SVE: Add Sve.Abs() and Sve.Add()
Change-Id: Ie8cfe828595da9a87adbc0857c0c44c0ce12f5b2
* Fix sve scaling in enitIns_R_S/S_R
* Revert "Fix sve scaling in enitIns_R_S/S_R"
This reverts commit e9fa735.
* Fix sve scaling in enitIns_R_S/S_R
* Restore testing
* Use NaturalScale_helper for vector load/stores
* wip
* Add ConditionalSelect() APIs
* Handle ConditionalSelect in JIT
* Add test coverage
* Update the test cases
* jit format
* fix merge conflicts
* Make predicated/unpredicated work with ConditionalSelect
Still some handling around RMW is needed, but this basically works
* Misc. changes
* jit format
* jit format
* Handle all the conditions correctly
* jit format
* fix some spacing
* Removed the assert
* fix the largest vector size to 64 to fixdotnet#100366
* review feedback
* wip
* Add SVE feature detection for Windows
* fix the check for invalid alignment
* Revert "Add SVE feature detection for Windows"
This reverts commit ed7c781.
* Handle case where Abs() is wrapped in another conditionalSelect
* jit format
* fix the size comparison
* HW_Flag_MaskedPredicatedOnlyOperation
* Revert the change in emitarm64.cpp around INS_sve_ldr_mask/INS_sve_str_mask
* Fix the condition for lowering
* address review feedback for movprfx
* Move the special handling of Vector<>.Zero from lowerer to importer
* Rename IsEmbeddedMaskedOperation/IsOptionalEmbeddedMaskedOperation
* Add more test coverage for conditionalSelect
* Rename test method name
* Add more test coverage for conditionalSelect:Abs
* jit format
* Add logging on test methods
* Add the missing movprfx for abs
* Add few more scenarios where falseVal is zero
* Make sure LoadVector is marked as explicit needing mask
* revisit the codegen logic
* Remove commented code and add some other comments
* jit format
---------
Co-authored-by: Alan Hayward <alan.hayward@arm.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 27, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIarm-sveWork related to arm64 SVE/SVE2 supportnew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@kunalspathak@tannergooding@a74nh@TamarChristinaArm