Skip to content

JIT poor codegen for calculating field offsets of structs #40021

@john-h-k

Description

@john-h-k

Description

The JIT doesn't generate good assembly when calculating (what should be) constant fields offsets.
Example sharplab

Configuration

.NET 5, master branch on sharplab and I repro'd it locally with what i believe is a reasonably up to date copy of the runtime (i don't think it is more than a week old)

Analysis

I'm aware the JIT has to throw for null in the first null case, but they show it has the ability to resolve it to a constant (it emits it as a constant load of 4 there, although right after throwing an NRE). It doesn't seem to succeed doing this with either a local (even when SkipLocalsInit is enabled) or just with a pointer (where I would expect identical codegen to the null case, except comparing the pointer for null rather than immediately NREing).

[module: SkipLocalsInit]

public struct Example
{
    public byte Zero;

    private byte _1, _2, _3;

    public byte Four;
}

// good codegen :)! ... but instant null ref ex
public int OffsetAsNull()
{
    Example* p = null;
    return (int)(&p->Four - &p->Zero);
}

// bad codegen
public int OffsetAsNotNullWithLocal()
{
    Example local;
    Example* p = &local;
    return (int)(&p->Four - &p->Zero);
}

// bad codegen
public int OffsetAsNotNullWithParam(Example* p)
{
    return (int)(&p->Four - &p->Zero);
}

generates

C.OffsetAsNull()
    L0000: xor eax, eax
    L0002: cmp [eax], eax ; NRE
    L0004: mov eax, 4 ; constant offset load
    L0009: ret

C.OffsetAsNotNullWithLocal()
    L0000: sub esp, 8
    L0003: lea eax, [esp]
    L0006: cmp [eax], eax
    L0008: lea edx, [eax+4]
    L000b: sub edx, eax
    L000d: mov eax, edx
    L000f: add esp, 8
    L0012: ret

C.OffsetAsNotNullWithParam(Example*)
    L0000: cmp [edx], edx
    L0002: lea eax, [edx+4]  
    L0005: sub eax, edx ; it sets eax to edx + 4, then subs, but doesn't fold that to a constant?
    L0007: ret

category:cq
theme:basic-cq
skill-level:intermediate
cost:medium
impact:small

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions