Skip to content

[Wasm RyuJIT] Codegen for Const Vector Create and Basic Packed SIMD operations#129703

Open
adamperlin wants to merge 23 commits into
dotnet:mainfrom
adamperlin:adamperlin/wasm-basic-simd
Open

[Wasm RyuJIT] Codegen for Const Vector Create and Basic Packed SIMD operations#129703
adamperlin wants to merge 23 commits into
dotnet:mainfrom
adamperlin:adamperlin/wasm-basic-simd

Conversation

@adamperlin

Copy link
Copy Markdown
Contributor

This PR implements support for Vector128.Create on Wasm with known constant args, as well as table-driven expansion and codegen for a large set of PackedSimd opcodes that operate on v128, (v128, v128) and (v128, v128, v128) type operands.

Notably absent from this PR: Vector128.Create with non-constants (requires additional lowering work), and SIMD compares (need special codegen for ulong since i64_u compare is not natively supported on Wasm).

Copilot AI review requested due to automatic review settings June 22, 2026 18:02
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 22, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
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 extends CoreCLR’s Wasm (RyuJIT) pipeline to recognize Wasm SIMD instruction-set support and begin emitting v128 SIMD code, including constant Vector128.Create lowering to v128.const and table-driven codegen for many PackedSimd operations.

Changes:

  • Enable Wasm ISA flags (WasmBase, PackedSimd, Vector128) and wire up instruction-set support for Wasm32 (base, simd128).
  • Add GT_CNS_VEC emission via v128.const, plus v128 load/store selection for TYP_SIMD16.
  • Introduce initial importer/list/codegen plumbing for PackedSimd and Vector128.Create constants.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems Enables SupportsWasmIntrinsics for CoreCLR Wasm builds.
src/coreclr/tools/Common/InstructionSetHelpers.cs Adds Wasm32 baseline instruction sets (base, simd128).
src/coreclr/jit/lowerwasm.cpp Starts allowing SIMD-category GT_HWINTRINSIC through lowering.
src/coreclr/jit/lower.cpp Relaxes TYP_SIMD12 assert for Wasm during lowering checks.
src/coreclr/jit/instr.cpp Adds Wasm v128_load/v128_store mapping for TYP_SIMD16.
src/coreclr/jit/hwintrinsicwasm.cpp Implements constant Vector128.Create import to GT_CNS_VEC.
src/coreclr/jit/hwintrinsiclistwasm.h Adds PackedSimd intrinsic definitions and updates some Vector128 entries.
src/coreclr/jit/hwintrinsiccodegenwasm.cpp Adds initial table-driven Wasm HW intrinsic emission.
src/coreclr/jit/hwintrinsic.h Adds a Wasm HWIntrinsic helper wrapper (but currently has a preprocessor issue).
src/coreclr/jit/hwintrinsic.cpp Adds Wasm PackedSimd ISA range and simdSize validation for Wasm.
src/coreclr/jit/compiler.cpp Forces Wasm baseline ISAs into JIT supported set, adds Vector128.
src/coreclr/jit/codegenwasm.cpp Adds GT_HWINTRINSIC dispatch and GT_CNS_VEC emission (v128.const).
src/coreclr/jit/codegen.h Declares Wasm vector-constant codegen helper.

Comment thread src/coreclr/jit/hwintrinsic.h Outdated
Comment thread src/coreclr/jit/lowerwasm.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsic.cpp Outdated
Copilot AI review requested due to automatic review settings June 22, 2026 18:54

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.

Comment thread src/coreclr/jit/hwintrinsiccodegenwasm.cpp
Comment thread src/coreclr/jit/codegenwasm.cpp
Comment thread src/coreclr/jit/instr.cpp Outdated
Comment thread src/coreclr/jit/instr.cpp Outdated
Comment thread src/coreclr/jit/hwintrinsic.cpp Outdated
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsiclistwasm.h Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 22, 2026 19:32

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Comment thread src/coreclr/jit/hwintrinsic.cpp Outdated
…case in SPMI (can happen if NYI_WASM_SIMD fires during import)
Comment thread src/coreclr/jit/instr.cpp
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp

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

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Comment thread src/coreclr/jit/hwintrinsiclistwasm.h Outdated
Comment thread src/coreclr/jit/hwintrinsiclistwasm.h Outdated
Comment thread src/coreclr/scripts/superpmi.py Outdated
Comment thread src/coreclr/jit/hwintrinsicwasm.cpp
Copilot AI review requested due to automatic review settings June 23, 2026 20:57

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

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/jit/codegenwasm.cpp
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 23, 2026 22:05

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

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, GetElement, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, ToScalar, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, WithElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_ReturnsScalarT)
HARDWARE_INTRINSIC(Vector128, WithElement, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
Comment on lines +2408 to +2413
# A Wasm JIT may exit successfully without writing any disassembly to DOTNET_JitStdOutFile. For example, the wasm JIT
# with JitWasmSimdNyiToR2RUnsupported=1 exits via
# implReadyToRunUnsupported() (CORJIT_R2R_UNSUPPORTED) for NYI_WASM_SIMD during import, so no code is produced. This is an expected behavior.
# TODO-WASM: This check can potentially be removed once we no longer have any NYI's in the import stage.
if not os.path.exists(item_path) and self.coreclr_args.target_arch == "wasm":
return ""
…ck to managed implementation, and implement HARDWARE_INTRINSIC() stubs for all packed simd opcodes to ensure NYI
@adamperlin

Copy link
Copy Markdown
Contributor Author

@AndyAyersMS Copilot feedback has been implemented for the most part, so this one should be ready for another look. Now all of the PackedSimd intrinsics are at least stubbed out in the table and should cause NYI, so we won't end up trying to call the infinitely recursive managed versions.

@adamperlin

Copy link
Copy Markdown
Contributor Author

@tannergooding Could you please take a look at this when you have a chance? I don't think a fallback to managed path is possible for the PackedSimd intrinsics as they're just defined as self-calling.

@tannergooding

Copy link
Copy Markdown
Member

Could you please take a look at this when you have a chance?

Looking.

I don't think a fallback to managed path is possible for the PackedSimd intrinsics as they're just defined as self-calling.

This is expected. It's only the xplat APIs (i.e. Vector128<T> for WASM) where they fallback to managed if they cannot be accelerated by the JIT.

For the platform specified APIs (i.e. PackedSimd for WASM) they are "must expand" and so the JIT must handle them. This is generally setup in a way that if Isa.IsSupported is configured to return true then the JIT will create a relevant IR node and emit the codegen; otherwise it sees mustExpand = true and forces it to generate a throw new PlatformNotSupportedException instead. See https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/importercalls.cpp#L11472-L11531 and https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/importercalls.cpp#L3170-L3285, for where we handle the platform mismatch or the must expand calls for ISAs that aren't supported

For cases where the ISA is supported, but is not fully lit up, there is then a fallback to throw new NotImplementedException here: https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/importercalls.cpp#L3331-L3340; but this should only be hit when you're doing bringup for a new ISA and never in production.

else if (targetArchitecture == TargetArchitecture.Wasm32)
{
instructionSetSupportBuilder.AddSupportedInstructionSet("base");
instructionSetSupportBuilder.AddSupportedInstructionSet("simd128");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why simd128 and not packedsimd or similar?

Comment thread src/coreclr/jit/hwintrinsic.cpp Outdated
NYI_WASM_SIMD("PackedSimd.ReplaceScalar");
break;

case NI_PackedSimd_LoadVector128:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This one should just be gtNewSimdLoadNode, it only produces a GT_IND so the regular addressing mode and other support can kick in, similar with Store.

It's only the scalar and special semantic instructions which can't be represented as a "regular indirection" that we want to persist as GT_HWINTRINSIC nodes here.

NYI_WASM_SIMD("PackedSimd.Splat");
break;

case NI_Vector128_Create:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have nearly this same logic duplicated across xarch, arm64, and wasm now. It'd probably be good to have some impSimdCreate(intrinsicId) or similar so that the whole "pop stack and check if everything is constant" logic can be shared across them.

Co-authored-by: Tanner Gooding <tagoo@microsoft.com>
Copilot AI review requested due to automatic review settings June 25, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants