Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,43 @@ public abstract class PackedSimd
public static Vector128<int> AddPairwiseWidening(Vector128<short> value) { throw new PlatformNotSupportedException(); }
public static Vector128<uint> AddPairwiseWidening(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }

// Saturating integer arithmetic

public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }

public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }

public static Vector128<short> MultiplyRoundedSaturateQ15(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }

public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }

public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }

public static Vector128<byte> AverageRounded(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
public static Vector128<ushort> AverageRounded(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }

public static Vector128<sbyte> Abs(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
public static Vector128<short> Abs(Vector128<short> value) { throw new PlatformNotSupportedException(); }
public static Vector128<int> Abs(Vector128<int> value) { throw new PlatformNotSupportedException(); }
public static Vector128<long> Abs(Vector128<long> value) { throw new PlatformNotSupportedException(); }
public static Vector128<nint> Abs(Vector128<nint> value) { throw new PlatformNotSupportedException(); }

// Bit shifts

public static Vector128<sbyte> ShiftLeft(Vector128<sbyte> value, int count) { throw new PlatformNotSupportedException(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,127 @@ public abstract class PackedSimd
[Intrinsic]
public static Vector128<uint> AddPairwiseWidening(Vector128<ushort> value) => AddPairwiseWidening(value);

// Saturating integer arithmetic

/// <summary>
/// i8x16.add.sat.s
/// </summary>
public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => AddSaturate(left, right);
/// <summary>
/// i8x16.add.sat.u
/// </summary>
public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) => AddSaturate(left, right);
/// <summary>
/// i16x8.add.sat.s
/// </summary>
public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) => AddSaturate(left, right);
/// <summary>
/// i16x8.add.sat.u
/// </summary>
public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) => AddSaturate(left, right);

/// <summary>
/// i8x16.sub.sat.s
/// </summary>
public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => SubtractSaturate(left, right);
/// <summary>
/// i8x16.sub.sat.u
/// </summary>
public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) => SubtractSaturate(left, right);
/// <summary>
/// i16x8.sub.sat.s
/// </summary>
public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) => SubtractSaturate(left, right);
/// <summary>
/// i16x8.sub.sat.u
/// </summary>
public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) => SubtractSaturate(left, right);

/// <summary>
/// i16x8.q15mulr.sat.s
/// </summary>
public static Vector128<short> MultiplyRoundedSaturateQ15(Vector128<short> left, Vector128<short> right) => MultiplyRoundedSaturateQ15(left, right);

/// <summary>
/// i8x16.min.s
/// </summary>
public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
/// <summary>
/// i8x16.min.u
/// </summary>
public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
/// <summary>
/// i16x8.min.s
/// </summary>
public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
/// <summary>
/// i16x8.min.u
/// </summary>
public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
/// <summary>
/// i32x4.min.s
/// </summary>
public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
/// <summary>
/// i32x4.min.u
/// </summary>
public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);

/// <summary>
/// i8x16.max.s
/// </summary>
public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
/// <summary>
/// i8x16.max.u
/// </summary>
public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
/// <summary>
/// i16x8.max.s
/// </summary>
public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
/// <summary>
/// i16x8.max.u
/// </summary>
public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
/// <summary>
/// i32x4.max.s
/// </summary>
public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
/// <summary>
/// i32x4.max.u
/// </summary>
public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);

/// <summary>
/// i8x16.avgr.u
/// </summary>
public static Vector128<byte> AverageRounded(Vector128<byte> left, Vector128<byte> right) => AverageRounded(left, right);
/// <summary>
/// i16x8.avgr.u
/// </summary>
public static Vector128<ushort> AverageRounded(Vector128<ushort> left, Vector128<ushort> right) => AverageRounded(left, right);

/// <summary>
/// i8x16.abs
/// </summary>
public static Vector128<sbyte> Abs(Vector128<sbyte> value) => Abs(value);
/// <summary>
/// i16x8.abs
/// </summary>
public static Vector128<short> Abs(Vector128<short> value) => Abs(value);
/// <summary>
/// i32x4.abs
/// </summary>
public static Vector128<int> Abs(Vector128<int> value) => Abs(value);
/// <summary>
/// i64x2.abs
/// </summary>
public static Vector128<long> Abs(Vector128<long> value) => Abs(value);
/// <summary>
/// i32x4.abs
/// </summary>
public static Vector128<nint> Abs(Vector128<nint> value) => Abs(value);

// Bit shifts

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5745,6 +5745,34 @@ public abstract partial class PackedSimd
public static Vector128<ushort> AddPairwiseWidening(Vector128<byte> value) { throw null; }
public static Vector128<int> AddPairwiseWidening(Vector128<short> value) { throw null; }
public static Vector128<uint> AddPairwiseWidening(Vector128<ushort> value) { throw null; }
public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<short> MultiplyRoundedSaturateQ15(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw null; }
public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw null; }
public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw null; }
public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw null; }
public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw null; }
public static Vector128<byte> AverageRounded(Vector128<byte> left, Vector128<byte> right) { throw null; }
public static Vector128<ushort> AverageRounded(Vector128<ushort> left, Vector128<ushort> right) { throw null; }
public static Vector128<sbyte> Abs(Vector128<sbyte> value) { throw null; }
public static Vector128<short> Abs(Vector128<short> value) { throw null; }
public static Vector128<int> Abs(Vector128<int> value) { throw null; }
public static Vector128<long> Abs(Vector128<long> value) { throw null; }
public static Vector128<nint> Abs(Vector128<nint> value) { throw null; }
public static Vector128<sbyte> ShiftLeft(Vector128<sbyte> value, int count) { throw null; }
public static Vector128<byte> ShiftLeft(Vector128<byte> value, int count) { throw null; }
public static Vector128<short> ShiftLeft(Vector128<short> value, int count) { throw null; }
Expand Down
17 changes: 13 additions & 4 deletions src/mono/mono/mini/llvm-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,16 +242,18 @@ INTRINS(AESNI_AESDECLAST, x86_aesni_aesdeclast, X86)
INTRINS(AESNI_AESENC, x86_aesni_aesenc, X86)
INTRINS(AESNI_AESENCLAST, x86_aesni_aesenclast, X86)
INTRINS(AESNI_AESIMC, x86_aesni_aesimc, X86)
INTRINS_OVR(SSE_SADD_SATI8, sadd_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_UADD_SATI8, uadd_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_SADD_SATI16, sadd_sat, Generic, v128_i2_t)
INTRINS_OVR(SSE_UADD_SATI16, uadd_sat, Generic, v128_i2_t)

INTRINS_OVR(SSE_SSUB_SATI8, ssub_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_USUB_SATI8, usub_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_SSUB_SATI16, ssub_sat, Generic, v128_i2_t)
INTRINS_OVR(SSE_USUB_SATI16, usub_sat, Generic, v128_i2_t)
#endif
#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_WASM)
INTRINS_OVR(SSE_SADD_SATI8, sadd_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_UADD_SATI8, uadd_sat, Generic, v128_i1_t)
INTRINS_OVR(SSE_SADD_SATI16, sadd_sat, Generic, v128_i2_t)
INTRINS_OVR(SSE_UADD_SATI16, uadd_sat, Generic, v128_i2_t)
#endif
#if defined(TARGET_WASM)
INTRINS_OVR(WASM_EXTADD_PAIRWISE_SIGNED_V16, wasm_extadd_pairwise_signed, Wasm, sse_i2_t)
INTRINS_OVR(WASM_EXTADD_PAIRWISE_SIGNED_V8, wasm_extadd_pairwise_signed, Wasm, sse_i4_t)
Expand All @@ -265,6 +267,8 @@ INTRINS_OVR(WASM_ANYTRUE_V16, wasm_anytrue, Wasm, sse_i1_t)
INTRINS_OVR(WASM_ANYTRUE_V8, wasm_anytrue, Wasm, sse_i2_t)
INTRINS_OVR(WASM_ANYTRUE_V4, wasm_anytrue, Wasm, sse_i4_t)
INTRINS_OVR(WASM_ANYTRUE_V2, wasm_anytrue, Wasm, sse_i8_t)
INTRINS_OVR(WASM_AVERAGE_ROUNDED_V16, wasm_avgr_unsigned, Wasm, sse_i1_t)
INTRINS_OVR(WASM_AVERAGE_ROUNDED_V8, wasm_avgr_unsigned, Wasm, sse_i2_t)
INTRINS_OVR(WASM_BITMASK_V16, wasm_bitmask, Wasm, sse_i1_t)
INTRINS_OVR(WASM_BITMASK_V8, wasm_bitmask, Wasm, sse_i2_t)
INTRINS_OVR(WASM_BITMASK_V4, wasm_bitmask, Wasm, sse_i4_t)
Expand All @@ -276,7 +280,12 @@ INTRINS_OVR_2_ARG(WASM_NARROW_SIGNED_V16, wasm_narrow_signed, Wasm, sse_i1_t, ss
INTRINS_OVR_2_ARG(WASM_NARROW_SIGNED_V8, wasm_narrow_signed, Wasm, sse_i2_t, sse_i4_t)
INTRINS_OVR_2_ARG(WASM_NARROW_UNSIGNED_V16, wasm_narrow_unsigned, Wasm, sse_i1_t, sse_i2_t)
INTRINS_OVR_2_ARG(WASM_NARROW_UNSIGNED_V8, wasm_narrow_unsigned, Wasm, sse_i2_t, sse_i4_t)
INTRINS(WASM_Q15MULR_SAT_SIGNED, wasm_q15mulr_sat_signed, Wasm)
INTRINS(WASM_SHUFFLE, wasm_shuffle, Wasm)
INTRINS_OVR(WASM_SUB_SAT_SIGNED_V16, wasm_sub_sat_signed, Wasm, sse_i1_t)
INTRINS_OVR(WASM_SUB_SAT_SIGNED_V8, wasm_sub_sat_signed, Wasm, sse_i2_t)
INTRINS_OVR(WASM_SUB_SAT_UNSIGNED_V16, wasm_sub_sat_unsigned, Wasm, sse_i1_t)
INTRINS_OVR(WASM_SUB_SAT_UNSIGNED_V8, wasm_sub_sat_unsigned, Wasm, sse_i2_t)
INTRINS(WASM_SWIZZLE, wasm_swizzle, Wasm)
#endif
#if defined(TARGET_ARM64)
Expand Down
73 changes: 73 additions & 0 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -4891,17 +4891,23 @@ static SimdIntrinsic wasmbase_methods [] = {
};

static SimdIntrinsic packedsimd_methods [] = {
{SN_Abs, OP_VECTOR_IABS},
{SN_Add},
{SN_AddPairwiseWidening},
{SN_AddSaturate},
{SN_And, OP_XBINOP_FORCEINT, XBINOP_FORCEINT_AND},
{SN_AverageRounded},
{SN_Bitmask, OP_WASM_SIMD_BITMASK},
{SN_CompareEqual},
{SN_CompareNotEqual},
{SN_ConvertNarrowingSignedSaturate},
{SN_ConvertNarrowingUnsignedSaturate},
{SN_Dot, OP_XOP_X_X_X, INTRINS_WASM_DOT},
{SN_ExtractLane},
{SN_Max, OP_XBINOP, OP_IMIN, OP_XBINOP, OP_IMIN_UN},
{SN_Min, OP_XBINOP, OP_IMAX, OP_XBINOP, OP_IMAX_UN},
{SN_Multiply},
{SN_MultiplyRoundedSaturateQ15, OP_XOP_X_X_X, INTRINS_WASM_Q15MULR_SAT_SIGNED},
{SN_MultiplyWideningLower, OP_WASM_EXTMUL_LOWER, 0, OP_WASM_EXTMUL_LOWER_U},
{SN_MultiplyWideningUpper, OP_WASM_EXTMUL_UPPER, 0, OP_WASM_EXTMUL_UPPER_U},
{SN_Negate},
Expand All @@ -4912,6 +4918,7 @@ static SimdIntrinsic packedsimd_methods [] = {
{SN_Shuffle, OP_WASM_SIMD_SHUFFLE},
{SN_Splat},
{SN_Subtract},
{SN_SubtractSaturate},
{SN_Swizzle, OP_WASM_SIMD_SWIZZLE},
{SN_get_IsSupported},
};
Expand Down Expand Up @@ -5018,6 +5025,48 @@ emit_wasm_supported_intrinsics (

return NULL;
}
case SN_AddSaturate: {
op = OP_XOP_X_X_X;

switch (arg0_type) {
case MONO_TYPE_I1:
c0 = INTRINS_SSE_SADD_SATI8;
break;
case MONO_TYPE_I2:
c0 = INTRINS_SSE_SADD_SATI16;
break;
case MONO_TYPE_U1:
c0 = INTRINS_SSE_UADD_SATI8;
break;
case MONO_TYPE_U2:
c0 = INTRINS_SSE_UADD_SATI16;
break;
}

// continue with default emit
if (c0 != 0)
break;

return NULL;
}
case SN_AverageRounded: {
op = OP_XOP_X_X_X;

switch (arg0_type) {
case MONO_TYPE_U1:
c0 = INTRINS_WASM_AVERAGE_ROUNDED_V16;
break;
case MONO_TYPE_U2:
c0 = INTRINS_WASM_AVERAGE_ROUNDED_V8;
break;
}

// continue with default emit
if (c0 != 0)
break;

return NULL;
}
case SN_CompareEqual:
return emit_simd_ins_for_sig (cfg, klass, type_enum_is_float (arg0_type) ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_EQ, arg0_type, fsig, args);
case SN_CompareNotEqual:
Expand Down Expand Up @@ -5074,6 +5123,30 @@ emit_wasm_supported_intrinsics (
g_assert (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype));
return emit_simd_ins (cfg, klass, type_to_expand_op (etype->type), args [0]->dreg, -1);
}
case SN_SubtractSaturate: {
op = OP_XOP_X_X_X;

switch (arg0_type) {
case MONO_TYPE_I1:
c0 = INTRINS_WASM_SUB_SAT_SIGNED_V16;
break;
case MONO_TYPE_I2:
c0 = INTRINS_WASM_SUB_SAT_SIGNED_V8;
break;
case MONO_TYPE_U1:
c0 = INTRINS_WASM_SUB_SAT_UNSIGNED_V16;
break;
case MONO_TYPE_U2:
c0 = INTRINS_WASM_SUB_SAT_UNSIGNED_V8;
break;
}

// continue with default emit
if (c0 != 0)
break;

return NULL;
}
}

// default emit path for cases with op set
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/mini/simd-methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -634,10 +634,12 @@ METHOD(MultiplyRoundedDoublingScalarBySelectedScalarAndSubtractSaturateHigh)
// Arm.Dp
METHOD(DotProductBySelectedQuadruplet)
// Wasm
METHOD(AverageRounded)
METHOD(Bitmask)
METHOD(ConvertNarrowingSignedSaturate)
METHOD(ConvertNarrowingUnsignedSaturate)
METHOD(ExtractLane)
METHOD(MultiplyRoundedSaturateQ15)
METHOD(ReplaceLane)
METHOD(ShiftLeft)
METHOD(Splat)
Expand Down