JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

@AndyAyersMS@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

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

JIT: import entire method for OSR, prune unneeded parts later - #83910

Merged
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783
Mar 26, 2023
Merged

JIT: import entire method for OSR, prune unneeded parts later#83910
AndyAyersMS merged 3 commits into
dotnet:mainfrom
AndyAyersMS:Fix83783

Conversation

@AndyAyersMS

Copy link
Copy Markdown
Member

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes#83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

For OSR compiles, always import from the original entry point in addtion
to the OSR entry point. This gives the OSR compiler a chance
to see all of the method and so properly compute address exposure,
instead of relying on the Tier0
analysis.
Once address exposure has been determined, revoke special protection
for the original entry and try and prune away blocks that are no longer
needed.
Fixesdotnet#83783.
May also fix some of the cases where OSR perf is lagging (though
don't expect this to fix them all).
@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 24, 2023
@ghost

Copy link
Copy Markdown

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

Issue Details

For OSR compiles, always import from the original entry point in addtion to the OSR entry point. This gives the OSR compiler a chance to see all of the method and so properly compute address exposure, instead of relying on the Tier0
analysis.

Once address exposure has been determined, revoke special protection for the original entry and try and prune away blocks that are no longer needed.

Fixes #83783.

May also fix some of the cases where OSR perf is lagging (though don't expect this to fix them all).

Author:AndyAyersMS
Assignees:-
Labels:

area-CodeGen-coreclr

Milestone:-

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

FYI @jakobbotsch
cc @dotnet/jit-contrib

There are several ways to approach this -- in this version the original entry is unreachable, but we force it to stay around; alternatively, we could make the OSR entry unreachable and force it to stay around, and then swap entry points later.

This one is a bit less disruptive; if it pans out I can also reconcile it with the code where in OSR mode we forcibly import the original entry if we think the method might tail call (and which is why I know this approach will "work", since we already do this extra importation some of the time). For tail call cases we keep the original entry protected until after morph, so a bit later than what we do here. The protection mechanisms are different, so the tail call version still works.

This will be difficult to assess via SPMI as many OSR contexts will fail to replay. But some of them do and the diffs generally look encouraging.

It will also hurt OSR TP but again this may be hard to spot in SPMI. In actuality OSR compiles are pretty rare so I'm not that worried about the extra work.

A third option is to just compile the method normally and then once we're past morph say, rework the control flow to jump to the OSR entry from scratch. That would be more work because I'd have to revise the whole "OSR step block" scheme so that it could run later, in case the OSR entry happens to be in the middle of a bunch of try regions.

Much of what happens before morph is currently flow insensitive, so it doesn't matter that a big swath of blocks are unreachable. It might mess up early liveness, but if so we already have this problem in methods that might tail call.

This may fix some latent OSR perf issues, but I don't expect it to fix them all.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Hmm, looks like a fairly persistent assert.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Problem is that once you set BBF_DONT_REMOVE it is hard to safely un-set it. So I will just revise and use the existing artificial ref count solution. This will keep the extra IR and blocks around a bit longer but be simpler overall.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-jit-experimental

@azure-pipelines

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

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Test failures seem unrelated. Passed jit-experimental which has various forms of OSR stress.

@AndyAyersMS
AndyAyersMS marked this pull request as ready for review March 25, 2023 14:57

@jakobbotschjakobbotsch left a comment

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.

LGTM! I thought this would be a much more involved change

varDsc->lvIsOSRLocal = true;

if (info.compPatchpointInfo->IsExposed(lclNum))
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we still need to communicate the exposure information in the patchpoint information?

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.

No. However, I'll leave this as is for now so older jits can still do somewhat reasonable things with newer SPMI data.

@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

LGTM! I thought this would be a much more involved change

Luckily (I guess) we already had this capability for some OSR methods, so now we just use it for all of them.

@AndyAyersMS
AndyAyersMS merged commit f1f9fde into dotnet:mainMar 26, 2023
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Mar 27, 2023
When I changed the importation strategy for OSR in dotnet#83910 it
exposed a latent issue -- small OSR locals must normalized on load.
Fixesdotnet#83959.
AndyAyersMS added a commit that referenced this pull request Mar 28, 2023
When I changed the importation strategy for OSR in #83910 it
exposed a latent issue -- small OSR locals must normalized on load if
they were exposed at Tier0.
Fixes#83959.
Fixes#83960.
@AndyAyersMSAndyAyersMS mentioned this pull request Mar 30, 2023
72 tasks
@AndyAyersMS

Copy link
Copy Markdown
MemberAuthor

Also seeing a regression here (not (yet) autofiled): ubuntu x64

newplot - 2023-03-30T124748 849

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.

JIT: OSR is not conservative enough about exposing struct locals

2 participants

@AndyAyersMS@jakobbotsch