-
Notifications
You must be signed in to change notification settings - Fork 5.3k
JIT: Improve constant folding for commutative operators #656
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
Conversation
sandreenko
left a comment
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.
The idea looks good, I have a few questions about the pre-existing logic here, that could lead to new errors if you apply it more broadly.
Why did you decide to delete the tests?
src/coreclr/src/jit/morph.cpp
Outdated
| { | ||
| // Don't create a byref pointer that may point outside of the ref object. | ||
| // If a GC happens, the byref won't get updated. This can happen if one | ||
| // of the int components is negative. It also requires the address generation |
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 also requires the address generation be in a fully-interruptible code region.
That comment looks incorrect, at least I do not see where we check that a fully-interruptible code region condition.
It is also not clear for me in which case that optimization for varTypeIsGC is incorrect, could somebody explain that to me please?
|
@sandreenko thanks for feedback, will try to address it soon, sorry for the delay. |
|
@sandreenko could you please re-review? thanks |
sandreenko
left a comment
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.
Thanks for the update, @EgorBo.
The checks for each case are not obvious, could you please explain them to me?
| // If a GC happens, the byref won't get updated. This can happen if one | ||
| // of the int components is negative. It also requires the address generation | ||
| // be in a fully-interruptible code region. | ||
| if (!varTypeIsGC(op1->AsOp()->gtGetOp1()->TypeGet()) && !varTypeIsGC(op2->AsOp()->gtGetOp1()->TypeGet())) |
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.
here you check varTypeIsGC(x), varTypeIsGC(y), gtIsActiveCSE_Candidate(op2).
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.
Added also gtIsActiveCSE_Candidate(op1) here
| if (op2->IsCnsIntOrI() && varTypeIsIntegralOrI(tree->TypeGet())) | ||
| { | ||
| // Fold "((x <op> icon1) <op> icon2) to (x <op> (icon1 <op> icon2))" | ||
| if (op1->OperIs(oper) && !gtIsActiveCSE_Candidate(op1) && op1->AsOp()->gtGetOp2()->IsCnsIntOrI() && |
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.
here you check varTypeIsGC(icon1)? why does it need that check? Why don't you need to check x here as you do in the previous case?
You check gtIsActiveCSE_Candidate(op1), in the previous case you were checking gtIsActiveCSE_Candidate(op2), what is the difference?
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.
removed varTypeIsGC(icon1) and added gtIsActiveCSE_Candidate(op1) to the first expression
| const ssize_t icon1 = cns1->IconValue(); | ||
| const ssize_t icon2 = cns2->IconValue(); | ||
|
|
||
| if (oper == GT_ADD) |
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.
that code duplication doesn't look cool, but a function with 6 arguments GenTreeIntConCommon* fgGetCommutativeResult(oper, icon1, icon2, tree, op1, optional op2) also doesn't. I am not sure here.
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.
Neither am I, tried to simplify it a bit. Let me know if I should extract it to a separate method.
|
Please take a look at the new test failures after the last change that I have not seen before, like x86 windows: |
|
@EgorBo, still working on this? Thanks. |
|
@EgorBo, seems like you're not working on this anymore. Shall we close it? |
|
Sorry, will re-open it later with proper fixes 🙁 |
Moved from dotnet/coreclr: dotnet/coreclr#27325
This PR re-uses existing
GT_ADDconstant folding logic for other commutative operators, e.g.:Diff for the snippet above: https://www.diffchecker.com/1Us280l1
Jit-utills Diff: https://gist.github.com/EgorBo/1238cbde8226194c554b4de83a900609
cc @dotnet/jit-contrib