From 02ed3661b2bcb4b42625d75e54473a543914ff8b Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 15 May 2023 15:34:20 +0200 Subject: [PATCH 1/2] [wasm] Add extending conversions to PackedSimd --- .../Wasm/PackedSimd.PlatformNotSupported.cs | 28 ++++ .../Runtime/Intrinsics/Wasm/PackedSimd.cs | 124 ++++++++++++++++++ .../ref/System.Runtime.Intrinsics.cs | 24 ++++ src/mono/mono/mini/mini-llvm.c | 24 +++- src/mono/mono/mini/mini-ops.h | 4 + src/mono/mono/mini/simd-intrinsics.c | 4 + 6 files changed, 203 insertions(+), 5 deletions(-) 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 aa10a812145c0..a460ad4850610 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 9f9d481bace5e..416e2f3580d93 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 6153a616274da..3ba909855a4e4 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 a1cebd399b291..5f2e248d5e6a8 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -5207,6 +5207,13 @@ extract_low_elements (EmitContext *ctx, LLVMValueRef src_vec) return extract_half_elements (ctx, src_vec, FALSE); } +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 +9949,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 +10086,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 05f3c07cdd404..df1731f0e6801 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 dd35ca5068740..9de5495e07707 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}, }; From 2edb51324f7cbb53eeda1d7d4393c9c274ceeaf0 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Mon, 15 May 2023 17:22:26 +0200 Subject: [PATCH 2/2] Feedback --- src/mono/mono/mini/mini-llvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 5f2e248d5e6a8..85fec5bf75921 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -5207,7 +5207,8 @@ extract_low_elements (EmitContext *ctx, LLVMValueRef src_vec) return extract_half_elements (ctx, src_vec, FALSE); } -LLVMTypeRef extended_type (LLVMTypeRef src_t) { +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);