Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas
, '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

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag - #64863

Closed
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition
Closed

Remove condition that forbids promotion of HFAs with CUSTOMLAYOUT flag#64863
echesakov wants to merge 10 commits into
dotnet:mainfrom
echesakov:Remove-CustomLayout-HFA-Condition

Conversation

@echesakov

@echesakovechesakov commented Feb 6, 2022

Copy link
Copy Markdown
Contributor

We have logic that checks if the layout is valid

@ghostghost assigned echesakovFeb 6, 2022
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Feb 6, 2022
@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

Presumably, we have logic that checks if the layout is valid

Author:echesakovMSFT
Assignees:echesakovMSFT
Labels:

area-CodeGen-coreclr

Milestone:-

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/coreclr/jit/lclvars.cpp Outdated

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.

Would it make sense to delete or replace the other use StructHasCustomLayout as well?

The CORINFO_FLG_CUSTOMLAYOUT flag on JIT/EE interface has always been very poorly defined. It would be nice to get rid of it, and replace it with well-defined type property or type properties as necessary.

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 it does. The only other user of StructHasCustomLayout is

if (StructHasCustomLayout(typeFlags) && ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) == 0))
and based on the comment above the intent was to recognize structs with StructLayout(LayoutKind.Explicit, Size=...). However, in my local testing I found that structs marked with StructLayout(LayoutKind.Auto) also returns true for StructHasCustomLayout (e.g. ValueTuple).

Let me do more debugging here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I've been looking at the this and it seems that the original intent for StructHasCustomLayout was to identify LayoutKind.Explicit and prevent such structures from promoting (i.e. enregistering their fields).

I believe this is done to be able to properly copy such structs with explicitlayout attribute (incl. gaps between fields).

However, the way this is implemented in VM has interesting consequences.

For example, suppose we have

usingSystem;usingSystem.Runtime.CompilerServices;usingSystem.Runtime.InteropServices;namespaceRuntime_64863{classProgram{structDefLayout{ulongx0;uintw1;}[StructLayout(LayoutKind.Auto)]structAutoLayout{ulongx0;uintw1;}[MethodImpl(MethodImplOptions.NoInlining)]staticAutoLayoutRetAutoLayout()=>default(AutoLayout);[MethodImpl(MethodImplOptions.NoInlining)]staticDefLayoutRetDefLayout()=>default(DefLayout);staticvoidMain(string[]args){RetAutoLayout();RetDefLayout();}}}

On Arm64 DefLayout return type would be promotable

; Assembly listing for method Runtime_64863.Program:RetDefLayout():DefLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) long -> x0 single-def V00.x0(offs=0x00) P-INDEP "field V00.x0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) int -> x1 single-def V00.w1(offs=0x08) P-INDEP "field V00.w1 (fldOffset=0x8)";; Lcl frame size = 0G_M26462_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M26462_IG02: ;; offset=0008H AA1F03E0 mov x0, xzr 2A1F03E1 mov w1, wzr ;; bbWeight=1 PerfScore 1.00G_M26462_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

while AutoLayout return type would not:

; Assembly listing for method Runtime_64863.Program:RetAutoLayout():AutoLayout; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;; V00 loc0 [V00,T00] ( 2, 2 ) struct (16) [fp+10H] do-not-enreg[SR] multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace";; Lcl frame size = 16G_M39902_IG01: ;; offset=0000H A9BE7BFD stp fp, lr,[sp,#-32]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M39902_IG02: ;; offset=0008H 4E040FF0 dup v16.4s, wzr 3D8007B0 str q16,[fp,#16] // [V00 loc0] F9400BA0 ldr x0,[fp,#16] // [V00 loc0] F9400FA1 ldr x1,[fp,#24] // [V00 loc0+0x08] ;; bbWeight=1 PerfScore 7.00G_M39902_IG03: ;; offset=0018H A8C27BFD ldp fp, lr,[sp],#32 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

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.

Maybe, I misunderstand what ECMA-335 says but isn't [StructLayout(LayoutKind.Auto)] implied by default?

Wrt ECMA-335, there is always a StructLayout value written in metadata. This value is not optional.

The C# default for this value is StructLayout.Sequential for structs. So C# writes StructLayout.Sequential into metadata by default, unless it gets overridden by StructLayout attribute.

However, the way this is implemented in VM has interesting consequences.

Feel free to adjust the VM and JIT contract as needed. The existing CUSTOMLAYOUT flag is not very well defined. It would be great if we get something that well defined and easy to understand.

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.

Thanks for the explanation. I guess I confused the default value per ECMA

A class marked autolayout indicates that the loader is free to lay out the
class in any way it sees fit; any layout information that might have been specified is
ignored. This is the default.

and what C# and other compilers specify https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.layoutkind?view=net-6.0.

To reduce layout-related problems associated with the Auto value, C#, Visual Basic, and C++ compilers specify Sequential layout for value types.

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.

FWIW, the JIT primarily checks for combination of lvContainsHoles && lvCustomLayout in the code - looks that the intent was to check "a value type is not tightly packed and the "holes" are due to the layout being explicit". The assumption is that the "holes" can contain some information? If the "holes" are due to padding then the JIT can discard the information (as in DefLayout case in my example).

Looking at another example

structDefLayout2{uintw0;ulongx1;}

this seems to be the case

; Assembly listing for method Runtime_64863.Program:RetDefLayout2():DefLayout2; Emitting BLENDED_CODE for generic ARM64 CPU - Windows; optimized code; fp based frame; partially interruptible; No PGO data; Final local variable assignments;;* V00 loc0 [V00 ] ( 0, 0 ) struct (16) zero-ref multireg-ret ld-addr-op;# V01 OutArgs [V01 ] ( 1, 1 ) lclBlk ( 0) [sp+00H] "OutgoingArgSpace"; V02 tmp1 [V02,T00] ( 2, 2 ) int -> x0 single-def V00.w0(offs=0x00) P-INDEP "field V00.w0 (fldOffset=0x0)"; V03 tmp2 [V03,T01] ( 2, 2 ) long -> x1 single-def V00.x1(offs=0x08) P-INDEP "field V00.x1 (fldOffset=0x8)";; Lcl frame size = 0G_M35870_IG01: ;; offset=0000H A9BF7BFD stp fp, lr,[sp,#-16]! 910003FD mov fp,sp ;; bbWeight=1 PerfScore 1.50G_M35870_IG02: ;; offset=0008H 2A1F03E0 mov w0, wzr AA1F03E1 mov x1, xzr ;; bbWeight=1 PerfScore 1.00G_M35870_IG03: ;; offset=0010H A8C17BFD ldp fp, lr,[sp],#16 D65F03C0 ret lr ;; bbWeight=1 PerfScore 2.00; Total bytes of code 24, prolog size 8, PerfScore 6.90, instruction count 6, allocated bytes for code 24 (MethodHash=fc8373e1) for method Runtime_64863.Program:RetDefLayout2():DefLayout2; ============================================================

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from b2f355f to 678bc17CompareMarch 2, 2022 00:19
@echesakov
echesakovforce-pushed the Remove-CustomLayout-HFA-Condition branch from 678bc17 to 71334fdCompareMarch 14, 2022 20:57
@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@echesakov

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@ghost

Copy link
Copy Markdown

This pull request has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

@ghost

Copy link
Copy Markdown

This pull request will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days.

@ghostghost closed this Apr 30, 2022
@ghostghost locked as resolved and limited conversation to collaborators May 30, 2022
This pull request was closed.
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 SuperPMIno-recent-activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@echesakov@jkotas