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
When we write
foo >> shiftit gets imported as:Notice the masking by 31. Some architectures already perform this masking so we currently try to remove it in
LowerShift:runtime/src/coreclr/jit/lower.cpp
Lines 8809 to 8828 in e583c98
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 forfoo >> (shift & 31), whereas we end up withfoo >> cse0wherecse0 = (shift & 31).