diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index a5adb8057f6a5e..fe89ca49146caf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -665,15 +665,12 @@ public static TInteger ConvertToInteger(double value) public static TInteger ConvertToIntegerNative(double value) where TInteger : IBinaryInteger { -#if !MONO if (typeof(TInteger).IsPrimitive) { // We need this to be recursive so indirect calls (delegates // for example) produce the same result as direct invocation return ConvertToIntegerNative(value); } -#endif - return TInteger.CreateSaturating(value); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index ef991d4aea3ea0..ce37952076f6b8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -660,15 +660,12 @@ public static TInteger ConvertToInteger(float value) public static TInteger ConvertToIntegerNative(float value) where TInteger : IBinaryInteger { -#if !MONO if (typeof(TInteger).IsPrimitive) { // We need this to be recursive so indirect calls (delegates // for example) produce the same result as direct invocation return ConvertToIntegerNative(value); } -#endif - return TInteger.CreateSaturating(value); } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 53ca6d2a10804a..04bf096566f838 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2676,7 +2676,54 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas !strncmp ("Vector", klass_name, 6) && !strcmp (tm, "get_IsHardwareAccelerated"))) { *op = MINT_LDC_I4_0; - } + } else if ((target_method->klass == mono_defaults.double_class) || (target_method->klass == mono_defaults.single_class)) { + MonoGenericContext *method_context = mono_method_get_context (target_method); + bool isDouble = target_method->klass == mono_defaults.double_class; + if (!strcmp (tm, "ConvertToIntegerNative") && + method_context != NULL && + method_context->method_inst->type_argc == 1) { + MonoTypeEnum tto_type = method_context->method_inst->type_argv [0]->type; + switch (tto_type) { + case MONO_TYPE_I1: + *op = isDouble ? MINT_CONV_I1_R8 : MINT_CONV_I1_R4; + break; + case MONO_TYPE_I2: + *op = isDouble ? MINT_CONV_I2_R8 : MINT_CONV_I2_R4; + break; +#if TARGET_SIZEOF_VOID_P == 4 + case MONO_TYPE_I: +#endif + case MONO_TYPE_I4: + *op = isDouble ? MINT_CONV_I4_R8 : MINT_CONV_I4_R4; + break; +#if TARGET_SIZEOF_VOID_P == 8 + case MONO_TYPE_I: +#endif + case MONO_TYPE_I8: + *op = isDouble ? MINT_CONV_I8_R8 : MINT_CONV_I8_R4; + break; + case MONO_TYPE_U1: + *op = isDouble ? MINT_CONV_U1_R8 : MINT_CONV_U1_R4; + break; + case MONO_TYPE_U2: + *op = isDouble ? MINT_CONV_U2_R8 : MINT_CONV_U2_R4; + break; +#if TARGET_SIZEOF_VOID_P == 4 + case MONO_TYPE_U: +#endif + case MONO_TYPE_U4: + *op = isDouble ? MINT_CONV_U4_R8 : MINT_CONV_U4_R4; + break; +#if TARGET_SIZEOF_VOID_P == 8 + case MONO_TYPE_U: +#endif + case MONO_TYPE_U8: + *op = isDouble ? MINT_CONV_U8_R8 : MINT_CONV_U8_R4; + break; + default: return FALSE; + } + } + } return FALSE; } diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 41c5be9c82022c..1b2c85c64bf744 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -2322,6 +2322,64 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return ins; } } + } else if ((cmethod->klass == mono_defaults.double_class) || (cmethod->klass == mono_defaults.single_class)) { + MonoGenericContext *method_context = mono_method_get_context (cmethod); + bool isDouble = cmethod->klass == mono_defaults.double_class; + if (!strcmp (cmethod->name, "ConvertToIntegerNative") && + method_context != NULL && + method_context->method_inst->type_argc == 1) { + int opcode = 0; + MonoTypeEnum tto_type = method_context->method_inst->type_argv [0]->type; + MonoStackType tto_stack = STACK_I4; + switch (tto_type) { + case MONO_TYPE_I1: + opcode = isDouble ? OP_FCONV_TO_I1 : OP_RCONV_TO_I1; + break; + case MONO_TYPE_I2: + opcode = isDouble ? OP_FCONV_TO_I2 : OP_RCONV_TO_I2; + break; +#if TARGET_SIZEOF_VOID_P == 4 + case MONO_TYPE_I: +#endif + case MONO_TYPE_I4: + opcode = isDouble ? OP_FCONV_TO_I4 : OP_RCONV_TO_I4; + break; +#if TARGET_SIZEOF_VOID_P == 8 + case MONO_TYPE_I: +#endif + case MONO_TYPE_I8: + opcode = isDouble ? OP_FCONV_TO_I8 : OP_RCONV_TO_I8; + tto_stack = STACK_I8; + break; + case MONO_TYPE_U1: + opcode = isDouble ? OP_FCONV_TO_U1 : OP_RCONV_TO_U1; + break; + case MONO_TYPE_U2: + opcode = isDouble ? OP_FCONV_TO_U2 : OP_RCONV_TO_U2; + break; +#if TARGET_SIZEOF_VOID_P == 4 + case MONO_TYPE_U: +#endif + case MONO_TYPE_U4: + opcode = isDouble ? OP_FCONV_TO_U4 : OP_RCONV_TO_U4; + break; +#if TARGET_SIZEOF_VOID_P == 8 + case MONO_TYPE_U: +#endif + case MONO_TYPE_U8: + opcode = isDouble ? OP_FCONV_TO_U8 : OP_RCONV_TO_U8; + tto_stack = STACK_I8; + break; + default: return NULL; + } + + if (opcode != 0) { + int ireg = mono_alloc_ireg (cfg); + EMIT_NEW_UNALU (cfg, ins, opcode, ireg, args [0]->dreg); + ins->type = tto_stack; + return mono_decompose_opcode(cfg, ins); + } + } } ins = mono_emit_simd_intrinsics (cfg, cmethod, fsig, args);