diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 10f1dc91e1d9a1..b995d5026944e6 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1268,6 +1268,7 @@ is_element_type_primitive (MonoType *vector_type) } } +#ifdef TARGET_ARM64 static MonoInst* emit_msb_vector_mask (MonoCompile *cfg, MonoClass *arg_class, MonoTypeEnum arg_type) { @@ -1358,6 +1359,7 @@ emit_msb_shift_vector_constant (MonoCompile *cfg, MonoClass *arg_class, MonoType msb_shift_vec->klass = arg_class; return msb_shift_vec; } +#endif /* * Emit intrinsics in System.Numerics.Vector and System.Runtime.Intrinsics.Vector64/128/256/512. @@ -1800,13 +1802,30 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi g_assert_not_reached (); } case SN_ExtractMostSignificantBits: { - if (!is_element_type_primitive (fsig->params [0]) || type_enum_is_float (arg0_type)) + if (!is_element_type_primitive (fsig->params [0])) return NULL; #ifdef TARGET_WASM + if (type_enum_is_float (arg0_type)) + return NULL; + return emit_simd_ins_for_sig (cfg, klass, OP_WASM_SIMD_BITMASK, -1, -1, fsig, args); #elif defined(TARGET_ARM64) - MonoInst* result_ins = NULL; - MonoClass* arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + MonoClass* arg_class; + if (type_enum_is_float (arg0_type)) { + MonoClass* cast_class; + if (arg0_type == MONO_TYPE_R4) { + arg0_type = MONO_TYPE_I4; + cast_class = mono_defaults.int32_class; + } else { + arg0_type = MONO_TYPE_I8; + cast_class = mono_defaults.int64_class; + } + arg_class = create_class_instance ("System.Runtime.Intrinsics", m_class_get_name (klass), m_class_get_byval_arg (cast_class)); + } else { + arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + } + + // FIXME: Add support for Vector64 on arm64 int size = mono_class_value_size (arg_class, NULL); if (size != 16) return NULL; @@ -1816,11 +1835,12 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi and_res_vec->sreg2 = msb_mask_vec->dreg; MonoInst* msb_shift_vec = emit_msb_shift_vector_constant (cfg, arg_class, arg0_type); - + MonoInst* shift_res_vec = emit_simd_ins (cfg, arg_class, OP_XOP_OVR_X_X_X, and_res_vec->dreg, msb_shift_vec->dreg); shift_res_vec->inst_c0 = INTRINS_AARCH64_ADV_SIMD_USHL; shift_res_vec->inst_c1 = arg0_type; + MonoInst* result_ins = NULL; if (arg0_type == MONO_TYPE_I1 || arg0_type == MONO_TYPE_U1) { // Always perform unsigned operations as vector sum and extract operations could sign-extend the result into the GP register // making the final result invalid. This is not needed for wider type as the maximum sum of extracted MSB cannot be larger than 8bits