Closed
Description
using System;
public class C
{
public ReadOnlySpan<char> M1(ReadOnlySpan<char> span, int i)
{
if ((uint)i < (uint)span.Length)
{
return span.Slice(i);
}
return default;
}
public ReadOnlySpan<char> M2(ReadOnlySpan<char> span, int i)
{
if ((uint)i <= (uint)span.Length)
{
return span.Slice(i);
}
return default;
}
}
C.M1(System.ReadOnlySpan`1<Char>, Int32)
L0000: sub rsp, 0x28
L0004: mov rax, rdx
L0007: mov rdx, [r8]
L000a: mov ecx, [r8+8]
L000e: cmp r9d, ecx
L0011: jae short L002d
L0013: cmp r9d, ecx
L0016: ja short L003c
L0018: sub ecx, r9d
L001b: mov r8d, r9d
L001e: lea rdx, [rdx+r8*2]
L0022: mov [rax], rdx
L0025: mov [rax+8], ecx
L0028: add rsp, 0x28
L002c: ret
L002d: xor edx, edx
L002f: mov [rax], rdx
L0032: xor edx, edx
L0034: mov [rax+8], edx
L0037: add rsp, 0x28
L003b: ret
L003c: call 0x00007ffb1bc85778
L0041: int3
C.M2(System.ReadOnlySpan`1<Char>, Int32)
L0000: mov rax, rdx
L0003: mov rdx, [r8]
L0006: mov ecx, [r8+8]
L000a: cmp r9d, ecx
L000d: ja short L0020
L000f: sub ecx, r9d
L0012: mov r8d, r9d
L0015: lea rdx, [rdx+r8*2]
L0019: mov [rax], rdx
L001c: mov [rax+8], ecx
L001f: ret
L0020: xor edx, edx
L0022: mov [rax], rdx
L0025: xor edx, edx
L0027: mov [rax+8], edx
L002a: ret
ReadOnlySpan<T>.Slice
contains the following guard clause:
runtime/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs
Lines 332 to 339 in e4fb730
In M1, we've guaranteed we're only calling
span.Slice(i)
if i
is less than span.Length
, but the JIT doesn't see that it can then eliminate the branch in Slice
for when i
is greater than span.Length
.
In M2, the branch does get eliminated, presumably since it exactly matches the condition used by Slice
.
cc: @AndyAyersMS
Metadata
Metadata
Assignees
Type
Projects
Status
Done