Skip to content

JIT is missing a common case to track the IsNeverNegative assertion #102088

Closed
@tannergooding

Description

@tannergooding

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, ecx

This 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, ecx

This 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 %).

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions