Skip to content

JIT: consider optimizing constructor pattern for struct creation #9237

Open
@AndyAyersMS

Description

@AndyAyersMS

Currently if you newobj a struct via a constructor call the jit assumes the struct's old value may be read during the construction of the new value. So the pattern emitted is:

;; zero temp obj storage
;; call constructor on temp obj
;; copy temp obj to the destination

When the final destination is register promoted all this tends to get cleaned up, but when the final destination can't be register promoted the code the jit produces can be surprisingly large and slow.

For instance, given

ValueTask<int> Work() => new ValueTask<int>(42);
ValueTaskAwaiter<int> vt = Work().GetAwaiter();
  ... vt.GetResult();

The jit may produce code like:

       33C9                 xor      rcx, rcx
       B82A000000           mov      eax, 42
       488D542420           lea      rdx, bword ptr [rsp+20H]
       C4E17957C0           vxorpd   xmm0, xmm0
       C4E17A7F02           vmovdqu  qword ptr [rdx], xmm0
       488D542420           lea      rdx, bword ptr [rsp+20H]
       48890A               mov      gword ptr [rdx], rcx
       894208               mov      dword ptr [rdx+8], eax
       C4E17A6F442420       vmovdqu  xmm0, qword ptr [rsp+20H]
       C4E17A7F442430       vmovdqu  qword ptr [rsp+30H], xmm0

In most cases the aliasing the jit is worried about does not happen, and the new value could be constructed directly into the destination. And also in most cases this construction will fully write the fields of the struct so the zero initialization is not necessary.

category:cq
theme:structs
skill-level:expert
cost:large
impact:large

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-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