Description
Epic for improving the ability of the JIT to keep structs in registers.
Overview
The JIT currently supports keeping structs in registers when the individual fields are promoted to local variables (also known as scalar replacement). However, there are a number of cases where it forces them to the stack. Some of these cases are more fundamental, e.g. when they are address exposed. Others, however, are due to JIT limitations in handling argument passing and returns.
The Jit does not support keeping small structs in registers when the fields are not promoted and not accessed, for example, when the struct is only used as an argument or block.
.NET 6 scope:
Work items for multi-reg
- Support remaining unhandled cases where incoming arguments are passed in type-matched registers (i.e. there are N fields, and they are passed in N registers of the appropriate integer or floating-point type). (WIP @CarolEidt)
- CQ: Address cases where we're still forcing structs to the stack when they are passed in general-purpose registers, but contain promoted floating-point fields.
- This should address RyuJIT properly optimizes structs with a single field if the field type is int but not if it is double #4323, Struct getters are generating unneccessary instructions on x64 when struct contains floats #7200 and the remaining case in [RyuJIT] Eliminate unecessary copies when passing structs #9839.
Work items for single-reg
- CQ: Generate
LCL_FLD
instead ofIND(ADDR(LCL_VAR))
to avoid marking LCL_VAR as address-taken (struct improvement, part1: create more LCL_FLD #48377); - CQ: Allow small structs without field accesses and which address is not taken to be in registers;
- Correctness: fix passing HFA on stack on arm64 (Assertion failed '!foundDiff' when an HFA local var is passed on stack #49780);
- Correctness: improve Value numbering checking to prevent bad code generation with additional struct improvements (in progress Add checks to prevent silent bad codegen from VN optimizations. #49504, will address Test failure: System.Buffers.Tests.ArrayBufferWriterTests_Char.Advance #42517 , Test failure: JIT\\opt\\Structs\\structcopies\\structcopies.cmd in jitstress #49954, Jit asserts with
STRESS_PROMOTE_LESS_STRUCTS
#49189); - Testing: add additional stress modes to better test new and pre-existing optimizations (add STRESS_PROMOTE_LESS_STRUCTS mode. #49084, Add byref stress mode. #49636).
Stretch goals for 6.0:
Stretch goal for multi-reg:
- Cleanup of the multi-reg support methods (Enable promotion of structs passed in multiple registers with matching fields #37924)
Stretch goal for single-reg:
- Add support for LclFld with struct type;
- LclVar struct as first-class nodes, meaning don't create
OBJ(ADDR(LCL_VAR))
when pass as args etc.
.NET 6 Result:
We have a set of repro-tests that show incorrect/inefficient code generation in 5.0 that is expected to be fixed. It is covered by issues in the previous section.
The perf results are shown in the bottom messages.
category:planning
theme:planning
skill-level:expert
cost:large
impact:medium
Metadata
Metadata
Assignees
Labels
Type
Projects
Status