JIT: (bug) Loop cloning drops bounds checks when the limit local is redefined between the zero-trip guard and the loop preheader
- 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
Assessment
This issue has not been assessed yet.