Skip to content

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

@EgorBo@stephentoub@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Handle side-effects in impBoxPatternMatch by EgorBo · Pull Request #90496 · dotnet/runtime · GitHub
Skip to content

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

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

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

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

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

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

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

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

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

@EgorBo@stephentoub@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Handle side-effects in impBoxPatternMatch by EgorBo · Pull Request #90496 · dotnet/runtime · GitHub
Skip to content

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

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

Handle side-effects in impBoxPatternMatch - #90496

Merged
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch
Aug 14, 2023
Merged

Handle side-effects in impBoxPatternMatch#90496
EgorBo merged 8 commits into
dotnet:mainfrom
EgorBo:handle-sideeffects-in-impBoxPatternMatch

Conversation

@EgorBo

@EgorBoEgorBo commented Aug 13, 2023

Copy link
Copy Markdown
Member

Closes#90492
Contributes to #9120

The main motivation is to get rid of [MethodImpl(MethodImplOptions.AggressiveOptimization)] from AsyncTaskMethodBuilderT.cs it was placed there to avoid unnecessary allocation Tier0 used to produce while Tier-FullOpts did not. New tier0 codegen for that method:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 13, 2023
@ghostghost assigned EgorBoAug 13, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

Closes #90492

The changes are not big if you ignore white-spaces in code-review tab

Author:EgorBo
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@stephentoub

Copy link
Copy Markdown
Member

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
?

@EgorBo

EgorBo commented Aug 13, 2023

Copy link
Copy Markdown
MemberAuthor

can we also delete

[MethodImpl(MethodImplOptions.AggressiveOptimization)]// workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120

?

so there is still one allocation I can't yet eliminate

Looks like it can be removed, Tier0 codegen:

; Assembly listing for method System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.Threading.Tasks.VoidTaskResult]:AwaitUnsafeOnCompleted[System.Runtime.CompilerServices.TaskAwaiter](byref,System.Runtime.CompilerServices.IAsyncStateMachineBox) (Tier0)G_M46438_IG01: ;; offset=0x0000pushrbpsubrsp,80learbp,[rsp+0x50] vxorps xmm4,xmm4,xmm4 vmovdqa xmmword ptr [rbp-0x30],xmm4 vmovdqa xmmword ptr [rbp-0x20],xmm4 vmovdqa xmmword ptr [rbp-0x10],xmm4mov bword ptr [rbp+0x10],rcxmov gword ptr [rbp+0x18],rdx ;; size=37 bbWeight=1 PerfScore 10.08G_M46438_IG02: ;; offset=0x0025xorecx,ecxmov gword ptr [rbp-0x08],rcxmovrcx, bword ptr [rbp+0x10]movrcx, gword ptr [rcx]mov gword ptr [rbp-0x30],rcxmovrcx, bword ptr [rbp+0x10]mov bword ptr [rbp-0x10],rcxmovrcx, bword ptr [rbp-0x10]movrcx, gword ptr [rcx]movrdx, gword ptr [rbp+0x18]movr8d,1call[System.Runtime.CompilerServices.TaskAwaiter:UnsafeOnCompletedInternal(System.Threading.Tasks.Task,System.Runtime.CompilerServices.IAsyncStateMachineBox,bool)]nop ;; size=49 bbWeight=1 PerfScore 14.75G_M46438_IG03: ;; offset=0x0056addrsp,80poprbpret ;; size=6 bbWeight=1 PerfScore 1.75; Total bytes of code 92

Previous Tier0 codegen: https://gist.github.com/EgorBo/7da915602c4d826e0e7d0d981aafc08d

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot --tier0

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@MihuBot

@EgorBo

EgorBo commented Aug 14, 2023

Copy link
Copy Markdown
MemberAuthor

@jakobbotsch @dotnet/jit-contrib PTAL, I recommend disabling "whitespaces" for review.

impBoxPatternMatch used to be conservative about side-effects, now I spill them as separate statements.
Diffs aren't big but at least I was able to remove AggressiveOpt.

impResolveToken(codeAddr + 1, &isInstResolvedToken, CORINFO_TOKENKIND_Casting);
}
else if ((foldAsHelper == CORINFO_HELP_BOX_NULLABLE) &&
((impStackTop().val->gtFlags & GTF_SIDE_EFFECT) == 0))

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Didn't do it for nullable due to empty diffs for it (would have to add tests as the logic is a bit different).

Comment threadsrc/coreclr/jit/importer.cpp Outdated
Comment on lines 2875 to 2879
GenTree* op = impPopStack().val;
if ((op->gtFlags & GTF_SIDE_EFFECT) != 0)
{
JITDUMP("\n Importing BOX; BR_TRUE/FALSE as %sconstant\n",
treeToNullcheck == nullptr ? "" : "nullcheck+");
impPopStack();

GenTree* result = gtNewIconNode(1);

if (treeToNullcheck != nullptr)
{
GenTree* nullcheck = gtNewNullCheck(treeToNullcheck, compCurBB);
result = gtNewOperNode(GT_COMMA, TYP_INT, nullcheck, result);
}

impPushOnStack(result, typeInfo(TYP_INT));
return 0;
impStoreTemp(lvaGrabTemp(true DEBUGARG("spill side effects")), op, CHECK_SPILL_ALL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a bit of an unusual way of doing this in the importer, use impSpillSideEffect instead?

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

@EgorBoEgorBoAug 14, 2023

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, thanks for the hint. addressed.

Also we already do this from the caller for BoxPatterns::IsByRefLike. Should it be unified?

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it. Presumably the byref case is rare so it's ok to call it twice for simplicity?

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.

Looks like that one has to be always done regardless wether we match a pattern or not while here we only do this when we match it.

I don't think so (note that the comment is misleading -- we BADCODE today on unmatched patterns, we do not generate code to throw InvalidProgramException at runtime). But I'm ok with leaving it to avoid further risk and potentially cleaning it up in .NET 9, assuming you want this in .NET 8.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I see, yeah let's clean it up in .NET 9.0, it has a potential to slightly refactor the whole thing

Comment threadsrc/coreclr/jit/importer.cpp Outdated
impPushOnStack(result, typeInfo(TYP_INT));
return 0;
}
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("spilling side-effects"));

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.

Did you check diffs for this? I'm not sure we want to spill all side effects, it should be enough to spill the top one (and the slots it interferes with). I also don't think we need to pass true. Not sure if there is any significant difference given the side-effecting trees we would expect at the top of the stack here, though.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Diffs - I've also checked that all side-effects are preserved in my tests

@EgorBo
EgorBo merged commit 8323e58 into dotnet:mainAug 14, 2023
@EgorBo
EgorBo deleted the handle-sideeffects-in-impBoxPatternMatch branch August 14, 2023 14:50
@ghostghost locked as resolved and limited conversation to collaborators Sep 15, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allocation for a simple isinst pattern in Tier0

3 participants

@EgorBo@stephentoub@jakobbotsch