diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs index aa10a812145c0f..a460ad48506100 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs @@ -464,5 +464,33 @@ public abstract class PackedSimd internal static Vector128 ConvertNarrowingUnsignedSaturate(Vector128 lower, Vector128 upper) { throw new PlatformNotSupportedException(); } internal static Vector128 ConvertNarrowingUnsignedSaturate(Vector128 lower, Vector128 upper) { throw new PlatformNotSupportedException(); } + + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw new PlatformNotSupportedException(); } + + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw new PlatformNotSupportedException(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs index 9f9d481bace5e6..416e2f3580d93e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs @@ -1949,5 +1949,129 @@ public abstract class PackedSimd /// [Intrinsic] internal static Vector128 ConvertNarrowingUnsignedSaturate(Vector128 lower, Vector128 upper) => ConvertNarrowingUnsignedSaturate(lower, upper); + + /// + /// i16x8.extend_low_i8x16_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + /// + /// i16x8.extend_low_i8x16_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + /// + /// i32x4.extend_low_i16x8_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + /// + /// i32x4.extend_low_i16x8_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + /// + /// i64x2.extend_low_i32x4_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + /// + /// i64x2.extend_low_i32x4_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningLower(Vector128 value) => SignExtendWideningLower(value); + + /// + /// i16x8.extend_high_i8x16_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + /// + /// i16x8.extend_high_i8x16_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + /// + /// i32x4.extend_high_i16x8_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + /// + /// i32x4.extend_high_i16x8_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + /// + /// i64x2.extend_high_i32x4_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + /// + /// i64x2.extend_high_i32x4_s + /// + [Intrinsic] + public static Vector128 SignExtendWideningUpper(Vector128 value) => SignExtendWideningUpper(value); + + /// + /// i16x8.extend_low_i8x16_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + /// + /// i16x8.extend_low_i8x16_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + /// + /// i32x4.extend_low_i16x8_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + /// + /// i32x4.extend_low_i16x8_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + /// + /// i64x2.extend_low_i32x4_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + /// + /// i64x2.extend_low_i32x4_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningLower(Vector128 value) => ZeroExtendWideningLower(value); + + /// + /// i16x8.extend_high_i8x16_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + /// + /// i16x8.extend_high_i8x16_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + /// + /// i32x4.extend_high_i16x8_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + /// + /// i32x4.extend_high_i16x8_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + /// + /// i64x2.extend_high_i32x4_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); + /// + /// i64x2.extend_high_i32x4_u + /// + [Intrinsic] + public static Vector128 ZeroExtendWideningUpper(Vector128 value) => ZeroExtendWideningUpper(value); } } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 6153a616274da0..3ba909855a4e4a 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -6600,5 +6600,29 @@ public abstract partial class PackedSimd public static Vector128 ConvertToDoubleLower(Vector128 value) { throw null; } public static Vector128 ConvertToInt32Saturate(Vector128 value) { throw null; } public static Vector128 ConvertToInt32Saturate(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 SignExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningLower(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } + public static Vector128 ZeroExtendWideningUpper(Vector128 value) { throw null; } } } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index a1cebd399b291c..85fec5bf75921a 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -5207,6 +5207,14 @@ extract_low_elements (EmitContext *ctx, LLVMValueRef src_vec) return extract_half_elements (ctx, src_vec, FALSE); } +static G_GNUC_UNUSED LLVMTypeRef extended_type (LLVMTypeRef src_t) +{ + int nelems = LLVMGetVectorSize (src_t) / 2; + unsigned int width = mono_llvm_get_prim_size_bits (LLVMGetElementType(src_t)); + LLVMTypeRef int_t = LLVMIntType (width * 2); + return LLVMVectorType (int_t, nelems); +} + static LLVMValueRef keep_lowest_element (EmitContext *ctx, LLVMTypeRef dst_t, LLVMValueRef vec) { @@ -9942,6 +9950,17 @@ MONO_RESTORE_WARNING } #endif #if defined(TARGET_WASM) + case OP_WASM_SIMD_SEXT_LOWER: + case OP_WASM_SIMD_SEXT_UPPER: + case OP_WASM_SIMD_ZEXT_LOWER: + case OP_WASM_SIMD_ZEXT_UPPER: { + LLVMTypeRef ret_t = extended_type (LLVMTypeOf (lhs)); + gboolean upper = (ins->opcode == OP_WASM_SIMD_SEXT_UPPER || ins->opcode == OP_WASM_SIMD_ZEXT_UPPER); + gboolean sext = (ins->opcode == OP_WASM_SIMD_SEXT_LOWER || ins->opcode == OP_WASM_SIMD_SEXT_UPPER); + LLVMValueRef ext = upper ? extract_high_elements (ctx, lhs) : extract_low_elements (ctx, lhs); + values [ins->dreg] = sext ? LLVMBuildSExt (builder, ext, ret_t, "") : LLVMBuildZExt (builder, ext, ret_t, ""); + break; + } case OP_WASM_SIMD_CONV_R8_TO_R4: { LLVMValueRef val = LLVMBuildFPTrunc (builder, lhs, v64_r4_t, ""); values [ins->dreg] = LLVMBuildShuffleVector (builder, val, LLVMConstNull(v64_r4_t), create_const_vector_4_i32 (0, 1, 2, 3), ""); @@ -10068,11 +10087,7 @@ MONO_RESTORE_WARNING case OP_WASM_EXTMUL_UPPER_U: case OP_WASM_EXTMUL_LOWER: case OP_WASM_EXTMUL_UPPER: { - LLVMTypeRef src_t = LLVMTypeOf (lhs); - int nelems = LLVMGetVectorSize (src_t) / 2; - unsigned int width = mono_llvm_get_prim_size_bits (LLVMGetElementType(src_t)); - LLVMTypeRef int_t = LLVMIntType (width * 2); - LLVMTypeRef ret_t = LLVMVectorType (int_t, nelems); + LLVMTypeRef ret_t = extended_type (LLVMTypeOf (lhs)); int lower = ins->opcode == OP_WASM_EXTMUL_LOWER || ins->opcode == OP_WASM_EXTMUL_LOWER_U; gboolean is_unsigned = ins->opcode == OP_WASM_EXTMUL_LOWER_U || ins->opcode == OP_WASM_EXTMUL_UPPER_U; LLVMValueRef part1 = lower ? extract_low_elements (ctx, lhs) : extract_high_elements(ctx, lhs); diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index 05f3c07cdd4046..df1731f0e68015 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -862,6 +862,10 @@ MINI_OP(OP_WASM_EXTMUL_UPPER_U, "wasm_extmul_upper_u", XREG, XREG, XREG) MINI_OP(OP_WASM_SIMD_CONV_R8_TO_R4, "wasm_simd_conv_r8_to_r4", XREG, XREG, NONE) MINI_OP(OP_WASM_SIMD_CONV_R8_TO_I4_ZERO, "wasm_simd_conv_r8_to_i4_zero", XREG, XREG, NONE) MINI_OP(OP_WASM_SIMD_CONV_U4_TO_R8_LOW, "wasm_simd_conv_u4_to_r8_low", XREG, XREG, NONE) +MINI_OP(OP_WASM_SIMD_SEXT_LOWER, "wasm_simd_ext_lower_s", XREG, XREG, NONE) +MINI_OP(OP_WASM_SIMD_SEXT_UPPER, "wasm_simd_ext_upper_s", XREG, XREG, NONE) +MINI_OP(OP_WASM_SIMD_ZEXT_LOWER, "wasm_simd_ext_lower_u", XREG, XREG, NONE) +MINI_OP(OP_WASM_SIMD_ZEXT_UPPER, "wasm_simd_ext_upper_u", XREG, XREG, NONE) #endif #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_WASM) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index dd35ca50687406..9de5495e077077 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -5114,6 +5114,8 @@ static SimdIntrinsic packedsimd_methods [] = { {SN_ShiftRightArithmetic, OP_SIMD_SSHR}, {SN_ShiftRightLogical, OP_SIMD_USHR}, {SN_Shuffle, OP_WASM_SIMD_SHUFFLE}, + {SN_SignExtendWideningLower, OP_WASM_SIMD_SEXT_LOWER}, + {SN_SignExtendWideningUpper, OP_WASM_SIMD_SEXT_UPPER}, {SN_Splat}, {SN_Sqrt}, {SN_Subtract}, @@ -5121,6 +5123,8 @@ static SimdIntrinsic packedsimd_methods [] = { {SN_Swizzle, OP_WASM_SIMD_SWIZZLE}, {SN_Truncate, OP_XOP_OVR_X_X, INTRINS_SIMD_TRUNC}, {SN_Xor, OP_XBINOP_FORCEINT, XBINOP_FORCEINT_XOR}, + {SN_ZeroExtendWideningLower, OP_WASM_SIMD_ZEXT_LOWER}, + {SN_ZeroExtendWideningUpper, OP_WASM_SIMD_ZEXT_UPPER}, {SN_get_IsSupported}, };