Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall
, '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

Implement LoadPairVector64 and LoadPairVector128 - #64864

Merged
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128
Feb 10, 2022
Merged

Implement LoadPairVector64 and LoadPairVector128#64864
echesakov merged 30 commits into
dotnet:mainfrom
echesakov:Arm64-ASIMD-LoadPairVector64-LoadPairVector128

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

Resolves#39243

@echesakovechesakov added arch-arm64 area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels Feb 6, 2022
@echesakovechesakov self-assigned this Feb 6, 2022
@ghost

ghost commented Feb 6, 2022

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, to 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.

@ghost

ghost commented Feb 6, 2022

Copy link
Copy Markdown

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

null

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

arch-arm64, area-CodeGen-coreclr

Milestone:-

…elpers.cs src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.tt
…mStructVal() to allow intrinsics returning a struct in importer.cpp
…alues in multiple registers in lsra.h lsraarm64.cpp lsraxarch.cpp
@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib @tannergooding PTAL

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
unreached();
}
#elif defined(TARGET_XARCH)
return 2;

@tannergoodingtannergoodingFeb 9, 2022

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.

nit: would be good to explicitly cover the intrinsic IDs for xarch as well (definitely could be a separate PR).

(that is switch (intrinsicId) with a default: unreached())

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.

Right, given that none are supported currently on X86 - I can replace this with unreached() and update with the switch when working on MultiplyNoFlags2 (or whatever name we decided)

Comment threadsrc/coreclr/jit/gentree.cpp Outdated
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:

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.

I'll probably see later in the review, but under what conditions are these containable?

I didn't think Arm64 really had ins reg, [mem] operations outside atomic instructions; particularly for non-temporal operations...

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.

Actually, I don't see where the containment handling is happening for this. I don't see any changes to lowering

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.

I think I marked them by mistake when experimenting with some ideas I had. Let me update this.

Comment threadsrc/coreclr/jit/gentree.h Outdated
if (OperIsHWIntrinsic())
{
return (TypeGet() == TYP_STRUCT);
return TypeIs(TYP_STRUCT);

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.

I wonder how well this will hold in the future? That is, are we expecting things that return TYP_STRUCT to always be multi-reg?

There are cases like say System.Half where we'll eventually need to add support and we'll need to treat it as TYP_HALF or recognize it some other way if we don't want it to be an issue.

I wonder if we should track this as a flag rather than by type just to be safe?

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.

Ah, looks like we have a flag. Maybe we should assert it or use it here instead?

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.

Sure, I can use a flag here.

Comment threadsrc/coreclr/jit/gentree.h Outdated
Comment on lines +8091 to +8115
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
#ifdef TARGET_ARM64
const GenTreeHWIntrinsic* intrinsic = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = intrinsic->GetHWIntrinsicId();

switch (intrinsicId)
{
// TODO-ARM64-NYI: Support hardware intrinsics operating on multiple contiguous registers.
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector64:
case NI_AdvSimd_Arm64_LoadPairVector64NonTemporal:
case NI_AdvSimd_Arm64_LoadPairVector128:
case NI_AdvSimd_Arm64_LoadPairVector128NonTemporal:
return 2;

default:
unreached();
}
#elif defined(TARGET_XARCH)
return 2;
}
#endif
}

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.

This looks to be the same logic as in gentree.cpp above. Should it be factored out into a shared helper or are there conditions where they won't/shouldn't be in sync?

else
{
assert(AsHWIntrinsic()->GetSimdSize() == 8);
return TYP_SIMD8;

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.

Do we have any cases of "arg size is 8" but "return size is 16" or vice-versa?

I know some instructions fit that bill, I'm not sure if any of the multi-reg cases will

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.

I don't see an example on Arm64 when this wouldn't hold.
ld[1-4] should be similar to ldp.

As for tbl and tbx:

TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>

the return value is going to be single-reg but the first source operand is multi-reg and composed of Vector128<byte>.

@tannergooding

Copy link
Copy Markdown
Member

Changes generally LGTM. Left some comments/questions on a couple bits on how we expect certain checks to work long term.

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@SamMonoRT

Copy link
Copy Markdown
Member

cc @imhameed@fanyang-mono

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Would be great to see a couple diffs/codegen examples particularly for the library changes.

@tannergooding There are suboptimalities in the code using LoadPairVector in the libraries.

To fix that I would need to implement #64863 and #64857.

If I apply these changes on top of this PR the code diffs would look as expected:

GetIndexOfFirstCharToEncodeAdvSimd64

@@ -69,10 +73,8 @@ G_M52035_IG03:
;; bbWeight=0.50 PerfScore 0.25
G_M52035_IG04:
add x6, x1, x4, LSL #1
- ld1 {v20.8h}, [x6]+ ldp q20, q21, [x6]
sqxtun v20.8b, v20.8h
- add x6, x6, #16- ld1 {v21.8h}, [x6]
sqxtun2 v20.16b, v21.8h
and v21.16b, v20.16b, v16.16b
tbl v21.16b, {v19.16b}, v21.16b
@@ -87,7 +89,7 @@ G_M52035_IG04:
add x4, x4, #16
cmp x4, x5
blo G_M52035_IG04
- ;; bbWeight=4 PerfScore 100.00+ ;; bbWeight=4 PerfScore 86.00

GetIndexOfFirstNonAsciiByte_Intrinsified

@@ -208,9 +211,8 @@ G_M18966_IG11:
@@ -208,9 +211,7 @@ G_M18966_IG11:
sub x22, x0, #32
;; bbWeight=0.50 PerfScore 1.75
G_M18966_IG12:
- ld1 {v16.16b}, [x19]- add x0, x19, #16- ld1 {v10.16b}, [x0]+ ldp q16, q9, [x19]
sshr v16.16b, v16.16b, #7
and v16.16b, v16.16b, v8.16b
addp v16.16b, v16.16b, v16.16b

Here is my plan:

  1. Undo the changes to these methods
  2. Merge this PR as is
  3. Finish the above-mentioned two PRs
  4. Follow-up with the libraries changes

I will keep the changes to BitArray:CopyTo though

@@ -413,18 +414,16 @@ G_M40488_IG18:
zip1 v19.16b, v18.16b, v18.16b
and v19.16b, v19.16b, v17.16b
umin v19.16b, v19.16b, v16.16b
- st1 {v19.16b}, [x3]
zip2 v18.16b, v18.16b, v18.16b
and v18.16b, v18.16b, v17.16b
umin v18.16b, v18.16b, v16.16b
- add x3, x3, #16- st1 {v18.16b}, [x3]+ stp q19, q18, [x3]
add w1, w1, #32
add w3, w1, #32
ldr w4, [x19,#16]
cmp w3, w4
bls G_M40488_IG18

@echesakov

Copy link
Copy Markdown
ContributorAuthor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

@echesakov

Copy link
Copy Markdown
ContributorAuthor

@dotnet/jit-contrib PTAL

@BruceForstallBruceForstall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@echesakov
echesakov merged commit 7814396 into dotnet:mainFeb 10, 2022
@echesakov
echesakov deleted the Arm64-ASIMD-LoadPairVector64-LoadPairVector128 branch February 10, 2022 19:51
@imhameed

Copy link
Copy Markdown
Contributor

Can someone on Mono team to sign off on the relevant changes, please?

For context: 15e56a0 was implemented by @imhameed during my initial attempt to get these changes in #52424

I'm 23 hours late to this but: the changes still look good to me (although I don't know if me signing off on my own implementation is kosher)

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-arm64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMInew-api-needs-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arm64] LoadPairVector64 and LoadPairVector128

5 participants

@echesakov@tannergooding@SamMonoRT@imhameed@BruceForstall