You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JIT: Improve parameter register field extraction and reconstruction - #131174
Rationalization and lowering now handle struct fields in ABI registers directly instead of going through memory:
Rationalizer::RewriteParameterField extracts aligned scalar fields from SIMD or FP parameter registers with GetElement (x64 movshdup, arm64 dup). Misaligned fields keep the bitcast/shift/narrow path.
On xarch, an 8-byte FP register is rebuilt from two promoted floats with unpcklps.
Promotion::MapsToParameterRegister is kept in sync with the rationalizer.
For {float X; float Y;}, return is 22 B → 4 B (PerfScore 6.25 → 2.00) and construct-and-pass is 9.4 ns → 4.4 ns. SuperPMI is net −7.8 KB on linux-x64 and −132 B on linux-arm, and library collections only improve. The regressions are mostly x64 HFA arguments that are only forwarded, which are now split and rebuilt with unpcklps. Promoting those by ABI segment instead would avoid that; this PR accepts the trade-off until then. The wasm fix landed separately in #131237. SuperPMI diffs
Note
This PR was authored with the assistance of GitHub Copilot.
The parameter-register-to-local mapping in lowering maps a scalar field of an
unenregisterable parameter to the local created for the containing register
segment, retyping the local access to the field's scalar type. On x64/arm64 a
scalar overlaps the low bytes of the vector register, so reading the register
local at scalar width is a free, correct reinterpret.
On wasm this is invalid: a v128 and a scalar (f64/f32/...) are distinct
value-stack types with no implicit reinterpret, so 'local.get <v128>' typed as
a scalar produces invalid wasm (wasm-tools: 'expected f64, found v128'). This
surfaces when crossgen2 compiles, e.g., Vector128<T>.GetHashCode (whose
GetElementUnsafe reads a scalar lane of the vector) inlined into
GenericEqualityComparer<Vector128<double>>.GetHashCode.
Guard the mapping on wasm: skip mapping a scalar field to a SIMD register
segment so the access falls back to the (memory-homed) unenregisterable
parameter and a normal scalar load is emitted. This is the floating-point
ToScalar / SIMD->scalar var_type case noted as deferred in dotnet#130444.
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adjusts JIT lowering for the wasm target to avoid inducing an invalid scalar read from a SIMD (v128) register-local when the accessed parameter field is a non-SIMD scalar type. The change is localized to the parameter-register-local mapping logic and is guarded to affect only wasm.
Changes:
Add a TARGET_WASM-guarded check in Lowering::FindInducedParameterRegisterLocals to skip mapping when the ABI segment is SIMD but the field access is scalar.
Preserve existing behavior for non-wasm targets and for SIMD-typed field accesses.
Yes — this is effectively on top of #130866 (it's in a wasm R2R prototype branch that has #130866 merged, which materializes `Vector128` as a wasm `v128` parameter — hence the v128 register parameter here). Agreed on `f64x2.extract_lane 0` (and the general extract/insert for the sibling paths) being the better, spill-free lowering. Let me look at doing it that way in this PR rather than the memory fallback.
Note
This comment was authored with the assistance of GitHub Copilot.
Per review feedback (thanks @tannergooding, @AndyAyersMS): rather than skipping the
parameter-register-local mapping for a scalar field of a SIMD register (which forces a spill/reload
through the memory-homed parameter), extract the lane directly from the SIMD register local via
gtNewSimdGetElementNode. This lowers to an explicit lane extract (e.g. f64x2.extract_lane 0) with no
spill. The GetElement node is lowered by the subsequent per-block lowering pass.
> [!NOTE]
> This change was authored with the assistance of GitHub Copilot.
Use direct SIMD lane extraction and scalar bit manipulation for fields carried in floating-point parameter registers. Keep physical promotion eligibility synchronized and retain the ARM32 fallback.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 22214765-2cd2-4951-b778-8793730f2bc1
lewing
changed the title
JIT: Fix wasm scalar-field extraction from a SIMD-register parameter
JIT: Improve parameter register field extraction
Jul 22, 2026
JIT/Directed uses hand-maintained MergedWrapperProjectReference lists
rather than the glob that JIT/opt uses, and the new project was never
added to one. No runner referenced it, so the test never ran in CI in
any form - it appears in neither the passed nor the skipped results for
the Pri0 legs. Building it directly with -Test or -Dir hid this, since
those bypass runner discovery.
Add it to Directed_ro.csproj alongside the other StructABI projects;
DebugType None with Optimize true matches that runner. The generated
runner now registers it as an out-of-process test, the same shape as
EmptyStructs.cmd.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Accept both the legacy two-operand and VEX three-operand forms of unpcklps in the FieldListFloatInsertion checks.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
ARM32 promotion needs a conservative exclusion or a corresponding reconstruction path.
Review tier: Lite Findings: None
Previously missed findings (1)
In code that hasn't changed since last review
Avoid re-enabling costly float promotion on ARM32
src/coreclr/jit/promotion.cpp:3077
On ARM32 this condition now allows MapsToParameterRegister to promote a float field from a floating-point parameter-register segment at offset 0. The induced extraction is supported, but ARM32 has no matching field-list reconstruction path, so calls that forward or P/Invoke these promoted values spill and reload; the PR reports a net +314-byte ARM32 regression, including +270 bytes in RayTracer:GetNaturalColor. Please retain the previous conservative exclusion for float accesses on ARM32 (while still allowing the existing integer-at-offset-zero case), or provide an ARM32 reconstruction before enabling this promotion.
Lowering::FindInducedParameterRegisterLocals moved to
Rationalizer::RewriteParameterField on main; carry the scalar
extraction changes over to the new location.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b44b5a92-06b0-45c9-a11f-c3ac6cab9b81
A GC-typed LCL_FLD over a SIMD parameter register reached
gtNewSimdGetElementNode, which requires an arithmetic base type.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b44b5a92-06b0-45c9-a11f-c3ac6cab9b81
- Gate the conservative FP-register check on LOWER_DECOMPOSE_LONGS, the
actual reason it exists, instead of TARGET_ARM.
- Clarify comments for the wasm exclusion and xarch-only float-pair rebuild.
- Move FieldListFloatInsertion to JIT/opt/Structs, which is picked up by
the JIT/opt merged runner glob.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b44b5a92-06b0-45c9-a11f-c3ac6cab9b81
…ility
IsFloatPairFieldListRegister already validates the whole register, so skip
the generic per-field loop for it, and restore the original float insertion
check. Document the fallthrough cases of the SIMD8 extraction.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b44b5a92-06b0-45c9-a11f-c3ac6cab9b81
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
6 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rationalization and lowering now handle struct fields in ABI registers directly instead of going through memory:
Rationalizer::RewriteParameterFieldextracts aligned scalar fields from SIMD or FP parameter registers withGetElement(x64movshdup, arm64dup). Misaligned fields keep the bitcast/shift/narrow path.unpcklps.Promotion::MapsToParameterRegisteris kept in sync with the rationalizer.For
{float X; float Y;}, return is 22 B → 4 B (PerfScore 6.25 → 2.00) and construct-and-pass is 9.4 ns → 4.4 ns. SuperPMI is net −7.8 KB on linux-x64 and −132 B on linux-arm, and library collections only improve. The regressions are mostly x64 HFA arguments that are only forwarded, which are now split and rebuilt withunpcklps. Promoting those by ABI segment instead would avoid that; this PR accepts the trade-off until then. The wasm fix landed separately in #131237. SuperPMI diffsNote
This PR was authored with the assistance of GitHub Copilot.