Minimal repro
using System;
using System.Runtime.CompilerServices;
public static class Program
{
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
public static void Test(int seed, long[] dst)
{
int c = seed;
for (int i = 0; i < 10; i++)
{
dst[i] = (uint)c * 8L;
c++;
}
}
public static int Main()
{
long[] actual = new long[10];
Test(-3, actual);
long[] expected = new long[10];
for (int i = 0, c = -3; i < 10; i++, c++)
expected[i] = (uint)c * 8L;
Console.WriteLine("expected: " + string.Join(",", expected));
Console.WriteLine("actual: " + string.Join(",", actual));
for (int i = 0; i < 10; i++)
if (actual[i] != expected[i]) { Console.WriteLine("FAILED"); return 101; }
Console.WriteLine("PASSED");
return 100;
}
}
Expected
34359738344,34359738352,34359738360,0,8,16,24,32,40,48 (the int counter wraps through zero, so (uint)c restarts at 0). Reproduced with DOTNET_JitEnableStrengthReduction=0.
Actual
34359738344,34359738352,34359738360,34359738368,34359738376,34359738384,34359738392,34359738400,34359738408,34359738416 — the sequence keeps climbing past 2^32*8, exit code 101.
Notes
scev.cpp:1738-1742 in AddRecMayOverflow returns "cannot overflow" whenever Start->GetConstantValue() fails, i.e. treats any symbolic start as 0, contradicting the comment at scev.cpp:1731 ("only ... addRec = <L, 0, 1>"). Simplify (scev.cpp:1132-1136) then distributes the zext into <L, V02.2, 1> producing <L, zext(V02.2), 1>, and strength reduction materializes it as a new 64-bit primary IV. Correct shape would be the step guard's form: if (!GetConstantValue(...) || (startCns != 0)) return true;.
Minimal repro
Expected
34359738344,34359738352,34359738360,0,8,16,24,32,40,48(theintcounter wraps through zero, so(uint)crestarts at 0). Reproduced withDOTNET_JitEnableStrengthReduction=0.Actual
34359738344,34359738352,34359738360,34359738368,34359738376,34359738384,34359738392,34359738400,34359738408,34359738416— the sequence keeps climbing past 2^32*8, exit code 101.Notes
scev.cpp:1738-1742inAddRecMayOverflowreturns "cannot overflow" wheneverStart->GetConstantValue()fails, i.e. treats any symbolic start as 0, contradicting the comment atscev.cpp:1731("only ...addRec = <L, 0, 1>").Simplify(scev.cpp:1132-1136) then distributes thezextinto<L, V02.2, 1>producing<L, zext(V02.2), 1>, and strength reduction materializes it as a new 64-bit primary IV. Correct shape would be the step guard's form:if (!GetConstantValue(...) || (startCns != 0)) return true;.