Skip to content

JIT: Strip out masking of shiftAmount way earlier when possible #126799

@BoyBaykiller

Description

@BoyBaykiller

When we write foo >> shift it gets imported as:

\--*  RSZ       int   
   +--*  LCL_VAR   int    V01 arg1   
   \--*  AND       int   
      +--*  LCL_VAR   int    V02 arg2
      \--*  CNS_INT   int    31

Notice the masking by 31. Some architectures already perform this masking so we currently try to remove it in LowerShift:

for (GenTree* andOp = shift->gtGetOp2(); andOp->OperIs(GT_AND); andOp = andOp->gtGetOp1())
{
GenTree* maskOp = andOp->gtGetOp2();
if (!maskOp->IsCnsIntOrI())
{
break;
}
if ((static_cast<size_t>(maskOp->AsIntCon()->IconValue()) & mask) != mask)
{
break;
}
shift->gtOp2 = andOp->gtGetOp1();
BlockRange().Remove(andOp);
BlockRange().Remove(maskOp);
// The parent was replaced, clear contain and regOpt flag.
shift->gtOp2->ClearContained();
}

Removing the mask way earlier like in import could save some tp and also handle more cases.
For example here the (shift & 31) got CSEd which causes the aforementioned opt to no longer recognize it, because its literally looking for foo >> (shift & 31), whereas we end up with foo >> cse0 where cse0 = (shift & 31).

uint ShiftAndCSE(uint foo, int shift)
{
    uint res = (foo >> shift);
    res <<= shift;

    return res;
}
G_M46394_IG02:  ;; offset=0x0000
       and      r8d, 31 ; <- currently not removed
       shrx     eax, edx, r8d
       shlx     eax, eax, r8d

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIuntriagedNew issue has not been triaged by the area owner

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions