From 16ff4c42389ee24d392335d8d97bb7b533078b69 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 23 Apr 2024 18:16:58 -0700 Subject: [PATCH] Expose the `ConvertToIntegerNative` APIs (#100993) * Expose the ConvertToIntegerNative APIs for the floating-point types * Accelerate the ConvertToInteger and related APIs * Applying formatting patch * Fixing some tests for x86 and skipping some tests on Mono --- src/coreclr/jit/compiler.h | 20 +- src/coreclr/jit/emit.h | 4 + src/coreclr/jit/gentree.cpp | 260 +++++++++++++----- src/coreclr/jit/hwintrinsicarm64.cpp | 26 +- src/coreclr/jit/hwintrinsiclistarm64.h | 8 + src/coreclr/jit/hwintrinsiclistxarch.h | 14 +- src/coreclr/jit/hwintrinsicxarch.cpp | 108 ++++++-- src/coreclr/jit/importercalls.cpp | 128 ++++++++- src/coreclr/jit/namedintrinsiclist.h | 2 + src/coreclr/jit/simdashwintrinsic.cpp | 101 +++---- src/coreclr/jit/simdashwintrinsiclistarm64.h | 4 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 4 + .../Common/tests/System/GenericMathHelpers.cs | 6 + .../ref/System.Numerics.Vectors.cs | 6 + .../src/System/Decimal.cs | 8 + .../src/System/Double.cs | 10 + .../System.Private.CoreLib/src/System/Half.cs | 8 + .../src/System/Numerics/IFloatingPoint.cs | 20 ++ .../src/System/Numerics/Vector.cs | 34 ++- .../System/Runtime/InteropServices/NFloat.cs | 8 + .../System/Runtime/Intrinsics/Vector128.cs | 62 ++++- .../System/Runtime/Intrinsics/Vector256.cs | 62 ++++- .../System/Runtime/Intrinsics/Vector512.cs | 62 ++++- .../src/System/Runtime/Intrinsics/Vector64.cs | 38 ++- .../src/System/Single.cs | 10 + .../ref/System.Runtime.InteropServices.cs | 2 + .../ref/System.Runtime.Intrinsics.cs | 24 ++ .../tests/Vectors/Vector128Tests.cs | 104 +++++++ .../tests/Vectors/Vector256Tests.cs | 104 +++++++ .../tests/Vectors/Vector512Tests.cs | 104 +++++++ .../tests/Vectors/Vector64Tests.cs | 73 +++++ .../System.Runtime/ref/System.Runtime.cs | 12 + .../System/DoubleTests.GenericMath.cs | 169 +++++++++++- .../System/SingleTests.GenericMath.cs | 167 +++++++++++ 34 files changed, 1578 insertions(+), 194 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3c19969d0c90d8..5b8a04e868836c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3188,13 +3188,17 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); -#if defined(TARGET_XARCH) - GenTree* gtNewSimdCvtNode(var_types type, - GenTree* op1, - CorInfoType simdTargetBaseJitType, - CorInfoType simdSourceBaseJitType, - unsigned simdSize); -#endif //TARGET_XARCH + GenTree* gtNewSimdCvtNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize); GenTree* gtNewSimdCreateBroadcastNode( var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize); @@ -5928,7 +5932,7 @@ class Compiler void fgReplaceEhfSuccessor(BasicBlock* block, BasicBlock* oldSucc, BasicBlock* newSucc); void fgRemoveEhfSuccessor(BasicBlock* block, const unsigned succIndex); - + void fgRemoveEhfSuccessor(FlowEdge* succEdge); void fgReplaceJumpTarget(BasicBlock* block, BasicBlock* oldTarget, BasicBlock* newTarget); diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 40a729dd70fee2..4fb37df5149111 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -4020,6 +4020,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subss: case INS_ucomiss: case INS_vbroadcastss: + case INS_vcvttss2usi32: + case INS_vcvttss2usi64: case INS_vfmadd132ss: case INS_vfmadd213ss: case INS_vfmadd231ss: @@ -4067,6 +4069,8 @@ emitAttr emitter::emitGetBaseMemOpSize(instrDesc* id) const case INS_subsd: case INS_ucomisd: case INS_vbroadcastsd: + case INS_vcvttsd2usi32: + case INS_vcvttsd2usi64: case INS_vfmadd132sd: case INS_vfmadd213sd: case INS_vfmadd231sd: diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 878c02ac1603df..c6d6b78c48ca9e 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21350,7 +21350,6 @@ GenTree* Compiler::gtNewSimdCeilNode(var_types type, GenTree* op1, CorInfoType s return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize); } -#if defined(TARGET_XARCH) GenTree* Compiler::gtNewSimdCvtNode(var_types type, GenTree* op1, CorInfoType simdTargetBaseJitType, @@ -21368,12 +21367,128 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, assert(varTypeIsIntegral(simdTargetBaseType)); assert(IsBaselineSimdIsaSupportedDebugOnly()); + +#if defined(TARGET_XARCH) assert(IsBaselineVector512IsaSupportedDebugOnly() || ((simdTargetBaseType == TYP_INT) && ((simdSize == 16 && compIsaSupportedDebugOnly(InstructionSet_SSE41)) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + GenTree* fixupVal; + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + /*Generate the control table for VFIXUPIMMSD/SS + - For conversion to unsigned + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b1000: Saturate to Zero + // +INF: 0b0000 + // -VAL: 0b1000: Saturate to Zero + // +VAL: 0b0000 + - For conversion to signed + // QNAN: 0b1000: Saturate to Zero + // SNAN: 0b1000: Saturate to Zero + // ZERO: 0b0000 + // +ONE: 0b0000 + // -INF: 0b0000 + // +INF: 0b0000 + // -VAL: 0b0000 + // +VAL: 0b0000 + */ + int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; + GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); + + // We need op1Clone to run fixup + GenTree* op1Clone = fgMakeMultiUse(&op1); + + // run vfixupimmsd base on table and no flags reporting + fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, + simdSourceBaseJitType, simdSize); + } + else + { + // Zero out NaN values from the input. + // mask1 contains the output either 0xFFFFFFFF or 0. + // FixupVal zeros out any NaN values in the input by ANDing input with mask1. + GenTree* op1Clone1 = fgMakeMultiUse(&op1); + GenTree* op1Clone2 = fgMakeMultiUse(&op1); + GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); + fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); + } + + if (varTypeIsSigned(simdTargetBaseType)) + { + GenTree* maxVal; + GenTree* maxValDup; + if (varTypeIsLong(simdTargetBaseType)) + { + int64_t actualMaxVal = INT64_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + else + { + ssize_t actualMaxVal = INT32_MAX; + maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); + maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); + maxValDup = + gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + } + + // we will be using the input value twice + GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + + // compare with max value of integer/long + fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + + // cast it + GenTree* castNode = + gtNewSimdCvtNativeNode(type, fixupValDup, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + + // use the fixupVal mask with input value and max value to blend + return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); + } + else + { + return gtNewSimdCvtNativeNode(type, fixupVal, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); + } +#elif defined(TARGET_ARM64) + return gtNewSimdCvtNativeNode(type, op1, simdTargetBaseJitType, simdSourceBaseJitType, simdSize); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 +} + +GenTree* Compiler::gtNewSimdCvtNativeNode(var_types type, + GenTree* op1, + CorInfoType simdTargetBaseJitType, + CorInfoType simdSourceBaseJitType, + unsigned simdSize) +{ + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdSourceBaseType = JitType2PreciseVarType(simdSourceBaseJitType); + var_types simdTargetBaseType = JitType2PreciseVarType(simdTargetBaseJitType); + assert(varTypeIsFloating(simdSourceBaseType)); + assert(varTypeIsIntegral(simdTargetBaseType)); + + assert(IsBaselineSimdIsaSupportedDebugOnly()); + // Generate intrinsic needed for conversion NamedIntrinsic hwIntrinsicID = NI_Illegal; + +#if defined(TARGET_XARCH) + assert(IsBaselineVector512IsaSupportedDebugOnly() || + ((simdTargetBaseType == TYP_INT) && + ((simdSize == 16) || (simdSize == 32 && compIsaSupportedDebugOnly(InstructionSet_AVX))))); + switch (simdSourceBaseJitType) { case CORINFO_TYPE_FLOAT: @@ -21389,21 +21504,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512Int32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX_ConvertToVector256Int32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_SSE2_ConvertToVector128Int32WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_UINT: { switch (simdSize) @@ -21413,26 +21532,31 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512F_ConvertToVector512UInt32WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector256UInt32WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512F_VL_ConvertToVector128UInt32WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + case CORINFO_TYPE_DOUBLE: { switch (simdTargetBaseJitType) @@ -21446,21 +21570,25 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512Int64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256Int64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128Int64WithTruncation; break; } + default: unreached(); } break; } + case CORINFO_TYPE_ULONG: { switch (simdSize) @@ -21470,115 +21598,95 @@ GenTree* Compiler::gtNewSimdCvtNode(var_types type, hwIntrinsicID = NI_AVX512DQ_ConvertToVector512UInt64WithTruncation; break; } + case 32: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector256UInt64WithTruncation; break; } + case 16: { hwIntrinsicID = NI_AVX512DQ_VL_ConvertToVector128UInt64WithTruncation; break; } + default: unreached(); } break; } + default: unreached(); } break; } + default: unreached(); } - assert(hwIntrinsicID != NI_Illegal); - - GenTree* fixupVal; +#elif defined(TARGET_ARM64) + assert((simdSize == 8) || (simdSize == 16)); - if (IsBaselineVector512IsaSupportedOpportunistically()) + switch (simdSourceBaseJitType) { - /*Generate the control table for VFIXUPIMMSD/SS - - For conversion to unsigned - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b1000: Saturate to Zero - // +INF: 0b0000 - // -VAL: 0b1000: Saturate to Zero - // +VAL: 0b0000 - - For conversion to signed - // QNAN: 0b1000: Saturate to Zero - // SNAN: 0b1000: Saturate to Zero - // ZERO: 0b0000 - // +ONE: 0b0000 - // -INF: 0b0000 - // +INF: 0b0000 - // -VAL: 0b0000 - // +VAL: 0b0000 - */ - int32_t iconVal = varTypeIsUnsigned(simdTargetBaseType) ? 0x08080088 : 0x00000088; - GenTree* tblCon = gtNewSimdCreateBroadcastNode(type, gtNewIconNode(iconVal), simdTargetBaseJitType, simdSize); - - // We need op1Clone to run fixup - GenTree* op1Clone = fgMakeMultiUse(&op1); + case CORINFO_TYPE_FLOAT: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_INT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToInt32RoundToZero; + break; + } - // run vfixupimmsd base on table and no flags reporting - fixupVal = gtNewSimdHWIntrinsicNode(type, op1, op1Clone, tblCon, gtNewIconNode(0), NI_AVX512F_Fixup, - simdSourceBaseJitType, simdSize); - } - else - { - // Zero out NaN values from the input. - // mask1 contains the output either 0xFFFFFFFF or 0. - // FixupVal zeros out any NaN values in the input by ANDing input with mask1. - GenTree* op1Clone1 = fgMakeMultiUse(&op1); - GenTree* op1Clone2 = fgMakeMultiUse(&op1); - GenTree* mask1 = gtNewSimdCmpOpNode(GT_EQ, type, op1, op1Clone1, simdSourceBaseJitType, simdSize); - fixupVal = gtNewSimdBinOpNode(GT_AND, type, op1Clone2, mask1, simdSourceBaseJitType, simdSize); - } + case CORINFO_TYPE_UINT: + { + hwIntrinsicID = NI_AdvSimd_ConvertToUInt32RoundToZero; + break; + } - if (varTypeIsSigned(simdTargetBaseType)) - { - GenTree* maxVal; - GenTree* maxValDup; - if (varTypeIsLong(simdTargetBaseType)) - { - int64_t actualMaxVal = INT64_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewLconNode(actualMaxVal), simdTargetBaseJitType, simdSize); - } - else - { - ssize_t actualMaxVal = INT32_MAX; - maxVal = gtNewDconNode(static_cast(actualMaxVal), simdSourceBaseType); - maxVal = gtNewSimdCreateBroadcastNode(type, maxVal, simdSourceBaseJitType, simdSize); - maxValDup = - gtNewSimdCreateBroadcastNode(type, gtNewIconNode(actualMaxVal), simdTargetBaseJitType, simdSize); + default: + unreached(); + } + break; } - // we will be using the input value twice - GenTree* fixupValDup = fgMakeMultiUse(&fixupVal); + case CORINFO_TYPE_DOUBLE: + { + switch (simdTargetBaseJitType) + { + case CORINFO_TYPE_LONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; + break; + } - // compare with max value of integer/long - fixupVal = gtNewSimdCmpOpNode(GT_GE, type, fixupVal, maxVal, simdSourceBaseJitType, simdSize); + case CORINFO_TYPE_ULONG: + { + hwIntrinsicID = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar + : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; + break; + } - // cast it - GenTree* castNode = gtNewSimdHWIntrinsicNode(type, fixupValDup, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); + } + break; + } - // use the fixupVal mask with input value and max value to blend - return gtNewSimdCndSelNode(type, fixupVal, maxValDup, castNode, simdTargetBaseJitType, simdSize); - } - else - { - return gtNewSimdHWIntrinsicNode(type, fixupVal, hwIntrinsicID, simdSourceBaseJitType, simdSize); + default: + unreached(); } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + + assert(hwIntrinsicID != NI_Illegal); + return gtNewSimdHWIntrinsicNode(type, op1, hwIntrinsicID, simdSourceBaseJitType, simdSize); } -#endif // TARGET_XARCH GenTree* Compiler::gtNewSimdCmpOpNode( genTreeOps op, var_types type, GenTree* op1, GenTree* op2, CorInfoType simdBaseJitType, unsigned simdSize) diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index 8e3288f75d7090..98342739cb4e0d 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -621,28 +621,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } case NI_Vector64_ConvertToInt32: + case NI_Vector64_ConvertToInt32Native: case NI_Vector128_ConvertToInt32: + case NI_Vector128_ConvertToInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - op1 = impSIMDPopStack(); - retNode = - gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } case NI_Vector64_ConvertToInt64: + case NI_Vector64_ConvertToInt64Native: case NI_Vector128_ConvertToInt64: + case NI_Vector128_ConvertToInt64Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); break; } @@ -658,28 +658,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } case NI_Vector64_ConvertToUInt32: + case NI_Vector64_ConvertToUInt32Native: case NI_Vector128_ConvertToUInt32: + case NI_Vector128_ConvertToUInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, simdBaseJitType, - simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); break; } case NI_Vector64_ConvertToUInt64: + case NI_Vector64_ConvertToUInt64Native: case NI_Vector128_ConvertToUInt64: + case NI_Vector128_ConvertToUInt64Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - intrinsic = (simdSize == 8) ? NI_AdvSimd_Arm64_ConvertToUInt64RoundToZeroScalar - : NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero; - op1 = impSIMDPopStack(); - retNode = gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); break; } diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index f1a48b2d28127c..06feb2816de5ce 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -37,10 +37,14 @@ HARDWARE_INTRINSIC(Vector64, Ceiling, HARDWARE_INTRINSIC(Vector64, ConditionalSelect, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt32Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, ConvertToUInt64Native, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, Create, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, CreateScalar, 8, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) @@ -146,10 +150,14 @@ HARDWARE_INTRINSIC(Vector128, Ceiling, HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 07bc2e4838c88c..d3f7c575a86667 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -56,10 +56,14 @@ HARDWARE_INTRINSIC(Vector128, Ceiling, HARDWARE_INTRINSIC(Vector128, ConditionalSelect, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, ConvertToDouble, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToSingle, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToUInt32, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt32Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, ConvertToUInt64Native, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, Create, 16, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) @@ -162,10 +166,14 @@ HARDWARE_INTRINSIC(Vector256, Ceiling, HARDWARE_INTRINSIC(Vector256, ConditionalSelect, 32, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) +HARDWARE_INTRINSIC(Vector256, ConvertToInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt32Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, ConvertToUInt64Native, 32, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, Create, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateScalar, 32, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible) @@ -274,11 +282,15 @@ HARDWARE_INTRINSIC(Vector512, CreateScalar, HARDWARE_INTRINSIC(Vector512, CreateScalarUnsafe, 64, 1, true, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(Vector512, CreateSequence, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, ConvertToDouble, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToSingle, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToUInt32, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt32Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, ConvertToUInt64, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, ConvertToUInt64Native, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, Divide, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, Equals, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) HARDWARE_INTRINSIC(Vector512, EqualsAll, 64, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index fc3c01e4c31d29..553e1bdf78366a 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -1440,58 +1440,59 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - case NI_Vector128_ConvertToInt64: - case NI_Vector256_ConvertToInt64: - case NI_Vector512_ConvertToInt64: + case NI_Vector128_ConvertToInt32: + case NI_Vector256_ConvertToInt32: + case NI_Vector512_ConvertToInt32: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - if (IsBaselineVector512IsaSupportedOpportunistically()) + assert(simdBaseType == TYP_FLOAT); + + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToUInt32: - case NI_Vector256_ConvertToUInt32: - case NI_Vector512_ConvertToUInt32: + case NI_Vector128_ConvertToInt32Native: + case NI_Vector256_ConvertToInt32Native: + case NI_Vector512_ConvertToInt32Native: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - if (IsBaselineVector512IsaSupportedOpportunistically()) - { - op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); - } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); break; } - case NI_Vector128_ConvertToUInt64: - case NI_Vector256_ConvertToUInt64: - case NI_Vector512_ConvertToUInt64: + case NI_Vector128_ConvertToInt64: + case NI_Vector256_ConvertToInt64: + case NI_Vector512_ConvertToInt64: { assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } - case NI_Vector128_ConvertToInt32: - case NI_Vector256_ConvertToInt32: - case NI_Vector512_ConvertToInt32: + case NI_Vector128_ConvertToInt64Native: + case NI_Vector256_ConvertToInt64Native: + case NI_Vector512_ConvertToInt64Native: { assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + assert(simdBaseType == TYP_DOUBLE); + + if (IsBaselineVector512IsaSupportedOpportunistically()) { op1 = impSIMDPopStack(); - retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } break; } @@ -1545,6 +1546,65 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_ConvertToUInt32: + case NI_Vector256_ConvertToUInt32: + case NI_Vector512_ConvertToUInt32: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt32Native: + case NI_Vector256_ConvertToUInt32Native: + case NI_Vector512_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64: + case NI_Vector256_ConvertToUInt64: + case NI_Vector512_ConvertToUInt64: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_ConvertToUInt64Native: + case NI_Vector256_ConvertToUInt64Native: + case NI_Vector512_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + + if (IsBaselineVector512IsaSupportedOpportunistically()) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Create: case NI_Vector256_Create: case NI_Vector512_Create: diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 0ec0d6b9afd3e8..4dc64523217230 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -5164,12 +5164,16 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, assert(sig->sigInst.classInstCount == 0); var_types retType = JITtype2varType(sig->retType); - assert(varTypeIsArithmetic(retType)); + + if (!varTypeIsArithmetic(retType)) + { + assert((intrinsic == NI_PRIMITIVE_ConvertToInteger) || (intrinsic == NI_PRIMITIVE_ConvertToIntegerNative)); + return nullptr; + } NamedIntrinsic hwintrinsic = NI_Illegal; CORINFO_ARG_LIST_HANDLE args = sig->args; - assert((sig->numArgs == 1) || (sig->numArgs == 2)); CORINFO_CLASS_HANDLE op1ClsHnd; @@ -5180,6 +5184,113 @@ GenTree* Compiler::impPrimitiveNamedIntrinsic(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_PRIMITIVE_ConvertToInteger: + case NI_PRIMITIVE_ConvertToIntegerNative: + { + assert(sig->sigInst.methInstCount == 1); + assert(varTypeIsFloating(baseType)); + + var_types tgtType = JitType2PreciseVarType(sig->retType); + retType = genActualType(retType); + bool uns = varTypeIsUnsigned(tgtType) && !varTypeIsSmall(tgtType); + + GenTree* res = nullptr; + GenTree* op1 = nullptr; + +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + if ((intrinsic == NI_PRIMITIVE_ConvertToIntegerNative) && IsBaselineSimdIsaSupported()) + { + NamedIntrinsic hwIntrinsicId = NI_Illegal; + + if (retType == TYP_INT) + { + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_ConvertToInt32WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_ConvertToUInt32WithTruncation; + } + } + } +#if defined(TARGET_AMD64) + else + { + assert(retType == TYP_LONG); + + if (baseType == TYP_FLOAT) + { + if (!uns) + { + hwIntrinsicId = NI_SSE_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + else + { + assert(baseType == TYP_DOUBLE); + + if (!uns) + { + hwIntrinsicId = NI_SSE2_X64_ConvertToInt64WithTruncation; + } + else if (IsBaselineVector512IsaSupportedOpportunistically()) + { + hwIntrinsicId = NI_AVX512F_X64_ConvertToUInt64WithTruncation; + } + } + } +#endif // TARGET_AMD64 + + if (hwIntrinsicId != NI_Illegal) + { + op1 = impPopStack().val; + res = gtNewSimdHWIntrinsicNode(retType, op1, hwIntrinsicId, baseJitType, 16); + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + return res; + } + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + + op1 = impPopStack().val; + + if (varTypeIsSmall(tgtType)) + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, retType); + res = gtFoldExpr(res); + res = gtNewCastNode(TYP_INT, res, /* uns */ false, tgtType); + } + else + { + res = gtNewCastNodeL(retType, op1, /* uns */ false, tgtType); + } + + return gtFoldExpr(res); + } + case NI_PRIMITIVE_Crc32C: { assert(sig->numArgs == 2); @@ -10072,6 +10183,19 @@ NamedIntrinsic Compiler::lookupPrimitiveFloatNamedIntrinsic(CORINFO_METHOD_HANDL { result = NI_System_Math_Ceiling; } + else if (strncmp(methodName, "ConvertToInteger", 16) == 0) + { + methodName += 16; + + if (methodName[0] == '\0') + { + result = NI_PRIMITIVE_ConvertToInteger; + } + else if (strcmp(methodName, "Native") == 0) + { + result = NI_PRIMITIVE_ConvertToIntegerNative; + } + } else if (strncmp(methodName, "Cos", 3) == 0) { methodName += 3; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index b3eb292677d809..67eec1059e82e8 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -227,6 +227,8 @@ enum NamedIntrinsic : unsigned short NI_PRIMITIVE_START, + NI_PRIMITIVE_ConvertToInteger, + NI_PRIMITIVE_ConvertToIntegerNative, NI_PRIMITIVE_Crc32C, NI_PRIMITIVE_LeadingZeroCount, NI_PRIMITIVE_Log2, diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 9ffd3b7b011d55..c9b227440d4e5d 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -523,20 +523,23 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return nullptr; } - case NI_VectorT_ConvertToInt64: - case NI_VectorT_ConvertToUInt32: - case NI_VectorT_ConvertToUInt64: + case NI_VectorT_ConvertToInt32: { - if (IsBaselineVector512IsaSupportedOpportunistically()) + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { break; } return nullptr; } - case NI_VectorT_ConvertToInt32: + case NI_VectorT_ConvertToInt64: + case NI_VectorT_ConvertToInt64Native: + case NI_VectorT_ConvertToUInt32: + case NI_VectorT_ConvertToUInt32Native: + case NI_VectorT_ConvertToUInt64: + case NI_VectorT_ConvertToUInt64Native: { - if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (IsBaselineVector512IsaSupportedOpportunistically()) { break; } @@ -1175,34 +1178,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #if defined(TARGET_XARCH) - - case NI_VectorT_ConvertToInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt32: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToUInt64: - { - assert(sig->numArgs == 1); - assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); - } - - case NI_VectorT_ConvertToInt32: - { - assert(simdBaseType == TYP_FLOAT); - return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); - } - case NI_VectorT_ConvertToDouble: { assert(sig->numArgs == 1); @@ -1273,43 +1248,71 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, simdSize); } + case NI_VectorT_ConvertToSingle: + { + assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); + return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, + simdSize); + } +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + case NI_VectorT_ConvertToInt32: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToInt32RoundToZero, simdBaseJitType, - simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToInt32Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_INT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } - case NI_VectorT_ConvertToSingle: + case NI_VectorT_ConvertToInt64Native: { - assert((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToSingle, simdBaseJitType, - simdSize); + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_LONG, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt32: { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_FLOAT); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt32Native: + { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_FLOAT); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_ConvertToUInt32RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_UINT, simdBaseJitType, simdSize); } case NI_VectorT_ConvertToUInt64: { + assert(sig->numArgs == 1); assert(simdBaseType == TYP_DOUBLE); - return gtNewSimdHWIntrinsicNode(retType, op1, NI_AdvSimd_Arm64_ConvertToUInt64RoundToZero, - simdBaseJitType, simdSize); + return gtNewSimdCvtNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); + } + + case NI_VectorT_ConvertToUInt64Native: + { + assert(sig->numArgs == 1); + assert(simdBaseType == TYP_DOUBLE); + return gtNewSimdCvtNativeNode(retType, op1, CORINFO_TYPE_ULONG, simdBaseJitType, simdSize); } -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 default: { diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index cb8d702be5e71f..911306e712409c 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -224,10 +224,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 5cf07eff0c84ae..dd1d6374bc248f 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -224,10 +224,14 @@ SIMD_AS_HWINTRINSIC_ID(VectorT, Ceiling, SIMD_AS_HWINTRINSIC_ID(VectorT, ConditionalSelect, 3, {NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect, NI_VectorT_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToDouble, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToDouble, NI_VectorT_ConvertToDouble, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToSingle, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToSingle, NI_VectorT_ConvertToSingle, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt32Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt32Native, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT, ConvertToUInt64Native, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_ConvertToUInt64Native}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT, CreateBroadcast, ".ctor", 2, {NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast, NI_VectorT_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, CreateSequence, 2, {NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence, NI_VectorT_CreateSequence}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(VectorT, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_VectorT_Divide, NI_VectorT_Divide}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/Common/tests/System/GenericMathHelpers.cs b/src/libraries/Common/tests/System/GenericMathHelpers.cs index 277580dc5920d8..a02f8a4e162a6e 100644 --- a/src/libraries/Common/tests/System/GenericMathHelpers.cs +++ b/src/libraries/Common/tests/System/GenericMathHelpers.cs @@ -151,6 +151,12 @@ public static class FloatingPointHelper { public static TSelf Ceiling(TSelf x) => TSelf.Ceiling(x); + public static TInteger ConvertToInteger(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToInteger(x); + + public static TInteger ConvertToIntegerNative(TSelf x) + where TInteger : IBinaryInteger => TSelf.ConvertToIntegerNative(x); + public static TSelf Floor(TSelf x) => TSelf.Floor(x); public static TSelf Round(TSelf x) => TSelf.Round(x); diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 8bf4cb6c534827..531a379cf06e99 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -235,14 +235,20 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToDouble(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt32(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt32Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToInt64(System.Numerics.Vector value) { throw null; } + public static System.Numerics.Vector ConvertToInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToSingle(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt32(System.Numerics.Vector value) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt32Native(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector ConvertToUInt64(System.Numerics.Vector value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Numerics.Vector ConvertToUInt64Native(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector CreateSequence(T start, T step) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Divide(System.Numerics.Vector left, T right) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index f2d89445f834ba..189e54dcc1ef74 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1117,6 +1117,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IFloatingPoint // + /// + public static TInteger ConvertToInteger(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(decimal value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// int IFloatingPoint.GetExponentByteCount() => sizeof(sbyte); diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 71d73546bc1364..04e8269c78f464 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -655,6 +655,16 @@ public static bool IsPow2(double value) [Intrinsic] public static double Ceiling(double x) => Math.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(double value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(double value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// [Intrinsic] public static double Floor(double x) => Math.Floor(x); diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index adc7df07932f7f..d4459c5162366f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -1314,6 +1314,14 @@ public static bool IsPow2(Half value) /// public static Half Ceiling(Half x) => (Half)MathF.Ceiling((float)x); + /// + public static TInteger ConvertToInteger(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(Half value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static Half Floor(Half x) => (Half)MathF.Floor((float)x); diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs index e36c76007bbdfd..9c92a14f0e75c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/IFloatingPoint.cs @@ -16,6 +16,26 @@ public interface IFloatingPoint /// The ceiling of . static virtual TSelf Ceiling(TSelf x) => TSelf.Round(x, digits: 0, MidpointRounding.ToPositiveInfinity); + /// Converts a value to a specified integer type using saturation on overflow + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToInteger(TSelf value) + where TInteger : IBinaryInteger + { + return TInteger.CreateSaturating(value); + } + + /// Converts a value to a specified integer type using platform specific behavior on overflow. + /// The integer type to which is converted. + /// The value to be converted. + /// An instance of created from . + static virtual TInteger ConvertToIntegerNative(TSelf value) + where TInteger : IBinaryInteger + { + return TSelf.ConvertToInteger(value); + } + /// Computes the floor of a value. /// The value whose floor is to be computed. /// The floor of . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 5d8bc58bbe26ee..0e968e6fca8f34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -325,7 +325,7 @@ public static Vector ConvertToDouble(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -342,7 +342,13 @@ public static Vector ConvertToInt32(Vector value) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt32Native(Vector value) => ConvertToInt32(value); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -359,6 +365,12 @@ public static Vector ConvertToInt64(Vector value) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + public static Vector ConvertToInt64Native(Vector value) => ConvertToInt64(value); + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -396,7 +408,7 @@ public static Vector ConvertToSingle(Vector value) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -414,7 +426,14 @@ public static Vector ConvertToUInt32(Vector value) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt32Native(Vector value) => ConvertToUInt32(value); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -432,6 +451,13 @@ public static Vector ConvertToUInt64(Vector value) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + public static Vector ConvertToUInt64Native(Vector value) => ConvertToUInt64(value); + /// Creates a new instance where the elements begin at a specified value and which are spaced apart according to another specified value. /// The type of the elements in the vector. /// The value that element 0 will be initialized to. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index 37c39bbc029a24..b314daec02a93c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -992,6 +992,14 @@ static NFloat IBinaryNumber.AllBitsSet /// public static NFloat Ceiling(NFloat x) => new NFloat(NativeType.Ceiling(x._value)); + /// + public static TInteger ConvertToInteger(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + public static TInteger ConvertToIntegerNative(NFloat value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// public static NFloat Floor(NFloat x) => new NFloat(NativeType.Floor(x._value)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 3e24e591a32c12..4080b06c92b77b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -468,7 +468,7 @@ public static unsafe Vector128 ConvertToDouble(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -481,7 +481,20 @@ public static unsafe Vector128 ConvertToInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt32Native(vector._lower), + Vector64.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -494,6 +507,19 @@ public static unsafe Vector128 ConvertToInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToInt64Native(vector._lower), + Vector64.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -564,7 +590,7 @@ static Vector128 SoftwareFallback(Vector128 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -578,7 +604,21 @@ public static unsafe Vector128 ConvertToUInt32(Vector128 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt32Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt32Native(vector._lower), + Vector64.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -592,6 +632,20 @@ public static unsafe Vector128 ConvertToUInt64(Vector128 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector128 ConvertToUInt64Native(Vector128 vector) + { + return Create( + Vector64.ConvertToUInt64Native(vector._lower), + Vector64.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 1347a082afab97..4d174eef197544 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -386,7 +386,7 @@ public static Vector256 ConvertToDouble(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -399,7 +399,20 @@ public static Vector256 ConvertToInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt32Native(vector._lower), + Vector128.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -412,6 +425,19 @@ public static Vector256 ConvertToInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToInt64Native(vector._lower), + Vector128.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -472,7 +498,7 @@ public static Vector256 ConvertToSingle(Vector256 vector) } } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -486,7 +512,21 @@ public static Vector256 ConvertToUInt32(Vector256 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt32Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt32Native(vector._lower), + Vector128.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -500,6 +540,20 @@ public static Vector256 ConvertToUInt64(Vector256 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 ConvertToUInt64Native(Vector256 vector) + { + return Create( + Vector128.ConvertToUInt64Native(vector._lower), + Vector128.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index edb84585a987de..d63f12afb64d9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -348,7 +348,7 @@ public static Vector512 ConvertToDouble(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -361,7 +361,20 @@ public static Vector512 ConvertToInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt32Native(vector._lower), + Vector256.ConvertToInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -374,6 +387,19 @@ public static Vector512 ConvertToInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToInt64Native(vector._lower), + Vector256.ConvertToInt64Native(vector._upper) + ); + } + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -401,7 +427,7 @@ public static Vector512 ConvertToSingle(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -415,7 +441,21 @@ public static Vector512 ConvertToUInt32(Vector512 vector) ); } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt32Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt32Native(vector._lower), + Vector256.ConvertToUInt32Native(vector._upper) + ); + } + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -429,6 +469,20 @@ public static Vector512 ConvertToUInt64(Vector512 vector) ); } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 ConvertToUInt64Native(Vector512 vector) + { + return Create( + Vector256.ConvertToUInt64Native(vector._lower), + Vector256.ConvertToUInt64Native(vector._upper) + ); + } + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 50e9f697c94f44..04c5e0672a9d1b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -339,7 +339,7 @@ public static unsafe Vector64 ConvertToDouble(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -357,7 +357,14 @@ public static unsafe Vector64 ConvertToInt32(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt32Native(Vector64 vector) => ConvertToInt32(vector); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -375,6 +382,13 @@ public static unsafe Vector64 ConvertToInt64(Vector64 vector) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToInt64Native(Vector64 vector) => ConvertToInt64(vector); + /// Converts a to a . /// The vector to convert. /// The converted vector. @@ -412,7 +426,7 @@ public static unsafe Vector64 ConvertToSingle(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -431,7 +445,15 @@ public static unsafe Vector64 ConvertToUInt32(Vector64 vector) return result; } - /// Converts a to a . + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt32Native(Vector64 vector) => ConvertToUInt32(vector); + + /// Converts a to a using saturation on overflow. /// The vector to convert. /// The converted vector. [Intrinsic] @@ -450,6 +472,14 @@ public static unsafe Vector64 ConvertToUInt64(Vector64 vector) return result; } + /// Converts a to a using platform specific behavior on overflow. + /// The vector to convert. + /// The converted vector. + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector64 ConvertToUInt64Native(Vector64 vector) => ConvertToUInt64(vector); + /// Copies a to a given array. /// The type of the elements in the vector. /// The vector to be copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 9cc7c6b56c0adf..8a8a38aa2c0b48 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -650,6 +650,16 @@ public static bool IsPow2(float value) [Intrinsic] public static float Ceiling(float x) => MathF.Ceiling(x); + /// + [Intrinsic] + public static TInteger ConvertToInteger(float value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + + /// + [Intrinsic] + public static TInteger ConvertToIntegerNative(float value) + where TInteger : IBinaryInteger => TInteger.CreateSaturating(value); + /// [Intrinsic] public static float Floor(float x) => MathF.Floor(x); diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index c0fe858d94c608..3b718d224417c7 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1341,6 +1341,8 @@ public static void Free(void* ptr) { } public static System.Runtime.InteropServices.NFloat Clamp(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat min, System.Runtime.InteropServices.NFloat max) { throw null; } public int CompareTo(object? obj) { throw null; } public int CompareTo(System.Runtime.InteropServices.NFloat other) { throw null; } + public static TInteger ConvertToInteger(System.Runtime.InteropServices.NFloat value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(System.Runtime.InteropServices.NFloat value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static System.Runtime.InteropServices.NFloat CopySign(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat sign) { throw null; } public static System.Runtime.InteropServices.NFloat Cos(System.Runtime.InteropServices.NFloat x) { throw null; } public static System.Runtime.InteropServices.NFloat Cosh(System.Runtime.InteropServices.NFloat x) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index c34725ba0bae50..bd7871cdf99065 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -49,14 +49,20 @@ public static partial class Vector128 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ConvertToInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32(System.Runtime.Intrinsics.Vector128 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) { } @@ -384,14 +390,20 @@ public static partial class Vector256 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ConvertToInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32(System.Runtime.Intrinsics.Vector256 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) { } @@ -719,14 +731,20 @@ public static partial class Vector512 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToDouble(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ConvertToInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToSingle(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32(System.Runtime.Intrinsics.Vector512 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector512 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination, int startIndex) { } @@ -1050,14 +1068,20 @@ public static partial class Vector64 [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ConvertToInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32(System.Runtime.Intrinsics.Vector64 vector) { throw null; } [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + [System.CLSCompliantAttribute(false)] + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64Native(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination) { } public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) { } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 0ebed660f33689..95cf6d16b66171 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -5,6 +5,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4872,5 +4873,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector128 actualResult = Vector128.Log2(Vector128.Create(value)); AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2), Vector128.ConvertToInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(int.MaxValue), Vector128.ConvertToInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector128.Create(int.MaxValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MaxValue))); + } + Assert.Equal(Vector128.Create(int.MinValue), Vector128.ConvertToInt32Native(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2), Vector128.ConvertToInt32Native(Vector128.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2L), Vector128.ConvertToInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(long.MaxValue), Vector128.ConvertToInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector128.Create(long.MaxValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MaxValue))); + } + + Assert.Equal(Vector128.Create(long.MinValue), Vector128.ConvertToInt64Native(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2L), Vector128.ConvertToInt64Native(Vector128.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector128.Create(uint.MinValue), Vector128.ConvertToUInt32(Vector128.Create(float.MinValue))); + Assert.Equal(Vector128.Create(2u), Vector128.ConvertToUInt32(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector128.Create(uint.MinValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MinValue))); + } + + Assert.Equal(Vector128.Create(2u), Vector128.ConvertToUInt32Native(Vector128.Create(2.6f))); + Assert.Equal(Vector128.Create(uint.MaxValue), Vector128.ConvertToUInt32Native(Vector128.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector128.Create(ulong.MinValue), Vector128.ConvertToUInt64(Vector128.Create(double.MinValue))); + Assert.Equal(Vector128.Create(2UL), Vector128.ConvertToUInt64(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64(Vector128.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector128.Create(ulong.MinValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MinValue))); + } + + Assert.Equal(Vector128.Create(2UL), Vector128.ConvertToUInt64Native(Vector128.Create(2.6))); + Assert.Equal(Vector128.Create(ulong.MaxValue), Vector128.ConvertToUInt64Native(Vector128.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index d658ca08b17b32..a5559d43c81505 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5887,5 +5888,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector256 actualResult = Vector256.Log2(Vector256.Create(value)); AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2), Vector256.ConvertToInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(int.MaxValue), Vector256.ConvertToInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector256.Create(int.MaxValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MaxValue))); + } + Assert.Equal(Vector256.Create(int.MinValue), Vector256.ConvertToInt32Native(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2), Vector256.ConvertToInt32Native(Vector256.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2L), Vector256.ConvertToInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(long.MaxValue), Vector256.ConvertToInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector256.Create(long.MaxValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MaxValue))); + } + + Assert.Equal(Vector256.Create(long.MinValue), Vector256.ConvertToInt64Native(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2L), Vector256.ConvertToInt64Native(Vector256.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector256.Create(uint.MinValue), Vector256.ConvertToUInt32(Vector256.Create(float.MinValue))); + Assert.Equal(Vector256.Create(2u), Vector256.ConvertToUInt32(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector256.Create(uint.MinValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MinValue))); + } + + Assert.Equal(Vector256.Create(2u), Vector256.ConvertToUInt32Native(Vector256.Create(2.6f))); + Assert.Equal(Vector256.Create(uint.MaxValue), Vector256.ConvertToUInt32Native(Vector256.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector256.Create(ulong.MinValue), Vector256.ConvertToUInt64(Vector256.Create(double.MinValue))); + Assert.Equal(Vector256.Create(2UL), Vector256.ConvertToUInt64(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64(Vector256.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector256.Create(ulong.MinValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MinValue))); + } + + Assert.Equal(Vector256.Create(2UL), Vector256.ConvertToUInt64Native(Vector256.Create(2.6))); + Assert.Equal(Vector256.Create(ulong.MaxValue), Vector256.ConvertToUInt64Native(Vector256.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index 4b4f9e2d4692aa..c01f88facbf574 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -5320,5 +5321,108 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector512 actualResult = Vector512.Log2(Vector512.Create(value)); AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2), Vector512.ConvertToInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(int.MaxValue), Vector512.ConvertToInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Sse2.IsSupported) + { + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MaxValue))); + } + else + { + Assert.Equal(Vector512.Create(int.MaxValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MaxValue))); + } + Assert.Equal(Vector512.Create(int.MinValue), Vector512.ConvertToInt32Native(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2), Vector512.ConvertToInt32Native(Vector512.Create(2.6f))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2L), Vector512.ConvertToInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(long.MaxValue), Vector512.ConvertToInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MaxValue))); + } + else + { + Assert.Equal(Vector512.Create(long.MaxValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MaxValue))); + } + + Assert.Equal(Vector512.Create(long.MinValue), Vector512.ConvertToInt64Native(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2L), Vector512.ConvertToInt64Native(Vector512.Create(2.6))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector512.Create(uint.MinValue), Vector512.ConvertToUInt32(Vector512.Create(float.MinValue))); + Assert.Equal(Vector512.Create(2u), Vector512.ConvertToUInt32(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512F.VL.IsSupported) + { + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MinValue))); + } + else + { + Assert.Equal(Vector512.Create(uint.MinValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MinValue))); + } + + Assert.Equal(Vector512.Create(2u), Vector512.ConvertToUInt32Native(Vector512.Create(2.6f))); + Assert.Equal(Vector512.Create(uint.MaxValue), Vector512.ConvertToUInt32Native(Vector512.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector512.Create(ulong.MinValue), Vector512.ConvertToUInt64(Vector512.Create(double.MinValue))); + Assert.Equal(Vector512.Create(2UL), Vector512.ConvertToUInt64(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64(Vector512.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + if (Vector128.IsHardwareAccelerated && Avx512DQ.VL.IsSupported) + { + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MinValue))); + } + else + { + Assert.Equal(Vector512.Create(ulong.MinValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MinValue))); + } + + Assert.Equal(Vector512.Create(2UL), Vector512.ConvertToUInt64Native(Vector512.Create(2.6))); + Assert.Equal(Vector512.Create(ulong.MaxValue), Vector512.ConvertToUInt64Native(Vector512.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index 69f37520ad735a..3c2d8064681fe1 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -4287,5 +4288,77 @@ public void Log2SingleTest(float value, float expectedResult, float variance) Vector64 actualResult = Vector64.Log2(Vector64.Create(value)); AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Create(variance)); } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32Test() + { + Assert.Equal(Vector64.Create(int.MinValue), Vector64.ConvertToInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2), Vector64.ConvertToInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(int.MaxValue), Vector64.ConvertToInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt32NativeTest() + { + Assert.Equal(Vector64.Create(int.MinValue), Vector64.ConvertToInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2), Vector64.ConvertToInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(int.MaxValue), Vector64.ConvertToInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64Test() + { + Assert.Equal(Vector64.Create(long.MinValue), Vector64.ConvertToInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2L), Vector64.ConvertToInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(long.MaxValue), Vector64.ConvertToInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToInt64NativeTest() + { + Assert.Equal(Vector64.Create(long.MinValue), Vector64.ConvertToInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2L), Vector64.ConvertToInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(long.MaxValue), Vector64.ConvertToInt64Native(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32Test() + { + Assert.Equal(Vector64.Create(uint.MinValue), Vector64.ConvertToUInt32(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2u), Vector64.ConvertToUInt32(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(uint.MaxValue), Vector64.ConvertToUInt32(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt32NativeTest() + { + Assert.Equal(Vector64.Create(uint.MinValue), Vector64.ConvertToUInt32Native(Vector64.Create(float.MinValue))); + Assert.Equal(Vector64.Create(2u), Vector64.ConvertToUInt32Native(Vector64.Create(2.6f))); + Assert.Equal(Vector64.Create(uint.MaxValue), Vector64.ConvertToUInt32Native(Vector64.Create(float.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64Test() + { + Assert.Equal(Vector64.Create(ulong.MinValue), Vector64.ConvertToUInt64(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2UL), Vector64.ConvertToUInt64(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(ulong.MaxValue), Vector64.ConvertToUInt64(Vector64.Create(double.MaxValue))); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public void ConvertToUInt64NativeTest() + { + Assert.Equal(Vector64.Create(ulong.MinValue), Vector64.ConvertToUInt64Native(Vector64.Create(double.MinValue))); + Assert.Equal(Vector64.Create(2UL), Vector64.ConvertToUInt64Native(Vector64.Create(2.6))); + Assert.Equal(Vector64.Create(ulong.MaxValue), Vector64.ConvertToUInt64Native(Vector64.Create(double.MaxValue))); + } } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 14575b820c33ab..a3f2a4b07e2f48 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4,6 +4,8 @@ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ +using System.Numerics; + namespace Microsoft.Win32.SafeHandles { public abstract partial class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle @@ -1985,6 +1987,8 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S public static int Compare(decimal d1, decimal d2) { throw null; } public int CompareTo(decimal value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(decimal value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static decimal CopySign(decimal value, decimal sign) { throw null; } public static decimal CreateChecked(TOther value) where TOther : System.Numerics.INumberBase { throw null; } public static decimal CreateSaturating(TOther value) where TOther : System.Numerics.INumberBase { throw null; } @@ -2259,6 +2263,8 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double Clamp(double value, double min, double max) { throw null; } public int CompareTo(double value) { throw null; } public int CompareTo(object? value) { throw null; } + public static TInteger ConvertToInteger(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static double CopySign(double value, double sign) { throw null; } public static double Cos(double x) { throw null; } public static double Cosh(double x) { throw null; } @@ -2881,6 +2887,8 @@ public enum GCNotificationStatus public static System.Half Clamp(System.Half value, System.Half min, System.Half max) { throw null; } public int CompareTo(System.Half other) { throw null; } public int CompareTo(object? obj) { throw null; } + public static TInteger ConvertToInteger(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static System.Half CopySign(System.Half value, System.Half sign) { throw null; } public static System.Half Cos(System.Half x) { throw null; } public static System.Half Cosh(System.Half x) { throw null; } @@ -4998,6 +5006,8 @@ public SerializableAttribute() { } public static float Clamp(float value, float min, float max) { throw null; } public int CompareTo(object? value) { throw null; } public int CompareTo(float value) { throw null; } + public static TInteger ConvertToInteger(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + public static TInteger ConvertToIntegerNative(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } public static float CopySign(float value, float sign) { throw null; } public static float Cos(float x) { throw null; } public static float Cosh(float x) { throw null; } @@ -10809,6 +10819,8 @@ public partial interface IFloatingPointIeee754 : System.IComparable, Syst public partial interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint? { static virtual TSelf Ceiling(TSelf x) { throw null; } + static virtual TInteger ConvertToInteger(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } + static virtual TInteger ConvertToIntegerNative(TSelf value) where TInteger : System.Numerics.IBinaryInteger { throw null; } static virtual TSelf Floor(TSelf x) { throw null; } int GetExponentByteCount(); int GetExponentShortestBitLength(); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs index 05e71be7b325c2..d829eb1199d4d7 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(double.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(UInt128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(double.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() { @@ -1055,7 +1222,7 @@ public static void CreateCheckedFromDecimalTest() AssertBitwiseEqual(-0.0, NumberBaseHelper.CreateChecked(-0.0m)); AssertBitwiseEqual(+0.0, NumberBaseHelper.CreateChecked(+0.0m)); AssertBitwiseEqual(+1.0, NumberBaseHelper.CreateChecked(+1.0m)); - AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); + AssertBitwiseEqual(+79228162514264337593543950335.0, NumberBaseHelper.CreateChecked(decimal.MaxValue)); } [Fact] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs index a6637de7f7e2a3..21a4ba2cd77a11 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.GenericMath.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; using Xunit; namespace System.Tests @@ -356,6 +357,172 @@ public static void op_InequalityTest() // IFloatingPoint // + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + + // Unsigned Values + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToInteger(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToInteger(2.6f)); + + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToInteger(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToInteger(float.MaxValue)); + } + + [Fact] + [SkipOnMono("https://github.com/dotnet/runtime/issues/100368")] + public static void ConvertToIntegerNativeTest() + { + // Signed Values + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(Int128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to int is natively supported and returns 0x8000_0000 + // * Conversion to long is natively supported on 64-bit and returns 0x8000_0000_0000_0000 + + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(0, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + if (Environment.Is64BitProcess) + { + Assert.Equal(long.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + } + else + { + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(int.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(long.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(-1, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(Int128.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + + // Unsigned Values + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + if (Avx512F.IsSupported) + { + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + + if (Environment.Is64BitProcess && Avx512F.IsSupported) + { + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + else + { + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + } + else + { + Assert.Equal(uint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ulong.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(nuint.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + } + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + Assert.Equal(UInt128.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MinValue)); + + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + Assert.Equal(2u, FloatingPointHelper.ConvertToIntegerNative(2.6f)); + + if (Sse2.IsSupported) + { + // On Xarch: + // * Conversion to uint is natively supported w/ Avx512 and returns 0xFFFF_FFFF + // * Conversion to ulong is natively supported on 64-bit w/ Avx512 and returns 0xFFFF_FFFF_FFFF_FFFF + + Assert.Equal(byte.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MinValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + else + { + Assert.Equal(byte.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ushort.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + Assert.Equal(uint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(ulong.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(new UInt128(0xFFFF_FF00_0000_0000, 0x0000_0000_0000_0000), FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + Assert.Equal(nuint.MaxValue, FloatingPointHelper.ConvertToIntegerNative(float.MaxValue)); + } + [Fact] public static void GetExponentByteCountTest() {