Skip to content

Use an explicit allow list for SIMD types in getTypeLayout - #131479

Open
tannergooding wants to merge 1 commit into
dotnet:mainfrom
tannergooding:tannergooding-fuzzy-tribble
Open

Use an explicit allow list for SIMD types in getTypeLayout#131479
tannergooding wants to merge 1 commit into
dotnet:mainfrom
tannergooding:tannergooding-fuzzy-tribble

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Follow-up to #131345 (comment).

The intrinsic check in getTypeLayout was a deny form: every [Intrinsic] type in System.Numerics and System.Runtime.Intrinsics was reported to the JIT as an opaque SIMD node, with the decimal floating-point types carved back out via IsDecimalFloatingPointOrHasDecimalFloatingPointFields. That only held while every intrinsic type in those namespaces happened to be SIMD, so each new non-SIMD intrinsic type needs another carve-out.

This names the SIMD types explicitly instead, via a new IsSimdIntrinsicType helper on both the native VM and the managed (crossgen2 / ILCompiler) side, mirroring the set recognized by Compiler::getBaseTypeAndSizeOfSIMDType:

  • System.Runtime.Intrinsics: Vector64<T>, Vector128<T>, Vector256<T>, Vector512<T>
  • System.Numerics: Vector<T>, Vector2, Vector3, Vector4, Plane, Quaternion

The managed helper reuses the existing VectorFieldLayoutAlgorithm.IsVectorType and VectorOfTFieldLayoutAlgorithm.IsVectorOfTType rather than duplicating those name checks. IsDecimalFloatingPointOrHasDecimalFloatingPointFields is untouched -- it's still used for the by-value marshal restriction in dllimport.cpp, mlinfo.cpp, classlayoutinfo.cpp, and MarshalHelpers.cs.


Matrix3x2/Matrix4x4 fall out of the set as well. They're [Intrinsic] and live in System.Numerics, so the old namespace-only test caught them, but getBaseTypeAndSizeOfSIMDType returns TYP_UNDEF for them, so their simdTypeHnd was never usable. Their fields are now enumerated like any other struct:

  • TryPromoteValueClassAsPrimitive rejected a Matrix field before (SIMD lookup fails, then numFields == 0 != 1) and rejects it now (simdTypeHnd == null, then numFields == 6 or 16 != 1), so no promotion can be lost.
  • TryPromoteStructVar has a 1 + MAX_NumOfFieldsInPromotableStruct * 2 == 9 node budget; a Matrix4x4 field overflows it into Partial -> return false, the same outcome as before.
  • ClassLayout::GetNonPadding treats a simdTypeHnd node as entirely non-padding. Matrices have no padding, and SegmentList::Add merges the adjacent per-field segments, so the resulting map is identical.
  • For R2R, Matrix types no longer hit the NeedsTypeLayoutCheck -> Failure bail and take the ordinary field-enumeration path. Their fields are primitive floats, which CheckTypeLayout handles; the getClassSize fixup concern applies only to types reported via simdTypeHnd.

No JIT-EE GUID bump -- the interface signature and CORINFO_TYPE_LAYOUT_NODE are unchanged.

Deliberately out of scope: MethodTable::ClassifyEightBytes* and SystemVStructClassificator also do intrinsic-type name checks, but against a deliberately smaller set (only Vector64/128/256/512<T> and Vector<T> -- Vector2/3/4, Plane, and Quaternion are passed in registers), so they can't share this helper.

Validation

SuperPMI can't cover this -- it replays recorded getTypeLayout responses, so a VM-side change is invisible to asmdiffs. Validated with a real build instead:

  • build.cmd clr -rc checked -- 0 warnings, 0 errors. Both ILCompiler.RyuJit and ILCompiler.ReadyToRun relink, so both #if READYTORUN arms compile.
  • A/B JitDump over wrapper structs for all 15 affected types (10 SIMD + Matrix3x2/Matrix4x4 + Decimal32/64/128), before vs. after, address-normalized: 0 differing lines out of 83,382. This confirms empirically that the Matrix delta is inert, including the Matrix3x2 case that fits within the node budget.
  • JIT/SIMD: 116/116 passed. JIT/Directed/StructPromote + JIT/Directed/physicalpromotion: 9/9 passed.

Note

This PR description and the accompanying code changes were drafted with GitHub Copilot.

The intrinsic check was a deny form: every [Intrinsic] type in System.Numerics
and System.Runtime.Intrinsics was reported to the JIT as an opaque SIMD node,
with the decimal floating-point types carved back out. That only held while
every intrinsic type in those namespaces happened to be SIMD, so each new
non-SIMD intrinsic type needs another carve-out.

Name the SIMD types explicitly instead, mirroring the set recognized by
Compiler::getBaseTypeAndSizeOfSIMDType. Matrix3x2/Matrix4x4 now fall out of the
set as well; the JIT already returned TYP_UNDEF for them, so their simdTypeHnd
was never usable.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 28, 2026 16:51
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens getTypeLayout’s SIMD “primitive” detection by replacing a broad namespace-based intrinsic check with an explicit allow list of SIMD types, ensuring non-SIMD [Intrinsic] types in System.Numerics / System.Runtime.Intrinsics have their fields enumerated and reported to the JIT.

Changes:

  • Add a VM-side IsSimdIntrinsicType(MethodTable*) helper and use it to decide when to set simdTypeHnd in CEEInfo::GetTypeLayoutHelper.
  • Add a managed (crossgen2/ILCompiler) IsSimdIntrinsicType(MetadataType) helper and use it for the analogous GetTypeLayoutHelper logic.
  • Remove the previous “deny-form” namespace-only SIMD detection (and associated decimal carve-out) from both implementations.
Show a summary per file
File Description
src/coreclr/vm/jitinterface.cpp Introduces an explicit SIMD allow list helper and uses it to drive simdTypeHnd in getTypeLayout.
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs Mirrors the VM behavior for AOT/tooling by introducing the same allow-list concept using existing vector type helpers.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 0

@tannergooding

Copy link
Copy Markdown
Member Author

CC. @MichalStrehovsky, this does the explicit filtering to avoid any potential future issues, only skipping for the types we definitely know are safe (because they map to TYP_SIMD*)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants