Skip to content

JIT: Bounds checks not removed after casting a Span<T> with a known length to another type #32776

@Thealexbarney

Description

@Thealexbarney

The JIT doesn't completely eliminate the bounds checks in either of these functions.

public static short GetValue()
{
    ReadOnlySpan<byte> span = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    return MemoryMarshal.Cast<byte, short>(span)[1];
}

public static short GetValueS(ref byte a)
{
    ReadOnlySpan<byte> span = MemoryMarshal.CreateReadOnlySpan(ref a, 6);
    return MemoryMarshal.Cast<byte, short>(span)[1];
}

It's able to recognize that the new span has a known length, but doesn't remove the comparison between constants.

G_M41738_IG01:
       sub      rsp, 40
       nop      

G_M41738_IG02:
       mov      eax, 3
       cmp      eax, 1
       jbe      SHORT G_M41738_IG05
       mov      rax, 0xD1FFAB1E
       movsx    rax, word  ptr [rax]

G_M41738_IG03:
       add      rsp, 40
       ret      

G_M41738_IG04:
       call     CORINFO_HELP_OVERFLOW
       int3     

G_M41738_IG05:
       call     CORINFO_HELP_RNGCHKFAIL
       int3     

; Total bytes of code 46

-------------------------------------
G_M41737_IG01:
       sub      rsp, 40
       nop      

G_M41737_IG02:
       mov      eax, 3
       cmp      eax, 1
       jbe      SHORT G_M41737_IG05
       movsx    rax, word  ptr [rcx+2]

G_M41737_IG03:
       add      rsp, 40
       ret      

G_M41737_IG04:
       call     CORINFO_HELP_OVERFLOW
       int3     

G_M41737_IG05:
       call     CORINFO_HELP_RNGCHKFAIL
       int3     

; Total bytes of code 37

Returning a byte instead of casting to a short results in no bounds checks.

G_M41729_IG01:
       nop      

G_M41729_IG02:
       mov      rax, 0xD1FFAB1E
       movzx    rax, byte  ptr [rax]

G_M41729_IG03:
       ret      

; Total bytes of code 19

-------------------------------------
G_M41728_IG01:
       nop      

G_M41728_IG02:
       movzx    rax, byte  ptr [rcx+1]

G_M41728_IG03:
       ret      

; Total bytes of code 10

category:cq
theme:bounds-checks
skill-level:expert
cost:medium

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 SuperPMI

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions