Skip to content

Span indexer doesn't elide bounds check when span initialized from an RVA static #13464

Description

When a ReadOnlySpan<byte> is initialized from an RVA static, typical bounds check elision on the span's indexer doesn't take place as expected.

    private static ReadOnlySpan<byte> MyRvaStatic => new byte[] { 1, 2, 3, 4, 5 };
    
    public static int FetchFromRvaStatic(int index) {
        int retVal = default;
        
        ReadOnlySpan<Byte> span = MyRvaStatic;
        if ((uint)index < (uint)span.Length)
        {
            retVal = span[index];
        }
        
        return retVal;
    }
    
    public static int FetchFromArgument(int index, ReadOnlySpan<byte> span) {
        int retVal = default;
        
        if ((uint)index < (uint)span.Length)
        {
            retVal = span[index];
        }
        
        return retVal;
    }
C.get_MyRvaStatic()
    L0000: mov rax, 0x2a875b3099c
    L000a: mov [rcx], rax
    L000d: mov dword [rcx+0x8], 0x5
    L0014: mov rax, rcx
    L0017: ret

C.FetchFromRvaStatic(Int32)
    L0000: sub rsp, 0x28
    L0004: xor eax, eax
    L0006: cmp ecx, 0x5
    L0009: jae L0021
    L000b: cmp ecx, 0x5
    L000e: jae L0026
    L0010: movsxd rax, ecx
    L0013: mov rdx, 0x2a875b3099c
    L001d: movzx eax, byte [rax+rdx]
    L0021: add rsp, 0x28
    L0025: ret
    L0026: call 0x7ff9de711e00
    L002b: int3

C.FetchFromArgument(Int32, System.ReadOnlySpan`1<Byte>)
    L0000: mov rax, [rdx]
    L0003: mov edx, [rdx+0x8]
    L0006: xor r8d, r8d
    L0009: cmp ecx, edx
    L000b: jae L0015
    L000d: movsxd r8, ecx
    L0010: movzx r8d, byte [rax+r8]
    L0015: mov eax, r8d
    L0018: ret

Note the FetchFromRvaStatic method has two bounds checks: the manual bounds check I wrote and the auto-generated bounds check from the indexer. The FetchFromArgument method only has the manual bounds check; the auto-generated bounds check is elided.

category:cq
theme:optimization
skill-level:expert
cost:medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIoptimization

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions