Skip to content
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

Merged
merged 4 commits into from
Mar 28, 2023

Conversation

jakobbotsch
Copy link
Member

@jakobbotsch jakobbotsch commented Mar 17, 2023

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.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 17, 2023
@ghost ghost assigned jakobbotsch Mar 17, 2023
@ghost
Copy link

ghost commented Mar 17, 2023

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

Issue Details

null

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@jakobbotsch jakobbotsch force-pushed the block-morph-commas branch 2 times, most recently from bef0cbb to 15ba192 Compare March 21, 2023 18:21
@jakobbotsch jakobbotsch changed the title JIT: Eliminate commas early in block morphing JIT: Generalize handling of commas in block morphing Mar 22, 2023
@jakobbotsch jakobbotsch marked this pull request as ready for review March 22, 2023 09:54
@jakobbotsch

This comment was marked as outdated.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@SingleAccretion SingleAccretion left a 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:

// TODO-ADDR: delete this once block morphing stops taking addresses of locals
// under COMMAs.
- pretty safe to just delete.

// 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);
- this one has somewhat broad CQ impact so may not be as easy to delete.

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.

{
printf("%s (after):\n", GetHelperName());
m_comp->gtDispTree(m_result);
m_result = m_comp->gtNewOperNode(GT_COMMA, m_result->TypeGet(), sideEffects, m_result);
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Member Author

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.

// the created commas. Therefore this function just returns a linked list of
// the side effects to be used for that purpose.
//
GenTree* MorphInitBlockHelper::EliminateCommas()
Copy link
Contributor

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?

Copy link
Member Author

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.

lhs = lhs->gtGetOp2();
}

assert(lhs->OperIsUnary() || lhs->OperIsLeaf());
Copy link
Contributor

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)?

assert(lhs->OperIsUnary() || lhs->OperIsLeaf());

GenTree* rhs = m_asg->gtGetOp2();
if (lhs->OperIsUnary() && ((lhs->gtGetOp1()->gtFlags & GTF_ALL_EFFECT) != 0) && rhs->OperIs(GT_COMMA))
Copy link
Contributor

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)

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch.

@jakobbotsch jakobbotsch marked this pull request as draft March 24, 2023 10:35
@jakobbotsch
Copy link
Member Author

jakobbotsch commented Mar 24, 2023

Updated this to address feedback. It's currently based on #83814 that will need to go in first.

  • pretty safe to just delete.

Thanks! Deleted this one.

  • this one has somewhat broad CQ impact so may not be as easy to delete.

Updated this too, overall an improvement (for win-arm64 at least) and diffs aren't that big.

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.

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.

jakobbotsch added a commit that referenced this pull request Mar 25, 2023
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.
@jakobbotsch
Copy link
Member Author

@SingleAccretion Was RewriteSIMDIndir meant to be for CQ or correctness? We can still see IND(LCL_VAR_ADDR) nodes due to forward sub, and I am hitting an assert on this in the backend -- apparently we mark the LCL_VAR_ADDR as contained and emitHandleMemOp is not prepared to handle that.

@jakobbotsch
Copy link
Member Author

I reverted the deletion of RewriteSIMDIndir, the backend needs to be taught how to handle IND<simd12>(LCL_VAR_ADDR/LCL_FLD_ADDR) with a contained address before it can be deleted. I will open an issue after this is merged.

@SingleAccretion
Copy link
Contributor

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.

@jakobbotsch jakobbotsch marked this pull request as ready for review March 27, 2023 17:49
@jakobbotsch
Copy link
Member Author

Diffs.

Can you please take another look @AndyAyersMS @SingleAccretion?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR 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.

Question/issue about GT_COMMA on rhs of GT_ASG.
3 participants