dotnet / dotnet/runtime

JIT generates redundant mov for inline ++i (pre-increment)

Open
#129,532 6 comments 0 reactions 0 assignees View on GitHub
area-CodeGen-coreclr help wanted
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

https://godbolt.org/z/aYMq87E9G

```csharp
// Simplified repro
public static int N(ReadOnlySpan s, int i)
{
while (true)
{
if ((uint)++i >= (uint)s.Length)
break;

if (s[i] == '?')
return i;
}

return -1;
}
```

**Generated ASM:**
```asm
lea eax, [rdx+0x01]
mov edx, eax ; redundant
cmp edx, esi
```

**With a separate increment:**
```csharp
++i;
if ((uint)i >= (uint)s.Length)
break;
```

**Generated ASM:**
```asm
inc edx
cmp edx, esi
```

**.NET 8.0 behavior:** both variants generate identical `inc`; `cmp` code.

**Issue:**
- Inline `++i` adds an extra `mov`, increasing register pressure
- Causes spills in register-constrained methods
- Larger binary size

Contributor guide

Open the contributing guide

Research direction

Start with the C# reproducer and generated assembly at the linked Godbolt example, comparing inline ++i with the separate increment under .NET 8. Identify the JIT path that produces the redundant mov; done when the inline form avoids that move and preserves the demonstrated inc/cmp sequence without regressions.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.