diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 890e6cad878c6..6403c739a03a8 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -9289,7 +9289,7 @@ MONO_RESTORE_WARNING break; } - case OP_SSSE3_ABS: { + case OP_VECTOR_IABS: { // %sub = sub <16 x i8> zeroinitializer, %arg // %cmp = icmp sgt <16 x i8> %arg, zeroinitializer // %abs = select <16 x i1> %cmp, <16 x i8> %arg, <16 x i8> %sub diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index 1123be8b4d689..b98c00b0b1709 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -1026,6 +1026,8 @@ MINI_OP(OP_CVTPS2PD, "cvtps2pd", XREG, XREG, NONE) MINI_OP(OP_CVTTPD2DQ, "cvttpd2dq", XREG, XREG, NONE) MINI_OP(OP_CVTTPS2DQ, "cvttps2dq", XREG, XREG, NONE) +MINI_OP(OP_VECTOR_IABS, "vector_integer_abs", XREG, XREG, NONE) + /* sse 1 */ /* inst_c1 is target type */ MINI_OP(OP_SSE_LOADU, "sse_loadu", XREG, XREG, NONE) @@ -1112,7 +1114,6 @@ MINI_OP(OP_SSE3_MOVSLDUP, "sse3_movsldup", XREG, XREG, NONE) MINI_OP(OP_SSE3_MOVDDUP_MEM, "sse3_movddup_mem", XREG, IREG, NONE) /* ssse 3 */ -MINI_OP(OP_SSSE3_ABS, "ssse3_abs", XREG, XREG, NONE) MINI_OP(OP_SSSE3_SHUFFLE, "ssse3_shuffle", XREG, XREG, XREG) MINI_OP3(OP_SSSE3_ALIGNR, "ssse3_alignr", XREG, XREG, XREG, IREG) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 80b966732904b..78c6a17fca101 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1130,12 +1130,27 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_Abs: { if (!is_element_type_primitive (fsig->params [0])) return NULL; -#ifdef TARGET_ARM64 if (type_enum_is_unsigned (arg0_type)) return NULL; - +#ifdef TARGET_ARM64 int iid = type_enum_is_float (arg0_type) ? INTRINS_AARCH64_ADV_SIMD_FABS : INTRINS_AARCH64_ADV_SIMD_ABS; return emit_simd_ins_for_sig (cfg, klass, OP_XOP_OVR_X_X, iid, arg0_type, fsig, args); +#elif defined(TARGET_AMD64) + MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + int size = mono_class_value_size (arg_class, NULL); + if (size != 16) // Works only with Vector128 + return NULL; + + if (type_enum_is_float(arg0_type)) { + // args [0] & ~vector(-0.0) + MonoInst *zero = emit_xzero(cfg, arg_class); // 0.0 + zero = emit_simd_ins (cfg, klass, OP_NEGATION, zero->dreg, -1); // -0.0 + MonoInst *ins = emit_simd_ins (cfg, klass, OP_SSE_ANDN, zero->dreg, args [0]->dreg); + ins->inst_c1 = arg0_type; + return ins; + } else { + return emit_simd_ins_for_sig (cfg, klass, OP_VECTOR_IABS, -1, arg0_type, fsig, args); + } #else return NULL; #endif @@ -3403,7 +3418,7 @@ static SimdIntrinsic sse3_methods [] = { }; static SimdIntrinsic ssse3_methods [] = { - {SN_Abs, OP_SSSE3_ABS}, + {SN_Abs, OP_VECTOR_IABS}, {SN_AlignRight}, {SN_HorizontalAdd}, {SN_HorizontalAddSaturate, OP_XOP_X_X_X, INTRINS_SSE_PHADDSW},