JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf
, '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

JIT: Rewrite initial parameter frame layout in terms of new ABI info - #101340

Merged
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi
May 8, 2024
Merged

JIT: Rewrite initial parameter frame layout in terms of new ABI info#101340
jakobbotsch merged 12 commits into
dotnet:mainfrom
jakobbotsch:arg-stack-offsets-new-abi

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Apr 20, 2024

Copy link
Copy Markdown
Member

Rewrite lvaAssignVirtualFrameOffsetsToArgs to make use of the ABI information that was already computed as part of ABI classification in the frontend.

No diffs are expected.

Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 20, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

Considering the stack alignment to be part of the passed stack size does
not really make sense since the callee does not own the extra bytes
added to ensure alignment.
@jakobbotsch
jakobbotsch marked this pull request as ready for review April 22, 2024 09:27
@jakobbotsch

jakobbotsch commented Apr 22, 2024

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @BruceForstall@kunalspathak

No diffs. Some minor TP improvements.

Also FYI @shushanhf @dotnet/samsung since this affects LA64/RISCV64 as well.

// Signature (int a0, int a1, int a2, struct {long} a3, ...)
// - On Windows, the Arm64 varargs ABI can split a 16 byte struct across x7 and stack
// - Arm32 generally allows structs to be split
// - LA64/RISCV64 both allow splitting of 16-byte structs across 1 register and stack

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.

For the splitting, is only the register saved on the stack within the prolog?
Should the second part of the struct which passed on caller's stack be copyed to on the prolog stack?
If don't copy the second part, how to process this part as the two parts are not stored on a continue stack space.

@jakobbotschjakobbotschApr 23, 2024

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes, for arm32/arm64 we only need to store the register part. The stack segments are always at the beginning and will be contiguous with the register segments. I thought LA64/RV64 was similar here.
@tomeksowi is enabling code in #101288 to handle it more generally. LA64 can do the same.

Out of curiosity, can you show the ABI information JITDUMP for the case with the split segments that doesn't have the stack segment first? For win-arm64 I think the split args were deliberately designed this way to make varargs possible to handle.

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.

For the old-style ABI, LA64 will copy the second part to the prolog stack where the splitting struct's size is the whole size and had allocated the whole stack space, that is, we can copy the second part directly.

I'm finding the test case, but I think/doubt the new-style can not process this case as we expected liking the old-style.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had found this case.
Late I will add this case.

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.

; V00 arg0 [V00 ] ( 1, 1 ) int -> [fp+0x54] do-not-enreg[]
; V01 arg1 [V01 ] ( 1, 1 ) struct (16) [fp+0x40] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V02 arg2 [V02 ] ( 1, 1 ) struct (16) [fp+0x30] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V03 arg3 [V03 ] ( 1, 1 ) struct (16) [fp+0x20] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
; V04 arg4 [V04 ] ( 1, 1 ) struct (16) [fp+0x10] do-not-enreg[XS] addr-exposed ld-addr-op <Point>
;# V05 OutArgs [V05 ] ( 1, 1 ) struct ( 0) [sp+0x00] do-not-enreg[XS] addr-exposed "OutgoingArgSpace"
;
; Lcl frame size = 80
DEBUG: LOONGARCH64, frameType:1
G_M40687_IG01: ;; offset=0x0000
0xff7575a760 02FE8063 addi.d sp, sp, -96
0xff7575a764 29C00061 st.d ra, sp, 0
0xff7575a768 29C02076 st.d fp, sp, 8
0xff7575a76c 02C02076 addi.d fp, sp, 8
0xff7575a770 298152C4 st.w a0, fp, 84 0xff7575a774 29C102C5 st.d a1, fp, 64 0xff7575a778 29C122C6 st.d a2, fp, 72 0xff7575a77c 29C0C2C7 st.d a3, fp, 48 0xff7575a780 29C0E2C8 st.d a4, fp, 56 0xff7575a784 29C082C9 st.d a5, fp, 32 0xff7575a788 29C0A2CA st.d a6, fp, 40 0xff7575a78c 29C042CB st.d a7, fp, 16 0xff7575a790 28C1806C ld.d t0, sp, 96 // the old-style ABI will copy, but now the new stype not.
0xff7575a794 29C062CC st.d t0, fp, 24 // the old-style ABI will copy, but now the new stype not. 

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.

OK.
Maybe it's better to split to some PRs before 101288 if there are much modification.

@tomeksowitomeksowiApr 24, 2024

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'm a bit apprehensive about merging a PR which breaks everything with split struct args. Maybe I'll handle split args in #101288 and then LA can enable the #ifdefs as well? I don't think there will be that much modification but I don't have a solution fully fleshed out yet.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Do you mean this PR? I don't think this PR will affect any behavior for either LA64/RISCV64. The only break right now came from #101224.

The original code computes the split stack parameters at similar offsets as this PR does for both LA64/RISCV64:

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (varDsc->lvIsSplit)
{
assert((varDsc->lvType == TYP_STRUCT) && (varDsc->GetOtherArgReg() == REG_STK));
// This is a split struct. It will account for an extra (8 bytes) for the whole struct.
varDsc->SetStackOffset(varDsc->GetStackOffset() + TARGET_POINTER_SIZE);
argOffs += TARGET_POINTER_SIZE;
}
#else// TARGET*

(In fact, this was one of the primary reasons I thought LA64/RV64 already worked this way for split parameters -- but the stack offset set there is never used.)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

It's possible I misunderstood what that code there is doing. Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

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.

It's possible I misunderstood what that code there is doing.

I think I didn't express clearly to make you understand.

Regardless, I don't think there is an issue with this PR since the offset this PR might be assigning to split parameters are getting overwritten regardless.

Yes, what I feedback is not about this PR and I don't think LA64/RV64's splitting error is about this PR.
We just discussed here with you.
You can proceed this PR with your plan.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @kunalspathak -- can you please take a look?

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@jakobbotsch
jakobbotsch merged commit 562457f into dotnet:mainMay 8, 2024
@jakobbotsch
jakobbotsch deleted the arg-stack-offsets-new-abi branch May 8, 2024 08:22
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
…otnet#101340)
Rewrite `lvaAssignVirtualFrameOffsetsToArgs` to make use of the ABI
information that was already computed as part of ABI classification in
the frontend.
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 7, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@jakobbotsch@tomeksowi@kunalspathak@shushanhf