Skip to content

Inefficient register allocation in simple method which dereferences a span #13466

@GrabYourPitchforks

Description

@GrabYourPitchforks
    public static int DerefAndReturn(int index, ReadOnlySpan<int> span) {
        int retVal = default;
        
        if ((uint)index < (uint)span.Length)
        {
            retVal = span[index];
        }
        
        return retVal;
    }
C.DerefAndReturn(Int32, System.ReadOnlySpan`1<Int32>)
    L0000: mov rax, [rdx]
    L0003: mov edx, [rdx+0x8]
    L0006: xor r8d, r8d
    L0009: cmp ecx, edx
    L000b: jae L0014
    L000d: movsxd r8, ecx
    L0010: mov r8d, [rax+r8*4]
    L0014: mov eax, r8d
    L0017: ret

In this code sample which utilizes a "single return from function" pattern, the local retVal is stored in the r8d register instead of the eax register. This necessitates an additional mov instruction near the end of the method (L0014) to get the result into the correct return register. By using r8 to hold the span reference and eax to hold the return value, we can eliminate this instruction and reduce the size of the code gen.

The movsxd instruction is also unnecessary and can be replaced with a simpler mov instruction: that's being tracked by https://github.com/dotnet/coreclr/issues/23127.

category:cq
theme:register-allocator
skill-level:expert
cost:large

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions