From c619d18853b2fcd8b0eb301bcf6f71fee6e954f3 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 24 Oct 2019 06:57:13 -0400 Subject: [PATCH] [netcore] Add a few more missing SSE intrinsics. (mono/mono#17511) * [netcore] Add a few more missing SSE intrinsics. * Disable some intrinsics for non-llvm. Commit migrated from https://github.com/mono/mono/commit/951769b2795df22904079d79d8d97d35c44466ba --- src/mono/mono/mini/mini-llvm.c | 24 +++++ src/mono/mono/mini/simd-intrinsics-netcore.c | 136 ++++++++++++++++++++------- src/mono/mono/mini/simd-methods-netcore.h | 9 ++ 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index d07953b..9354941 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -7437,6 +7437,30 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) case OP_FDIV: values [ins->dreg] = LLVMBuildFDiv (builder, lhs, rhs, ""); break; + case OP_FMAX: + case OP_FMIN: { + LLVMValueRef args [] = { lhs, rhs }; + + gboolean is_r4 = ins->inst_c1 == MONO_TYPE_R4; + if (ins->inst_c0 == OP_FMAX) + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, is_r4 ? INTRINS_SSE_MAXPS : INTRINS_SSE_MAXPD), args, 2, dname); + else + values [ins->dreg] = LLVMBuildCall (builder, get_intrins (ctx, is_r4 ? INTRINS_SSE_MINPS : INTRINS_SSE_MINPD), args, 2, dname); + break; + } + case OP_IMAX: { + gboolean is_unsigned = ins->inst_c1 == MONO_TYPE_U1 || ins->inst_c1 == MONO_TYPE_U2 || ins->inst_c1 == MONO_TYPE_U4 || ins->inst_c1 == MONO_TYPE_U8; + LLVMValueRef cmp = LLVMBuildICmp (builder, is_unsigned ? LLVMIntUGT : LLVMIntSGT, lhs, rhs, ""); + values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, ""); + break; + } + case OP_IMIN: { + gboolean is_unsigned = ins->inst_c1 == MONO_TYPE_U1 || ins->inst_c1 == MONO_TYPE_U2 || ins->inst_c1 == MONO_TYPE_U4 || ins->inst_c1 == MONO_TYPE_U8; + LLVMValueRef cmp = LLVMBuildICmp (builder, is_unsigned ? LLVMIntULT : LLVMIntSLT, lhs, rhs, ""); + values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, ""); + } + break; + default: g_assert_not_reached (); } diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c index b4f1317..3903e6e 100644 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ b/src/mono/mono/mini/simd-intrinsics-netcore.c @@ -99,39 +99,6 @@ lookup_intrins (guint16 *intrinsics, int size, MonoMethod *cmethod) return (int)*result; } -static guint16 vector_methods [] = { - SN_get_IsHardwareAccelerated -}; - -static MonoInst* -emit_sys_numerics_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - gboolean supported = FALSE; - int id; - - id = lookup_intrins (vector_methods, sizeof (vector_methods), cmethod); - if (id == -1) - return NULL; - - //printf ("%s\n", mono_method_full_name (cmethod, 1)); - -#ifdef MONO_ARCH_SIMD_INTRINSICS - supported = TRUE; -#endif - - switch (id) { - case SN_get_IsHardwareAccelerated: - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - ins->type = STACK_I4; - return ins; - default: - break; - } - - return NULL; -} - static int type_to_expand_op (MonoType *type) { @@ -236,6 +203,90 @@ emit_xcompare (MonoCompile *cfg, MonoClass *klass, MonoType *etype, MonoInst *ar return ins; } +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")); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; + return etype; +} + +static guint16 vector_methods [] = { + SN_ConvertToDouble, + SN_ConvertToInt32, + SN_ConvertToInt64, + SN_ConvertToSingle, + SN_ConvertToUInt32, + SN_ConvertToUInt64, + SN_Narrow, + SN_Widen, + SN_get_IsHardwareAccelerated, +}; + +static MonoInst* +emit_sys_numerics_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + MonoInst *ins; + gboolean supported = FALSE; + int id; + MonoType *etype; + + id = lookup_intrins (vector_methods, sizeof (vector_methods), cmethod); + if (id == -1) + return NULL; + + //printf ("%s\n", mono_method_full_name (cmethod, 1)); + +#ifdef MONO_ARCH_SIMD_INTRINSICS + supported = TRUE; +#endif + + if (cfg->verbose_level > 1) { + char *name = mono_method_full_name (cmethod, TRUE); + printf (" SIMD intrinsic %s\n", name); + g_free (name); + } + + switch (id) { + case SN_get_IsHardwareAccelerated: + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + ins->type = STACK_I4; + return ins; + case SN_ConvertToInt32: + if (!COMPILE_LLVM (cfg)) + return NULL; + etype = get_vector_t_elem_type (fsig->params [0]); + g_assert (etype->type == MONO_TYPE_R4); + return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTPS2DQ, args [0]->dreg, -1); + case SN_ConvertToSingle: + if (!COMPILE_LLVM (cfg)) + return NULL; + etype = get_vector_t_elem_type (fsig->params [0]); + g_assert (etype->type == MONO_TYPE_I4 || etype->type == MONO_TYPE_U4); + // FIXME: + if (etype->type == MONO_TYPE_U4) + return NULL; + return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTDQ2PS, args [0]->dreg, -1); + case SN_ConvertToDouble: + case SN_ConvertToInt64: + case SN_ConvertToUInt32: + case SN_ConvertToUInt64: + case SN_Narrow: + case SN_Widen: + // FIXME: + break; + default: + break; + } + + return NULL; +} + static guint16 vector_t_methods [] = { SN_ctor, SN_CopyTo, @@ -244,6 +295,8 @@ static guint16 vector_t_methods [] = { SN_GreaterThanOrEqual, SN_LessThan, SN_LessThanOrEqual, + SN_Max, + SN_Min, SN_get_AllOnes, SN_get_Count, SN_get_Item, @@ -471,10 +524,15 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig case SN_op_BitwiseAnd: case SN_op_BitwiseOr: case SN_op_ExclusiveOr: + case SN_Max: + case SN_Min: if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type))) return NULL; + if (!COMPILE_LLVM (cfg) && (id == SN_Max || id == SN_Min)) + return NULL; ins = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, args [1]->dreg); ins->inst_c1 = etype->type; + if (etype->type == MONO_TYPE_R4 || etype->type == MONO_TYPE_R8) { switch (id) { case SN_op_Addition: @@ -489,6 +547,12 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig case SN_op_Division: ins->inst_c0 = OP_FDIV; break; + case SN_Max: + ins->inst_c0 = OP_FMAX; + break; + case SN_Min: + ins->inst_c0 = OP_FMIN; + break; default: NULLIFY_INS (ins); return NULL; @@ -518,6 +582,12 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig case SN_op_ExclusiveOr: ins->inst_c0 = OP_IXOR; break; + case SN_Max: + ins->inst_c0 = OP_IMAX; + break; + case SN_Min: + ins->inst_c0 = OP_IMIN; + break; default: NULLIFY_INS (ins); return NULL; diff --git a/src/mono/mono/mini/simd-methods-netcore.h b/src/mono/mono/mini/simd-methods-netcore.h index 41e61b0..efabc55 100644 --- a/src/mono/mono/mini/simd-methods-netcore.h +++ b/src/mono/mono/mini/simd-methods-netcore.h @@ -26,6 +26,15 @@ METHOD(op_Explicit) METHOD(op_Inequality) METHOD(op_Multiply) METHOD(op_Subtraction) +// Vector +METHOD(ConvertToInt32) +METHOD(ConvertToUInt32) +METHOD(ConvertToInt64) +METHOD(ConvertToUInt64) +METHOD(ConvertToSingle) +METHOD(ConvertToDouble) +METHOD(Narrow) +METHOD(Widen) // BMI1 METHOD(AndNot) METHOD(BitFieldExtract) -- 2.7.4