JIT: (bug) Strength reduction zeroes an intermediate local that a preserved `checked` overflow check still reads, suppressing OverflowException
- 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
{
public static int s_sink;
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Consume(int v) { s_sink += v; }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
public static void Test(int n, int seed)
{
int i = seed;
for (int c = 0; c < n; c++)
{
int t = i * 2; // 800000000
Consume(checked(t * 3)); // 2400000000 -> must throw
Consume(checked(t * 3));
i++;
}
}
public static int Main()
{
try
{
Test(4, 400000000);
Console.WriteLine("NO EXCEPTION");
}
catch (OverflowException)
{
Console.WriteLine("OverflowException");
}
return 100;
}
}
```
### Expected
`OverflowException` (printed with `DOTNET_JitEnableStrengthReduction=0`)
### Actual
`NO EXCEPTION` — the loop runs to completion and `Consume` is called with 0.
### Notes
`ExpandStoredCursors` retires the store `t = i * 2` and rewrites its data to zero (inductionvariableopts.cpp:2557), but the cursor replacement at inductionvariableopts.cpp:2529 deliberately keeps the throwing `MUL ovfl` via `gtExtractSideEffList`, and that retained node still reads `t`. The preserved overflow check therefore evaluates `0 * 3`. JitDump confirms: `[000010] was the data of store [000011]; expanded to 1 new cursors, and will replace with a store of 0` followed by `Replacing [000010] with a zero constant`.
Contributor guide
Research direction
Start with the repro and JIT dump, comparing behavior with DOTNET_JitEnableStrengthReduction=0. Inspect ExpandStoredCursors in inductionvariableopts.cpp around lines 2529 and 2557, especially the retained checked MUL and the replacement of the intermediate store. Done means the repro consistently throws OverflowException and does not pass 0 to Consume when strength reduction is enabled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100