dotnet / dotnet/runtime

Slicing a span with a list pattern produces unnecessary bounds check

Open
#120,607 5 comments 0 reactions 1 assignee Claimed by @EgorBo View on GitHub
area-CodeGen-coreclr tenet-performance
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

Given
```cs
static Span M(Span input) =>
input switch {
[_, ..var rest] => rest,
_ => input
};
```

Roslyn produces
```cs
static Span M(Span input)
{
int length = input.Length;
Span span;
if (length >= 1)
span = input.Slice(1, length - 1);
else
span = input;
return span;
}
```
Which is then compiled to
```asm
// coreclr trunk-20251010+e572463b5706b0509fe0c524d9d09893e7e252da

Program:M(System.Span`1[byte]):System.Span`1[byte] (FullOpts):
push rbp
mov rbp, rsp
test esi, esi
jg SHORT G_M16130_IG04
mov rax, rdi
mov edx, esi
jmp SHORT G_M16130_IG05
G_M16130_IG04: ;; offset=0x000F
lea edx, [rsi-0x01]
mov eax, edx
inc rax
mov ecx, esi
cmp rax, rcx
ja SHORT G_M16130_IG06
lea rax, bword ptr [rdi+0x01]
G_M16130_IG05: ;; offset=0x0022
pop rbp
ret
G_M16130_IG06: ;; offset=0x0024
call [System.ThrowHelper:ThrowArgumentOutOfRangeException()]
int3
```

Notably, rewriting it as
```cs
Span span;
if (input.Length >= 1)
span = input.Slice(1, input.Length - 1);
else
span = input;
return span;
```
results in the same output (also an issue with strings)

### Configuration

.NET runtime main branch commit e572463b5706b0509fe0c524d9d09893e7e252da

### Regression?

No

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.