-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone
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
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
| public ReadOnlySpan<T> Slice(int start) | |
| { | |
| if ((uint)start > (uint)_length) | |
| ThrowHelper.ThrowArgumentOutOfRangeException(); | |
| return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start); | |
| } |
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
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Type
Projects
Status
Done