Skip to content

JIT: Transform '(cmp & x) | (cmp & y)' to 'cmp & (x | y)'#126070

Draft
BoyBaykiller wants to merge 2 commits intodotnet:mainfrom
BoyBaykiller:transform-double-and-or
Draft

JIT: Transform '(cmp & x) | (cmp & y)' to 'cmp & (x | y)'#126070
BoyBaykiller wants to merge 2 commits intodotnet:mainfrom
BoyBaykiller:transform-double-and-or

Conversation

@BoyBaykiller
Copy link
Contributor

No description provided.

@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 Mar 25, 2026
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Mar 25, 2026
@dotnet-policy-service
Copy link
Contributor

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

@BoyBaykiller
Copy link
Contributor Author

I am having a problem identifying certain cases.
Currently I detect such IR:

[000007] -----------                            \--*  OR        int   
[000003] -----------                               +--*  AND       int   
[000001] -----------                               |  +--*  LCL_VAR   int    V02 arg2         
[000002] -----------                               |  \--*  CNS_INT   int    256
[000006] -----------                               \--*  AND       int   
[000004] -----------                                  +--*  LCL_VAR   int    V02 arg2          (last use)
[000005] -----------                                  \--*  CNS_INT   int    512

Which works fine for (flags & 256) | (flags & 512),
but breaks down if I add a operation in front like 1 + (flags & 256) | (flags & 512). Then the IR is:

[000008] -----------                         \--*  OR        int   
[000004] -----------                            +--*  ADD       int   
[000000] -----------                            |  +--*  CNS_INT   int    1
[000003] -----------                            |  \--*  AND       int   
[000001] -----------                            |     +--*  LCL_VAR   int    V01 arg1         
[000002] -----------                            |     \--*  CNS_INT   int    256
[000007] -----------                            \--*  AND       int   
[000005] -----------                               +--*  LCL_VAR   int    V01 arg1         
[000006] -----------                               \--*  CNS_INT   int    512

When adding explicit parentheses like 1 + ((flags & 256) | (flags & 512)) it works again:

[000008] -----------                         \--*  ADD       int   
[000000] -----------                            +--*  CNS_INT   int    1
[000007] -----------                            \--*  OR        int   
[000003] -----------                               +--*  AND       int   
[000001] -----------                               |  +--*  LCL_VAR   int    V01 arg1         
[000002] -----------                               |  \--*  CNS_INT   int    256
[000006] -----------                               \--*  AND       int   
[000004] -----------                                  +--*  LCL_VAR   int    V01 arg1         
[000005] -----------                                  \--*  CNS_INT   int    512

But this shouldn't be needed. It shouldnt get confused by some extra commutative arithmetic like the ADD(1) here. What is the general way to fix this?

@huoyaoyuan
Copy link
Member

but breaks down if I add a operation in front like 1 + (flags & 256) | (flags & 512). Then the IR is:

The operator priority of | is lower than +. 1 + (flags & 256) | (flags & 512) means (1 + (flags & 256)) | (flags & 512). Check sharplab.

// Fold "(cmp & x) | (cmp & y)" to "cmp & (x | y)".
if (varTypeIsIntegralOrI(orOp) && op1->OperIs(GT_AND) && op2->OperIs(GT_AND))
{
if (GenTree::Compare(op1->gtGetOp1(), op2->gtGetOp1()))
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is legal - cmp may have side-effect or be a local whose value is changed via x or y

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