Skip to content

JIT: Move all OperIsConst() to right-side for comparisons (including missing EQ, NE)#127616

Closed
BoyBaykiller wants to merge 2 commits intodotnet:mainfrom
BoyBaykiller:EQ-NE-canonicalization-v2
Closed

JIT: Move all OperIsConst() to right-side for comparisons (including missing EQ, NE)#127616
BoyBaykiller wants to merge 2 commits intodotnet:mainfrom
BoyBaykiller:EQ-NE-canonicalization-v2

Conversation

@BoyBaykiller
Copy link
Copy Markdown
Contributor

@BoyBaykiller BoyBaykiller commented Apr 30, 2026

When turning 'CNS relop op2' into 'CNS relop* op2' we previously only allowed IsIntegralConst.
Also EQ, NE where not canonicalized at all.

@BoyBaykiller
Copy link
Copy Markdown
Contributor Author

@EgorBo

@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 30, 2026
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Apr 30, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

Comment thread src/coreclr/jit/morph.cpp Outdated
case GT_EQ:
case GT_NE:
// Change "CNS relop op2" to "op2 relop* CNS"
if (op1->IsIntegralConst() && tree->OperIsCompare() && gtCanSwapOrder(op1, op2))
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.

There is no need to restrict this to IsIntegralConst (same for GE/GT/LE/LT below) and no need to check OperIsCompare either, it's always true for these cases.

We may want to assert OperIsCompare to ensure no accidental codeflow is occurring from future refactorings, but that's optional.

For EQ/NE as well, there's no need to do SwapRelop as there is no change for EQ/NE, again a case that can be asserted but the general helper is for simplicity when the paths are all shared (which isn't trivial to share here)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I know but:

I just copy-pasted the code from GT_LT, GT_LE, GT_GE, GT_GT because plan is to refactor/unify this anyway.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But ok let me change it

Copy link
Copy Markdown
Member

@tannergooding tannergooding Apr 30, 2026

Choose a reason for hiding this comment

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

There's a difference between doing a big refactoring and doing a small contained improvement consistently.

The other change I had an issue with because it was starting to mix many different fixes and codegen improvements together as well as also mixing in a refactoring as part of that.

This one, however, is propagating a clear issue and so it's not really even fulfilling what the description is advertising.

We still have a small 10-15 line PR doing this "properly" where we fix all of EQ/NE/GT/GE/LT/LE to "canonicalize" for all cases where its valid by pushing constants to the right. It is then just a single logically contained fix for relop nodes.

@BoyBaykiller BoyBaykiller changed the title JIT: Canonicalize cns to right side for EQ, NE JIT: Move all OperIsConst() to right-side for comparisons (including missing EQ, NE) Apr 30, 2026
* specialize handling for NE, EQ
@BoyBaykiller BoyBaykiller force-pushed the EQ-NE-canonicalization-v2 branch from e62323e to 6864a7e Compare April 30, 2026 18:55
@EgorBo
Copy link
Copy Markdown
Member

EgorBo commented Apr 30, 2026

Sorry, but I don't understand the intent. I thought we agreed to make it generic for all commutative node, why do we still just copy-paste existing logic?

I think we should just handle it in both pre- and post- order before we enter the global switch, we just check if the oper is commutative and check the CanSwap and do it. thus we can also delete a few existing ad-hoc rotations.

@BoyBaykiller
Copy link
Copy Markdown
Contributor Author

Lol. The bikeshedding is real. If someone wants to take over please feel free. I think we all want the same thing in the end, but waste time on how and which way it should be split into PRs or whatever.

@EgorBo
Copy link
Copy Markdown
Member

EgorBo commented Apr 30, 2026

Here is the change that I proposed: https://github.com/dotnet/runtime/compare/main...EgorBo:runtime-1:swap-cns?expand=1 (although, probably needs a separate function vs lambda)

I assume with this change we can delete a couple of other "move cns to the right" here and there - haven't checked. No copy-paste

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants