-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Given the following code:
public static int M1(int y)
{
if (y < 0) { return y; }
return y % 8;
}
public static uint M2(uint y)
{
if ((int)y < 0) { return y; }
return y % 8;
}We currently generate the same assembly:
mov eax, ecx
and eax, 7
test ecx, ecx
cmovl eax, ecxThis is due to the if (y < 0) { return y; } check in M1 allowing the JIT to determine that y is never negative when it comes to the y % 8 expression.
However, in the case of the the following:
public static int M3(Span<int> x, int y)
{
return x[y] + (y % 8);
}We instead generate the following for the y % 8:
mov eax, ecx
sar eax, 31
and eax, 7
add eax, ecx
and eax, -8
sub ecx, eax
mov eax, ecxThis is unexpected since x[y] for both Span<T> and T[] is known to require a positive index and to throw if the index is not positive or greater than Length (i.e the bounds check fails). As such, it should be possible for the JIT to assert that y is never negative after it is successfully used as an index into a span or array.
While the code example given above is minimal and not necessarily representative of real world code, there are many places where such an index is used for latter indexing or computation and thus tracking the fact can lead to other downstream codegen improvements (whether that be simplified bounds checks elsewhere or optimizations such as is done for %).