dotnet / dotnet/runtime

JIT: (bug) Loop cloning drops bounds checks when the limit local is redefined between the zero-trip guard and the loop preheader

Closed
#133,762 3 comments 1 reaction 3 assignees Claimed by @jakobbotsch View on GitHub
area-CodeGen-coreclr
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Minimal repro
```csharp
using System;
using System.Runtime.CompilerServices;

public class Program
{
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
static int Test(int[] a, int i, int n)
{
int sum = 0;
if (i < n)
{
n = a.Length;
do
{
sum += a[i];
i++;
} while (i < n);
}
return sum;
}

public static int Main()
{
int[] a = new int[10];
try
{
int r = Test(a, 20, 30);
Console.WriteLine($"Expected: IndexOutOfRangeException / Actual: returned {r}");
return 1;
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Expected: IndexOutOfRangeException / Actual: IndexOutOfRangeException");
return 100;
}
}
}
```

Run: `corerun repro.dll` (Checked or Release JIT, .NET 11 main @ b44cd904110)

### Expected
`a[20]` on a 10-element array throws `IndexOutOfRangeException`; exit code 100.

### Actual
No exception

### Notes
No JIT knobs needed. `DOTNET_JitCloneLoops=0` restores the exception. `FlowGraphNaturalLoop::HasZeroTripTest` (flowgraph.cpp:6629) accepts the `i < n` guard without checking that `n` is not redefined between the guard and the preheader, so `NeedsZeroTripGuard` stays false and no entry guard is cloned (loopcloning.cpp:1346).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.