diff --git a/src/mono/mono/mini/interp/interp-simd-intrins.def b/src/mono/mono/mini/interp/interp-simd-intrins.def index d88e543af2347..05f32f7e0f2ee 100644 --- a/src/mono/mono/mini/interp/interp-simd-intrins.def +++ b/src/mono/mono/mini/interp/interp-simd-intrins.def @@ -70,6 +70,8 @@ INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_R4_MULTIPLY, interp_v128_ INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_R4_DIVISION, interp_v128_r4_op_division, 231) +INTERP_SIMD_INTRINSIC_P_P (INTERP_SIMD_INTRINSIC_V128_BITCAST, interp_v128_bitcast, -1) + INTERP_SIMD_INTRINSIC_P_P (INTERP_SIMD_INTRINSIC_V128_I1_NEGATION, interp_v128_i1_op_negation, 97) INTERP_SIMD_INTRINSIC_P_P (INTERP_SIMD_INTRINSIC_V128_I2_NEGATION, interp_v128_i2_op_negation, 129) INTERP_SIMD_INTRINSIC_P_P (INTERP_SIMD_INTRINSIC_V128_I4_NEGATION, interp_v128_i4_op_negation, 161) diff --git a/src/mono/mono/mini/interp/interp-simd.c b/src/mono/mono/mini/interp/interp-simd.c index cdc6a951c5f92..4b3ca913c6e5c 100644 --- a/src/mono/mono/mini/interp/interp-simd.c +++ b/src/mono/mono/mini/interp/interp-simd.c @@ -28,6 +28,13 @@ interp_v128_i4_all_bits_set (gpointer res) memset (res, 0xff, SIZEOF_V128); } +// Vector128 As(Vector128 v1) +static void +interp_v128_bitcast (gpointer res, gpointer v1) +{ + *(v128_i1*)res = *(v128_i1*)v1; +} + // op_Addition static void interp_v128_i1_op_addition (gpointer res, gpointer v1, gpointer v2) diff --git a/src/mono/mono/mini/interp/simd-methods.def b/src/mono/mono/mini/interp/simd-methods.def index 2806dc9c12c4f..6256c4ebca75c 100644 --- a/src/mono/mono/mini/interp/simd-methods.def +++ b/src/mono/mono/mini/interp/simd-methods.def @@ -23,6 +23,19 @@ SIMD_METHOD(op_UnaryNegation) SIMD_METHOD(op_UnsignedRightShift) SIMD_METHOD(AndNot) +SIMD_METHOD(As) +SIMD_METHOD(AsByte) +SIMD_METHOD(AsDouble) +SIMD_METHOD(AsInt16) +SIMD_METHOD(AsInt32) +SIMD_METHOD(AsInt64) +SIMD_METHOD(AsNInt) +SIMD_METHOD(AsNUInt) +SIMD_METHOD(AsSByte) +SIMD_METHOD(AsSingle) +SIMD_METHOD(AsUInt16) +SIMD_METHOD(AsUInt32) +SIMD_METHOD(AsUInt64) SIMD_METHOD(ConditionalSelect) SIMD_METHOD(Create) SIMD_METHOD(CreateScalar) diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index ee0501db4658e..79f9e0c2970b5 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -56,6 +56,19 @@ lookup_intrins (guint16 *intrinsics, int size, MonoMethod *cmethod) // i.e. all 'get_' and 'op_' need to come after regular title-case names static guint16 sri_vector128_methods [] = { SN_AndNot, + SN_As, + SN_AsByte, + SN_AsDouble, + SN_AsInt16, + SN_AsInt32, + SN_AsInt64, + SN_AsNInt, + SN_AsNUInt, + SN_AsSByte, + SN_AsSingle, + SN_AsUInt16, + SN_AsUInt32, + SN_AsUInt64, SN_ConditionalSelect, SN_Create, SN_CreateScalar, @@ -310,6 +323,42 @@ get_common_simd_info (MonoClass *vector_klass, MonoMethodSignature *csignature, return TRUE; } +static MonoType* +get_vector_t_elem_type (MonoType *vector_type) +{ + MonoClass *klass; + MonoType *etype; + + g_assert (vector_type->type == MONO_TYPE_GENERICINST); + klass = mono_class_from_mono_type_internal (vector_type); + g_assert ( + !strcmp (m_class_get_name (klass), "Vector`1") || + !strcmp (m_class_get_name (klass), "Vector64`1") || + !strcmp (m_class_get_name (klass), "Vector128`1") || + !strcmp (m_class_get_name (klass), "Vector256`1") || + !strcmp (m_class_get_name (klass), "Vector512`1")); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; + return etype; +} + +static gboolean +is_element_type_primitive (MonoType *vector_type) +{ + if (vector_type->type == MONO_TYPE_GENERICINST) { + MonoType *element_type = get_vector_t_elem_type (vector_type); + return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type); + } else { + MonoClass *klass = mono_class_from_mono_type_internal (vector_type); + g_assert ( + !strcmp (m_class_get_name (klass), "Plane") || + !strcmp (m_class_get_name (klass), "Quaternion") || + !strcmp (m_class_get_name (klass), "Vector2") || + !strcmp (m_class_get_name (klass), "Vector3") || + !strcmp (m_class_get_name (klass), "Vector4")); + return TRUE; + } +} + static void emit_common_simd_epilogue (TransformData *td, MonoClass *vector_klass, MonoMethodSignature *csignature, int vector_size, gboolean allow_void) { @@ -387,6 +436,25 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature simd_opcode = MINT_SIMD_INTRINS_P_PP; simd_intrins = INTERP_SIMD_INTRINSIC_V128_AND_NOT; break; + case SN_As: + case SN_AsByte: + case SN_AsDouble: + case SN_AsInt16: + case SN_AsInt32: + case SN_AsInt64: + case SN_AsNInt: + case SN_AsNUInt: + case SN_AsSByte: + case SN_AsSingle: + case SN_AsUInt16: + case SN_AsUInt32: + case SN_AsUInt64: { + if (!is_element_type_primitive (csignature->ret) || !is_element_type_primitive (csignature->params [0])) + return FALSE; + simd_opcode = MINT_SIMD_INTRINS_P_P; + simd_intrins = INTERP_SIMD_INTRINSIC_V128_BITCAST; + break; + } case SN_ConditionalSelect: simd_opcode = MINT_SIMD_INTRINS_P_PPP; simd_intrins = INTERP_SIMD_INTRINSIC_V128_CONDITIONAL_SELECT; diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 2344c04c37ae7..4bbc0a09e0869 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1185,6 +1185,8 @@ static guint16 sri_vector_methods [] = { SN_AsInt16, SN_AsInt32, SN_AsInt64, + SN_AsNInt, + SN_AsNUInt, SN_AsSByte, SN_AsSingle, SN_AsUInt16, @@ -1618,6 +1620,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_AsInt16: case SN_AsInt32: case SN_AsInt64: + case SN_AsNInt: + case SN_AsNUInt: case SN_AsSByte: case SN_AsSingle: case SN_AsUInt16: diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index 6c0c47d26288c..fbf4098406819 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -71,6 +71,8 @@ METHOD(AsDouble) METHOD(AsInt16) METHOD(AsInt32) METHOD(AsInt64) +METHOD(AsNInt) +METHOD(AsNUInt) METHOD(AsSByte) METHOD(AsSingle) METHOD(AsUInt16)