Skip to content

Commit

Permalink
[wasm] PackedSimd, implement store methods (#87828)
Browse files Browse the repository at this point in the history
* [wasm] PackedSimd, implement store methods

* Feedback
  • Loading branch information
radekdoulik authored Jun 21, 2023
1 parent fc75f7e commit 5b900dd
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,34 @@ public abstract class PackedSimd
public static unsafe Vector128<long> LoadWideningVector128(int* address) { throw new PlatformNotSupportedException(); }
public static unsafe Vector128<ulong> LoadWideningVector128(uint* address) { throw new PlatformNotSupportedException(); }

// Store

public static unsafe void Store(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(nint* address, Vector128<nint> source) { throw new PlatformNotSupportedException(); }
public static unsafe void Store(nuint* address, Vector128<nuint> source) { throw new PlatformNotSupportedException(); }

public static unsafe void StoreSelectedScalar(sbyte* address, Vector128<sbyte> source, [ConstantExpected(Max = (byte)(15))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx16
public static unsafe void StoreSelectedScalar(byte* address, Vector128<byte> source, [ConstantExpected(Max = (byte)(15))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx16
public static unsafe void StoreSelectedScalar(short* address, Vector128<short> source, [ConstantExpected(Max = (byte)(7))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx8
public static unsafe void StoreSelectedScalar(ushort* address, Vector128<ushort> source, [ConstantExpected(Max = (byte)(7))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx8
public static unsafe void StoreSelectedScalar(int* address, Vector128<int> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(uint* address, Vector128<uint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(long* address, Vector128<long> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(ulong* address, Vector128<ulong> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(float* address, Vector128<float> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(double* address, Vector128<double> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw new PlatformNotSupportedException(); } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(nint* address, Vector128<nint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw new PlatformNotSupportedException(); }
public static unsafe void StoreSelectedScalar(nuint* address, Vector128<nuint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw new PlatformNotSupportedException(); }

// Floating-point sign bit operations

public static Vector128<float> Negate(Vector128<float> value) { throw new PlatformNotSupportedException(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,130 @@ public abstract class PackedSimd
[Intrinsic]
public static unsafe Vector128<nuint> LoadScalarAndInsert(nuint* address, Vector128<nuint> vector, [ConstantExpected(Max = (byte)(3))] byte index) => LoadScalarAndInsert(address, vector, index); // takes ImmLaneIdx4

// Store

/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(sbyte* address, Vector128<sbyte> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(byte* address, Vector128<byte> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(short* address, Vector128<short> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(ushort* address, Vector128<ushort> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(int* address, Vector128<int> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(uint* address, Vector128<uint> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(long* address, Vector128<long> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(ulong* address, Vector128<ulong> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(float* address, Vector128<float> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(double* address, Vector128<double> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(nint* address, Vector128<nint> source) => Store(address, source);
/// <summary>
/// v128.store
/// </summary>
[Intrinsic]
public static unsafe void Store(nuint* address, Vector128<nuint> source) => Store(address, source);

/// <summary>
/// v128.store8_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(sbyte* address, Vector128<sbyte> source, [ConstantExpected(Max = (byte)(15))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx16
/// <summary>
/// v128.store8_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(byte* address, Vector128<byte> source, [ConstantExpected(Max = (byte)(15))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx16
/// <summary>
/// v128.store16_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(short* address, Vector128<short> source, [ConstantExpected(Max = (byte)(7))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx8
/// <summary>
/// v128.store16_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(ushort* address, Vector128<ushort> source, [ConstantExpected(Max = (byte)(7))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx8
/// <summary>
/// v128.store32_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(int* address, Vector128<int> source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4
/// <summary>
/// v128.store32_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(uint* address, Vector128<uint> source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4
/// <summary>
/// v128.store64_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(long* address, Vector128<long> source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2
/// <summary>
/// v128.store64_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(ulong* address, Vector128<ulong> source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2
/// <summary>
/// v128.store32_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(float* address, Vector128<float> source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx4
/// <summary>
/// v128.store64_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(double* address, Vector128<double> source, [ConstantExpected(Max = (byte)(1))] byte index) => StoreSelectedScalar(address, source, index); // takes ImmLaneIdx2
/// <summary>
/// v128.store32_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(nint* address, Vector128<nint> source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index);
/// <summary>
/// v128.store32_lane
/// </summary>
[Intrinsic]
public static unsafe void StoreSelectedScalar(nuint* address, Vector128<nuint> source, [ConstantExpected(Max = (byte)(3))] byte index) => StoreSelectedScalar(address, source, index);

/// <summary>
/// v128.load8x8_s
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6784,6 +6784,30 @@ public abstract partial class PackedSimd
public static unsafe Vector128<uint> LoadWideningVector128(ushort* address) { throw null; }
public static unsafe Vector128<long> LoadWideningVector128(int* address) { throw null; }
public static unsafe Vector128<ulong> LoadWideningVector128(uint* address) { throw null; }
public static unsafe void Store(sbyte* address, Vector128<sbyte> source) { throw null; }
public static unsafe void Store(byte* address, Vector128<byte> source) { throw null; }
public static unsafe void Store(short* address, Vector128<short> source) { throw null; }
public static unsafe void Store(ushort* address, Vector128<ushort> source) { throw null; }
public static unsafe void Store(int* address, Vector128<int> source) { throw null; }
public static unsafe void Store(uint* address, Vector128<uint> source) { throw null; }
public static unsafe void Store(long* address, Vector128<long> source) { throw null; }
public static unsafe void Store(ulong* address, Vector128<ulong> source) { throw null; }
public static unsafe void Store(float* address, Vector128<float> source) { throw null; }
public static unsafe void Store(double* address, Vector128<double> source) { throw null; }
public static unsafe void Store(nint* address, Vector128<nint> source) { throw null; }
public static unsafe void Store(nuint* address, Vector128<nuint> source) { throw null; }
public static unsafe void StoreSelectedScalar(sbyte* address, Vector128<sbyte> source, [ConstantExpected(Max = (byte)(15))] byte index) { throw null; } // takes ImmLaneIdx16
public static unsafe void StoreSelectedScalar(byte* address, Vector128<byte> source, [ConstantExpected(Max = (byte)(15))] byte index) { throw null; } // takes ImmLaneIdx16
public static unsafe void StoreSelectedScalar(short* address, Vector128<short> source, [ConstantExpected(Max = (byte)(7))] byte index) { throw null; } // takes ImmLaneIdx8
public static unsafe void StoreSelectedScalar(ushort* address, Vector128<ushort> source, [ConstantExpected(Max = (byte)(7))] byte index) { throw null; } // takes ImmLaneIdx8
public static unsafe void StoreSelectedScalar(int* address, Vector128<int> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw null; } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(uint* address, Vector128<uint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw null; } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(long* address, Vector128<long> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw null; } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(ulong* address, Vector128<ulong> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw null; } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(float* address, Vector128<float> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw null; } // takes ImmLaneIdx4
public static unsafe void StoreSelectedScalar(double* address, Vector128<double> source, [ConstantExpected(Max = (byte)(1))] byte index) { throw null; } // takes ImmLaneIdx2
public static unsafe void StoreSelectedScalar(nint* address, Vector128<nint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw null; }
public static unsafe void StoreSelectedScalar(nuint* address, Vector128<nuint> source, [ConstantExpected(Max = (byte)(3))] byte index) { throw null; }
public static Vector128<float> Negate(Vector128<float> value) { throw null; }
public static Vector128<double> Negate(Vector128<double> value) { throw null; }
public static Vector128<float> Abs(Vector128<float> value) { throw null; }
Expand Down
53 changes: 46 additions & 7 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -8299,7 +8299,11 @@ MONO_RESTORE_WARNING
#endif // defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_WASM)

#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_WASM)

case OP_SIMD_STORE: {
LLVMValueRef dst_vec = convert (ctx, lhs, pointer_type (LLVMTypeOf (rhs)));
mono_llvm_build_aligned_store (builder, rhs, dst_vec, FALSE, ins->inst_c0);
break;
}
case OP_PADDB:
case OP_PADDW:
case OP_PADDD:
Expand Down Expand Up @@ -8960,12 +8964,6 @@ MONO_RESTORE_WARNING
break;
}

case OP_SSE_STORE: {
LLVMValueRef dst_vec = convert (ctx, lhs, pointer_type (LLVMTypeOf (rhs)));
mono_llvm_build_aligned_store (builder, rhs, dst_vec, FALSE, ins->inst_c0);
break;
}

case OP_SSE_STORES: {
LLVMValueRef first_elem = LLVMBuildExtractElement (builder, rhs, const_int32 (0), "");
LLVMValueRef dst = convert (ctx, lhs, pointer_type (LLVMTypeOf (first_elem)));
Expand Down Expand Up @@ -10212,6 +10210,47 @@ MONO_RESTORE_WARNING
values [ins->dreg] = broadcast_element (ctx, scalar, elems);
break;
}
case OP_WASM_SIMD_STORE_LANE: {
LLVMTypeRef rtype;
gboolean is_fp = FALSE;
switch(inst_c1_type (ins)) {
case MONO_TYPE_I1:
case MONO_TYPE_U1:
rtype = v128_i1_t;
break;
case MONO_TYPE_I2:
case MONO_TYPE_U2:
rtype = v128_i2_t;
break;
case MONO_TYPE_R4:
is_fp = TRUE;
rtype = v128_i4_t;
break;
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
rtype = v128_i4_t;
break;
case MONO_TYPE_R8:
is_fp = TRUE;
rtype = v128_i8_t;
break;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
rtype = v128_i8_t;
break;
default:
g_assert_not_reached();
}

LLVMTypeRef srctype = LLVMGetElementType (rtype);
LLVMValueRef src = is_fp ? convert(ctx, rhs, rtype) : rhs;
LLVMValueRef address = convert (ctx, lhs, pointer_type (srctype));
LLVMValueRef elem = LLVMBuildExtractElement (builder, src, arg3, "");
mono_llvm_build_aligned_store (builder, elem, address, FALSE, 1);
break;
}
#endif
#if defined(TARGET_ARM64) || defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_WASM)
case OP_XEQUAL: {
Expand Down
5 changes: 3 additions & 2 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,10 +868,11 @@ 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_OP3(OP_WASM_SIMD_LOAD_SCALAR_INSERT, "wasm_simd_load_scalar_insert", XREG, IREG, XREG, IREG)
MINI_OP(OP_WASM_SIMD_LOAD_SCALAR_SPLAT, "wasm_simd_load_scalar_splat_i1", XREG, IREG, NONE)
MINI_OP(OP_WASM_SIMD_LOAD_SCALAR_SPLAT, "wasm_simd_load_scalar_splat", XREG, IREG, NONE)
MINI_OP(OP_WASM_SIMD_LOAD_WIDENING, "wasm_simd_load_widening", XREG, IREG, 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_OP3(OP_WASM_SIMD_STORE_LANE, "wasm_simd_store_lane", NONE, IREG, XREG, IREG)
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
Expand Down Expand Up @@ -1054,7 +1055,6 @@ MINI_OP(OP_VECTOR_ANDN, "vector_andnot", XREG, XREG, XREG)
/* inst_c1 is target type */
MINI_OP(OP_SSE_LOADU, "sse_loadu", XREG, XREG, NONE)
MINI_OP(OP_SSE_MOVMSK, "sse_movmsk", IREG, XREG, NONE)
MINI_OP(OP_SSE_STORE, "sse_store", NONE, XREG, XREG)
MINI_OP(OP_SSE_STORES, "sse_stores", NONE, XREG, XREG)
MINI_OP(OP_SSE_MOVS, "sse_movs", XREG, XREG, NONE)
MINI_OP(OP_SSE_MOVS2, "sse_movs2", XREG, XREG, XREG)
Expand Down Expand Up @@ -1827,6 +1827,7 @@ MINI_OP3(OP_SIMD_SSRA, "simd_ssra", XREG, XREG, XREG, IREG)
MINI_OP(OP_SIMD_LOAD_SCALAR_I4, "simd_load_scalar_i4", XREG, IREG, NONE)
MINI_OP(OP_SIMD_LOAD_SCALAR_I8, "simd_load_scalar_i8", XREG, IREG, NONE)
MINI_OP(OP_SIMD_LOAD_SCALAR_R8, "simd_load_scalar_r8", XREG, IREG, NONE)
MINI_OP(OP_SIMD_STORE, "simd_store", NONE, XREG, XREG)

#if defined(TARGET_WASM)
MINI_OP(OP_WASM_ONESCOMPLEMENT, "wasm_onescomplement", XREG, XREG, NONE)
Expand Down
Loading

0 comments on commit 5b900dd

Please sign in to comment.