Closed
Description
Description
Struct promotion (a.k.a. scalar replacement of aggregates) is an optimization that replaces structs with their constituent fields, allowing those fields to be optimized as if they were normal local variables. This is a very important optimization for low-level performance oriented code that makes heavy use of structs, so it is important that it is supported well by the JIT.
Limitations
The JIT supports promotion but with the following limitations today:
- Only whole structs with at most 4 fields can be promoted
- Nested structs are not supported, except when the nested struct is a wrapper around a primitive type
- A struct must be promoted for the full duration of the function or not at all
- Structs with overlapping fields are not supported
This issue is about removing (some of) these limitations.
Q1 work items
- Initial prototype (JIT: Add a (disabled) prototype for a generalized promotion pass #83388)
Q2 work items
- Add a few struct promotion related benchmarks performance#2991
- SPMI: Add possibility to specify custom options in diffs pipeline #84645
- Efficient decomposition for assignments
- JIT: Add a pass of liveness for the new locals inside physical promotion #86043
- JIT: Pick some low-hanging fruit in physical promotion throughput #86792
- JIT: Stop using ref counts in forward sub #85909
- JIT: Adjust physical promotion heuristics #86660
- JIT: Regularize readbacks for parameters/OSR-locals in physical promotion #87165
- JIT: Handle primitive remainder stores to regularly promoted fields in physical promotion #87217
- JIT: Reorder physical promotion and forward sub #87265
- JIT: Add support for induced field accesses in physical promotion #87410
- JIT: Induce more physical promotions #87810
- JIT: Cache significant segments computations for layouts in physical promotion #87745
- JIT: Insert readbacks eagerly in physical promotion #87809
- JIT: Insert writebacks more eagerly #87869
- JIT: Add a size component to the physical promotion heuristic #87969
- Rework JIT<->EE communication for struct promotion #87917
- Investigate regressions (see JIT: Enable physical promotion by default #88090 (comment))
- JIT: Enable physical promotion by default #88090
Future work items
CQ
- Decomposition via arithmetic
- Share backing storage when promoted locals are stack spilled
- Allow small-typed mismatches
- Support some bitcasts
- Partial lifetime promotion
- Move ABI info determination earlier so it can be utilized
- Store-forwarding for call args passed in registers
- Load-forwarding for calls
- Store-forwarding for structs returned in registers (JIT: Add a simple store-forwarding optimization for structs returned in registers #86388; punted due to low impact; existing promotion takes care of it)
- Custom class layouts with GC pointers (for some efficient decomposed copies)
- JIT: Handle liveness for defined retbufs in physical promotion #86711
- Readback/writeback resolution
- Full support for
GetElement
/WithElement
for SIMDs - Assignment decomposition for
GetElement
/WithElement
(JIT: Generalized struct promotion #76928 (comment))
Throughput
- More efficient accesses data structure
- Stop tracking accesses early when we know we won't promote (e.g. due to overlapping accesses)
- JIT: Add some limits in physical promotion #87729
- JIT: Optimize aggregate info iteration in physical promotion #87997
Related issues
- Promote (scalar replace) structs with more than 4 fields #6534
- JIT: Slow spills to stack in a loop on Linux vs Windows #58522
- Regressions due to QJFL and OSR #67594 (comment)
- Span<T> wrapped in a struct isn't performing as fast as it could be #68797
- Poor performance/code-gen with struct enumerators, especially when containing ReadOnlySpan #71510
- Poor codegen for "big" (> 4 fields) structs init #71565
- JIT: suboptimal generated code for struct overlapped field manipulation #69254
- Jit: Sub-optimal code when function is inlined #32415
- Recursive Promotion of structs containing fields of structs with a single pointer-sized field #7576
- RyuJIT x86: allow long-typed struct fields to be recursively promoted #6707
- Unused struct fields sometimes improve the codegen #79928