Skip to content

Extra bounds checks are being generated in common span usage pattern #10950

@ahsonkhan

Description

@ahsonkhan

I would expect the following code to have no bounds checks within the disassembly beyond the explicit length check, when accessing the data via the indexer:

public static bool IsFirstSpace(ReadOnlySpan<byte> buffer)
{
    if (buffer.Length < 1 || buffer[0] != ' ')
        return false;
    return true;
}

However, I am seeing an extra comparison and jump instruction:

00007FFEC26EC790  sub         rsp,28h  
00007FFEC26EC794  mov         rax,qword ptr [rcx]  
00007FFEC26EC797  mov         edx,dword ptr [rcx+8]  
00007FFEC26EC79A  test        edx,edx  
00007FFEC26EC79C  jle         00007FFEC26EC7A8  
00007FFEC26EC79E  cmp         edx,0  
00007FFEC26EC7A1  jbe         00007FFEC26EC7B9  
00007FFEC26EC7A3  cmp         byte ptr [rax],20h  
00007FFEC26EC7A6  je          00007FFEC26EC7AF  
00007FFEC26EC7A8  xor         eax,eax  
00007FFEC26EC7AA  add         rsp,28h  
00007FFEC26EC7AE  ret  
00007FFEC26EC7AF  mov         eax,1  
00007FFEC26EC7B4  add         rsp,28h  
00007FFEC26EC7B8  ret  
00007FFEC26EC7B9  call        00007FFF214A56F0  
00007FFEC26EC7BE  int         3  

Workarounds like casting to uint, etc. do not help:

public static bool IsFirstSpace(ReadOnlySpan<byte> buffer)
{
    if ((uint)buffer.Length >= 1u && buffer[0] == ' ')
        return true;
    return false;
}

public static bool IsFirstSpace(ReadOnlySpan<byte> buffer)
{
    if (!buffer.IsEmpty && buffer[0] == ' ')
        return true;
    return false;
}

SharpLab Link

Version: Microsoft.NETCore.App 3.0.0-preview1-26809-04

cc @AndyAyersMS, @benaadams, @GrabYourPitchforks

category:cq
theme:range-check
skill-level:expert
cost:large

Metadata

Metadata

Assignees

No one assigned

    Labels

    JitUntriagedCLR JIT issues needing additional triagearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIoptimizationtenet-performancePerformance related issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions