-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JIT: Generalize handling of commas in block morphing #83590
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue Detailsnull
|
bef0cbb
to
15ba192
Compare
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also have workarounds in place that can be deleted:
runtime/src/coreclr/jit/rationalize.cpp
Lines 72 to 73 in 6bcd4aa
// TODO-ADDR: delete this once block morphing stops taking addresses of locals | |
// under COMMAs. |
runtime/src/coreclr/jit/fginline.cpp
Lines 396 to 402 in 6bcd4aa
// Block morphing does not support (promoted) locals under commas, as such, instead of "COMMA(asg, lcl)" we | |
// do "OBJ(COMMA(asg, ADDR(LCL)))". TODO-1stClassStructs: improve block morphing and delete this workaround. | |
// | |
GenTree* lcl = m_compiler->gtNewLclvNode(lclNum, varDsc->TypeGet()); | |
GenTree* addr = m_compiler->gtNewOperNode(GT_ADDR, TYP_I_IMPL, lcl); | |
addr = m_compiler->gtNewOperNode(GT_COMMA, addr->TypeGet(), asg, addr); | |
GenTree* obj = m_compiler->gtNewObjNode(varDsc->GetLayout(), addr); |
Additionally, gtNewTempAssign
calls impAssignStruct
which tries to sink commas, which is then worked around in CSE and return merging. Notionally, it would be possible to get rid of the sinking.
Finally, this fixes #1699.
src/coreclr/jit/morphblock.cpp
Outdated
{ | ||
printf("%s (after):\n", GetHelperName()); | ||
m_comp->gtDispTree(m_result); | ||
m_result = m_comp->gtNewOperNode(GT_COMMA, m_result->TypeGet(), sideEffects, m_result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit unfortunate to recreate the comma nodes. I am assuming the memory consumption impact is negligible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did spend a while trying to avoid it, but it was significantly uglier to reuse the commas. Based on the throughput I think the case is very rare but let me double check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up reusing the commas by returning a pool of the freed ones from EliminateCommas
, also linked via their gtNext
fields. I couldn't find a more elegant way of doing this.
src/coreclr/jit/morphblock.cpp
Outdated
// the created commas. Therefore this function just returns a linked list of | ||
// the side effects to be used for that purpose. | ||
// | ||
GenTree* MorphInitBlockHelper::EliminateCommas() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the assignment was reversed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I need to handle that.
src/coreclr/jit/morphblock.cpp
Outdated
lhs = lhs->gtGetOp2(); | ||
} | ||
|
||
assert(lhs->OperIsUnary() || lhs->OperIsLeaf()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OperIsUnary
Why not OperIsIndir
(also below)?
src/coreclr/jit/morphblock.cpp
Outdated
assert(lhs->OperIsUnary() || lhs->OperIsLeaf()); | ||
|
||
GenTree* rhs = m_asg->gtGetOp2(); | ||
if (lhs->OperIsUnary() && ((lhs->gtGetOp1()->gtFlags & GTF_ALL_EFFECT) != 0) && rhs->OperIs(GT_COMMA)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not look like the case of RHS comma containing an assignment that affects locals on the LHS is handled:
V00 = oldAddr
// *(oldAddr + 4) = *(newAddr + 4)
ASG
IND(V00 + 4)
COMMA
ASG(V00 = newAddr)
IND(V00 + 4)
=>
// *(newAddr + 4) = *(newAddr + 4)
COMMA
ASG(V00 = newAddr)
ASG
IND(V00 + 4)
IND(V00 + 4)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
Updated this to address feedback. It's currently based on #83814 that will need to go in first.
Thanks! Deleted this one.
Updated this too, overall an improvement (for win-arm64 at least) and diffs aren't that big.
I will leave this as-is for now, the function has some recursive handling right now and it probably would need to be restructured a bit. |
Avoid creating commas that are on the LHS of an assignment or below an ADDR node. These primarily were created by morph which has an IND(COMMA(x, y)) -> COMMA(x, IND(y)) transformation that did not pay attention to whether it was on the left of an assignment. The IR shape is pretty odd; the RHS of these commas are not actually evaluated in the traditional sense, but happen as part of the parent ASG, so the semantics of the construct ends up being confusing. Additionally it complicates #83590.
Eliminate commas early in block morphing, before the rest of the transformation needs to look at it. Do this by extracting their side effects and adding them on top of the returned result instead. This allows us to handle arbitrary COMMAs on destination operand in a general manner. Prerequisite to dotnet#83388. Fix dotnet#1699.
659732b
to
4512bf1
Compare
@SingleAccretion Was |
I reverted the deletion of |
It was meant to be for CQ only (at this point anyway, in the past it was also needed for correctness). Unfortunate that a bug has snuck in the meantime. |
Can you please take another look @AndyAyersMS @SingleAccretion? |
Eliminate commas early in block morphing, before the rest of the transformation
needs to look at it. Do this by extracting their side effects and adding
them on top of the returned result instead. This allows us to handle
arbitrary COMMAs on destination operand in a general manner.
Prerequisite to #83388.
Fix #1699.