From 83433ff3a8ce73725cea8bcc614a9ed44fbfdc89 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 27 Jan 2023 15:48:07 -0800 Subject: [PATCH 01/30] Allow Quaternion and Plane to be imported as TYP_SIMD16 --- src/coreclr/jit/compiler.h | 76 +++++++++++++++++++++++++++++++++++--- src/coreclr/jit/simd.cpp | 32 ++++++++++++++++ 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3c74e06a534a8..b5ce58d69aa9d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -8411,6 +8411,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CORINFO_CLASS_HANDLE SIMDNIntHandle; CORINFO_CLASS_HANDLE SIMDNUIntHandle; + CORINFO_CLASS_HANDLE SIMDPlaneHandle; + CORINFO_CLASS_HANDLE SIMDQuaternionHandle; CORINFO_CLASS_HANDLE SIMDVector2Handle; CORINFO_CLASS_HANDLE SIMDVector3Handle; CORINFO_CLASS_HANDLE SIMDVector4Handle; @@ -8488,23 +8490,54 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX switch (simdType) { case TYP_SIMD8: + { return m_simdHandleCache->SIMDVector2Handle; + } + case TYP_SIMD12: + { return m_simdHandleCache->SIMDVector3Handle; + } + case TYP_SIMD16: - if ((getSIMDVectorType() == TYP_SIMD32) || - (m_simdHandleCache->SIMDVector4Handle != NO_CLASS_HANDLE)) + { + // We order the checks roughly by expected hit count so early exits are possible + + if (simdBaseJitType != CORINFO_TYPE_FLOAT) + { + // We could be Vector, so handle below + assert(getSIMDVectorType() == TYP_SIMD16); + break; + } + + if (m_simdHandleCache->SIMDVector4Handle != NO_CLASS_HANDLE) { return m_simdHandleCache->SIMDVector4Handle; } - break; + + if (m_simdHandleCache->SIMDQuaternionHandle != NO_CLASS_HANDLE) + { + return m_simdHandleCache->SIMDQuaternionHandle; + } + + if (m_simdHandleCache->SIMDPlaneHandle != NO_CLASS_HANDLE) + { + return m_simdHandleCache->SIMDPlaneHandle; + } + + return NO_CLASS_HANDLE; + } + case TYP_SIMD32: break; + default: unreached(); } } + assert(emitTypeSize(simdType) <= largestEnregisterableStructSize()); + switch (simdBaseJitType) { case CORINFO_TYPE_FLOAT: @@ -8534,6 +8567,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX default: assert(!"Didn't find a class handle for simdType"); } + return NO_CLASS_HANDLE; } @@ -8611,9 +8645,39 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // actually be declared as having fields. bool isOpaqueSIMDType(CORINFO_CLASS_HANDLE structHandle) const { - return ((m_simdHandleCache != nullptr) && (structHandle != m_simdHandleCache->SIMDVector2Handle) && - (structHandle != m_simdHandleCache->SIMDVector3Handle) && - (structHandle != m_simdHandleCache->SIMDVector4Handle)); + // We order the checks roughly by expected hit count so early exits are possible + + if (m_simdHandleCache == nullptr) + { + return false; + } + + if (structHandle == m_simdHandleCache->SIMDVector4Handle) + { + return false; + } + + if (structHandle == m_simdHandleCache->SIMDVector3Handle) + { + return false; + } + + if (structHandle == m_simdHandleCache->SIMDVector2Handle) + { + return false; + } + + if (structHandle == m_simdHandleCache->SIMDQuaternionHandle) + { + return false; + } + + if (structHandle == m_simdHandleCache->SIMDPlaneHandle) + { + return false; + } + + return true; } // Returns true if the lclVar is an opaque SIMD type. diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index d73d4d779e9e9..323300a90426b 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -284,6 +284,20 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH size = getSIMDVectorRegisterByteLength(); JITDUMP(" Known type SIMD Vector\n"); } + else if (typeHnd == m_simdHandleCache->SIMDQuaternionHandle) + { + simdBaseJitType = CORINFO_TYPE_FLOAT; + size = 4 * genTypeSize(TYP_FLOAT); + assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE)); + JITDUMP(" Known type Quaternion\n"); + } + else if (typeHnd == m_simdHandleCache->SIMDPlaneHandle) + { + simdBaseJitType = CORINFO_TYPE_FLOAT; + size = 4 * genTypeSize(TYP_FLOAT); + assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE)); + JITDUMP(" Known type Plane\n"); + } // slow path search if (simdBaseJitType == CORINFO_TYPE_UNDEF) @@ -382,6 +396,24 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH size = getSIMDVectorRegisterByteLength(); JITDUMP(" Found type Vector\n"); } + else if (strcmp(className, "Quaternion") == 0) + { + m_simdHandleCache->SIMDQuaternionHandle = typeHnd; + + simdBaseJitType = CORINFO_TYPE_FLOAT; + size = 4 * genTypeSize(TYP_FLOAT); + assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE)); + JITDUMP(" Found Quaternion\n"); + } + else if (strcmp(className, "Plane") == 0) + { + m_simdHandleCache->SIMDPlaneHandle = typeHnd; + + simdBaseJitType = CORINFO_TYPE_FLOAT; + size = 4 * genTypeSize(TYP_FLOAT); + assert(size == roundUp(info.compCompHnd->getClassSize(typeHnd), TARGET_POINTER_SIZE)); + JITDUMP(" Found Plane\n"); + } } } #ifdef FEATURE_HW_INTRINSICS From 9d5aa214a58db5e400b49c165ad07b55c8892969 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 27 Jan 2023 16:15:43 -0800 Subject: [PATCH 02/30] Add some minimal intrinsification of Quaternion and Plane --- src/coreclr/jit/simdashwintrinsic.cpp | 15 +++ src/coreclr/jit/simdashwintrinsic.h | 2 + src/coreclr/jit/simdashwintrinsiclistarm64.h | 28 +++++ src/coreclr/jit/simdashwintrinsiclistxarch.h | 27 +++++ .../src/System/Numerics/Plane.cs | 57 ++++----- .../src/System/Numerics/Quaternion.cs | 110 +++++++++--------- .../System/Runtime/Intrinsics/Vector128.cs | 16 +++ 7 files changed, 176 insertions(+), 79 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 6d36289c126c4..c1cea20ee6916 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -748,6 +748,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewOneConNode(retType, simdBaseType); } + case NI_Quaternion_get_Zero: case NI_Vector2_get_Zero: case NI_Vector3_get_Zero: case NI_Vector4_get_Zero: @@ -871,6 +872,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_op_UnaryNegation: case NI_Vector2_op_UnaryNegation: case NI_Vector3_op_UnaryNegation: case NI_Vector4_op_UnaryNegation: @@ -1059,6 +1061,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_Quaternion_op_Addition: case NI_Vector2_op_Addition: case NI_Vector3_op_Addition: case NI_Vector4_op_Addition: @@ -1134,6 +1137,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Plane_Dot: + case NI_Quaternion_Dot: case NI_Vector2_Dot: case NI_Vector3_Dot: case NI_Vector4_Dot: @@ -1155,6 +1160,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Plane_op_Equality: + case NI_Quaternion_op_Equality: case NI_Vector2_op_Equality: case NI_Vector3_op_Equality: case NI_Vector4_op_Equality: @@ -1254,6 +1261,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Plane_op_Inequality: + case NI_Quaternion_op_Inequality: case NI_Vector2_op_Inequality: case NI_Vector3_op_Inequality: case NI_Vector4_op_Inequality: @@ -1364,6 +1373,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_op_Multiply: case NI_Vector2_op_Multiply: case NI_Vector3_op_Multiply: case NI_Vector4_op_Multiply: @@ -1473,6 +1483,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_op_Subtraction: case NI_Vector2_op_Subtraction: case NI_Vector3_op_Subtraction: case NI_Vector4_op_Subtraction: @@ -1608,6 +1619,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Plane_CreateFromVector3: + case NI_Quaternion_CreateFromVector3: case NI_Vector3_CreateFromVector2: case NI_Vector4_CreateFromVector3: { @@ -1824,6 +1837,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_Plane_Create: + case NI_Quaternion_Create: case NI_Vector4_Create: { assert(retType == TYP_VOID); diff --git a/src/coreclr/jit/simdashwintrinsic.h b/src/coreclr/jit/simdashwintrinsic.h index f14b0870a7a5b..a7792d766eb32 100644 --- a/src/coreclr/jit/simdashwintrinsic.h +++ b/src/coreclr/jit/simdashwintrinsic.h @@ -7,6 +7,8 @@ enum class SimdAsHWIntrinsicClassId { Unknown, + Plane, + Quaternion, Vector2, Vector3, Vector4, diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 80e37fcaf88ef..93755b3a49ee3 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -32,6 +32,34 @@ * Each intrinsic has one or more flags with type of `enum SimdAsHWIntrinsicFlag` */ +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// Plane Intrinsics +SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) + +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// Quaternion Intrinsics +SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) + + // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 24671df67296a..36e285a7cf481 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -32,6 +32,33 @@ * Each intrinsic has one or more flags with type of `enum SimdAsHWIntrinsicFlag` */ +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// Plane Intrinsics +SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) + +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// ISA ID Name NumArg Instructions Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// Quaternion Intrinsics +SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) + // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index f60f32c0c962e..c962671b351d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; @@ -23,35 +22,37 @@ public struct Plane : IEquatable /// The distance of the plane along its normal from the origin. public float D; - /// Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. + /// Creates a object from the X, Y, and Z components of its normal, and its distance from the origin on that normal. /// The X component of the normal. /// The Y component of the normal. /// The Z component of the normal. /// The distance of the plane along its normal from the origin. + [Intrinsic] public Plane(float x, float y, float z, float d) { Normal = new Vector3(x, y, z); D = d; } - /// Creates a object from a specified normal and the distance along the normal from the origin. + /// Creates a object from a specified normal and the distance along the normal from the origin. /// The plane's normal vector. /// The plane's distance from the origin along its normal vector. + [Intrinsic] public Plane(Vector3 normal, float d) { Normal = normal; D = d; } - /// Creates a object from a specified four-dimensional vector. - /// A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. + /// Creates a object from a specified four-dimensional vector. + /// A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. public Plane(Vector4 value) { Normal = new Vector3(value.X, value.Y, value.Z); D = value.W; } - /// Creates a object that contains three specified points. + /// Creates a object that contains three specified points. /// The first point defining the plane. /// The second point defining the plane. /// The third point defining the plane. @@ -107,16 +108,17 @@ public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 p /// The plane. /// The four-dimensional vector. /// The dot product. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Dot(Plane plane, Vector4 value) { - return plane.Normal.X * value.X + - plane.Normal.Y * value.Y + - plane.Normal.Z * value.Z + - plane.D * value.W; + return (plane.Normal.X * value.X) + + (plane.Normal.Y * value.Y) + + (plane.Normal.Z * value.Z) + + (plane.D * value.W); } - /// Returns the dot product of a specified three-dimensional vector and the normal vector of this plane plus the distance () value of the plane. + /// Returns the dot product of a specified three-dimensional vector and the normal vector of this plane plus the distance () value of the plane. /// The plane. /// The 3-dimensional vector. /// The dot product. @@ -136,7 +138,7 @@ public static float DotCoordinate(Plane plane, Vector3 value) } } - /// Returns the dot product of a specified three-dimensional vector and the vector of this plane. + /// Returns the dot product of a specified three-dimensional vector and the vector of this plane. /// The plane. /// The three-dimensional vector. /// The dot product. @@ -155,7 +157,7 @@ public static float DotNormal(Plane plane, Vector3 value) } } - /// Creates a new object whose normal vector is the source plane's normal vector normalized. + /// Creates a new object whose normal vector is the source plane's normal vector normalized. /// The source plane. /// The normalized plane. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -197,7 +199,7 @@ public static Plane Normalize(Plane value) /// The normalized plane to transform. /// The transformation matrix to apply to . /// The transformed plane. - /// must already be normalized so that its vector is of unit length before this method is called. + /// must already be normalized so that its vector is of unit length before this method is called. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Plane Transform(Plane plane, Matrix4x4 matrix) { @@ -216,7 +218,7 @@ public static Plane Transform(Plane plane, Matrix4x4 matrix) /// The normalized plane to transform. /// The Quaternion rotation to apply to the plane. /// A new plane that results from applying the Quaternion rotation. - /// must already be normalized so that its vector is of unit length before this method is called. + /// must already be normalized so that its vector is of unit length before this method is called. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Plane Transform(Plane plane, Quaternion rotation) { @@ -260,22 +262,22 @@ public static Plane Transform(Plane plane, Quaternion rotation) /// The first plane to compare. /// The second plane to compare. /// if and are equal; otherwise, . - /// Two objects are equal if their and fields are equal. - /// The method defines the operation of the equality operator for objects. + /// Two objects are equal if their and fields are equal. + /// The method defines the operation of the equality operator for objects. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Plane value1, Plane value2) { - return (value1.Normal.X == value2.Normal.X && - value1.Normal.Y == value2.Normal.Y && - value1.Normal.Z == value2.Normal.Z && - value1.D == value2.D); + return (value1.Normal == value2.Normal) + && (value1.D == value2.D); } /// Returns a value that indicates whether two planes are not equal. /// The first plane to compare. /// The second plane to compare. /// if and are not equal; otherwise, . - /// The method defines the operation of the inequality operator for objects. + /// The method defines the operation of the inequality operator for objects. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(Plane value1, Plane value2) { @@ -285,7 +287,8 @@ public static Plane Transform(Plane plane, Quaternion rotation) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and their and fields are equal. + /// The current instance and are equal if is a object and their and fields are equal. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { @@ -295,7 +298,7 @@ public override readonly bool Equals([NotNullWhen(true)] object? obj) /// Returns a value that indicates whether this instance and another plane object are equal. /// The other plane. /// if the two planes are equal; otherwise, . - /// Two objects are equal if their and fields are equal. + /// Two objects are equal if their and fields are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(Plane other) { @@ -304,7 +307,7 @@ public readonly bool Equals(Plane other) if (Vector128.IsHardwareAccelerated) { - return Vector128.LoadUnsafe(ref Unsafe.AsRef(in Normal.X)).Equals(Vector128.LoadUnsafe(ref other.Normal.X)); + return this.AsVector128().Equals(other.AsVector128()); } return SoftwareFallback(in this, other); @@ -324,8 +327,8 @@ public override readonly int GetHashCode() } /// Returns the string representation of this plane object. - /// A string that represents this object. - /// The string representation of a object use the formatting conventions of the current culture to format the numeric values in the returned string. For example, a object whose string representation is formatted by using the conventions of the en-US culture might appear as {Normal:<1.1, 2.2, 3.3> D:4.4}. + /// A string that represents this object. + /// The string representation of a object use the formatting conventions of the current culture to format the numeric values in the returned string. For example, a object whose string representation is formatted by using the conventions of the en-US culture might appear as {Normal:<1.1, 2.2, 3.3> D:4.4}. public override readonly string ToString() => $"{{Normal:{Normal} D:{D}}}"; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 154615379e2ac..86540b46f2580 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -9,7 +9,7 @@ namespace System.Numerics { /// Represents a vector that is used to encode three-dimensional physical rotations. - /// The structure is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where: + /// The structure is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where: /// w = cos(theta/2) [Intrinsic] public struct Quaternion : IEquatable @@ -35,6 +35,7 @@ public struct Quaternion : IEquatable /// The value to assign to the Y component of the quaternion. /// The value to assign to the Z component of the quaternion. /// The value to assign to the W component of the quaternion. + [Intrinsic] public Quaternion(float x, float y, float z, float w) { X = x; @@ -46,6 +47,7 @@ public Quaternion(float x, float y, float z, float w) /// Creates a quaternion from the specified vector and rotation parts. /// The vector part of the quaternion. /// The rotation part of the quaternion. + [Intrinsic] public Quaternion(Vector3 vectorPart, float scalarPart) { X = vectorPart.X; @@ -58,6 +60,7 @@ public Quaternion(Vector3 vectorPart, float scalarPart) /// A quaternion whose values are (0, 0, 0, 0). public static Quaternion Zero { + [Intrinsic] get => default; } @@ -65,7 +68,7 @@ public static Quaternion Zero /// A quaternion whose values are (0, 0, 0, 1). public static Quaternion Identity { - get => new Quaternion(0, 0, 0, 1); + get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -74,7 +77,7 @@ public static Quaternion Identity /// was less than zero or greater than the number of elements. public float this[int index] { - get => GetElement(this, index); + readonly get => GetElement(this, index); set => this = WithElement(this, index, value); } @@ -128,7 +131,7 @@ internal static void SetElementUnsafe(ref Quaternion quaternion, int index, floa /// Gets a value that indicates whether the current instance is the identity quaternion. /// if the current instance is the identity quaternion; otherwise, . - /// + /// public readonly bool IsIdentity { get => this == Identity; @@ -138,24 +141,24 @@ public readonly bool IsIdentity /// The first quaternion. /// The second quaternion. /// The quaternion that contains the summed values of and . - /// The method defines the operation of the addition operator for objects. + /// The method defines the operation of the addition operator for objects. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion operator +(Quaternion value1, Quaternion value2) { - Quaternion ans; - - ans.X = value1.X + value2.X; - ans.Y = value1.Y + value2.Y; - ans.Z = value1.Z + value2.Z; - ans.W = value1.W + value2.W; - - return ans; + return new Quaternion( + value1.X + value2.X, + value1.Y + value2.Y, + value1.Z + value2.Z, + value1.W + value2.W + ); } /// Divides one quaternion by a second quaternion. /// The dividend. /// The divisor. /// The quaternion that results from dividing by . - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. public static Quaternion operator /(Quaternion value1, Quaternion value2) { Quaternion ans; @@ -199,7 +202,9 @@ public readonly bool IsIdentity /// The second quaternion to compare. /// if the two quaternions are equal; otherwise, . /// Two quaternions are equal if each of their corresponding components is equal. - /// The method defines the operation of the equality operator for objects. + /// The method defines the operation of the equality operator for objects. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Quaternion value1, Quaternion value2) { return (value1.X == value2.X) @@ -212,6 +217,8 @@ public readonly bool IsIdentity /// The first quaternion to compare. /// The second quaternion to compare. /// if and are not equal; otherwise, . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(Quaternion value1, Quaternion value2) { return !(value1 == value2); @@ -221,7 +228,7 @@ public readonly bool IsIdentity /// The first quaternion. /// The second quaternion. /// The product quaternion. - /// The method defines the operation of the multiplication operator for objects. + /// The method defines the operation of the multiplication operator for objects. public static Quaternion operator *(Quaternion value1, Quaternion value2) { Quaternion ans; @@ -255,50 +262,45 @@ public readonly bool IsIdentity /// The source quaternion. /// The scalar value. /// The scaled quaternion. - /// The method defines the operation of the multiplication operator for objects. + /// The method defines the operation of the multiplication operator for objects. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion operator *(Quaternion value1, float value2) { - Quaternion ans; - - ans.X = value1.X * value2; - ans.Y = value1.Y * value2; - ans.Z = value1.Z * value2; - ans.W = value1.W * value2; - - return ans; + return new Quaternion( + value1.X * value2, + value1.Y * value2, + value1.Z * value2, + value1.W * value2 + ); } /// Subtracts each element in a second quaternion from its corresponding element in a first quaternion. /// The first quaternion. /// The second quaternion. /// The quaternion containing the values that result from subtracting each element in from its corresponding element in . - /// The method defines the operation of the subtraction operator for objects. + /// The method defines the operation of the subtraction operator for objects. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion operator -(Quaternion value1, Quaternion value2) { - Quaternion ans; - - ans.X = value1.X - value2.X; - ans.Y = value1.Y - value2.Y; - ans.Z = value1.Z - value2.Z; - ans.W = value1.W - value2.W; - - return ans; + return new Quaternion( + value1.X - value2.X, + value1.Y - value2.Y, + value1.Z - value2.Z, + value1.W - value2.W + ); } /// Reverses the sign of each component of the quaternion. /// The quaternion to negate. /// The negated quaternion. - /// The method defines the operation of the unary negation operator for objects. + /// The method defines the operation of the unary negation operator for objects. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion operator -(Quaternion value) { - Quaternion ans; - - ans.X = -value.X; - ans.Y = -value.Y; - ans.Z = -value.Z; - ans.W = -value.W; - - return ans; + return Zero - value; } /// Adds each element in one quaternion with its corresponding element in a second quaternion. @@ -365,7 +367,7 @@ public static Quaternion Conjugate(Quaternion value) /// The unit vector to rotate around. /// The angle, in radians, to rotate around the vector. /// The newly created quaternion. - /// vector must be normalized before calling this method or the resulting will be incorrect. + /// vector must be normalized before calling this method or the resulting will be incorrect. public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle) { Quaternion ans; @@ -481,12 +483,14 @@ public static Quaternion Divide(Quaternion value1, Quaternion value2) /// The first quaternion. /// The second quaternion. /// The dot product. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Dot(Quaternion quaternion1, Quaternion quaternion2) { - return quaternion1.X * quaternion2.X + - quaternion1.Y * quaternion2.Y + - quaternion1.Z * quaternion2.Z + - quaternion1.W * quaternion2.W; + return (quaternion1.X * quaternion2.X) + + (quaternion1.Y * quaternion2.Y) + + (quaternion1.Z * quaternion2.Z) + + (quaternion1.W * quaternion2.W); } /// Returns the inverse of a quaternion. @@ -582,7 +586,7 @@ public static Quaternion Negate(Quaternion value) return -value; } - /// Divides each component of a specified by its length. + /// Divides each component of a specified by its length. /// The quaternion to normalize. /// The normalized quaternion. public static Quaternion Normalize(Quaternion value) @@ -663,7 +667,7 @@ public static Quaternion Subtract(Quaternion value1, Quaternion value2) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and the corresponding components of each matrix are equal. + /// The current instance and are equal if is a object and the corresponding components of each matrix are equal. public override readonly bool Equals([NotNullWhen(true)] object? obj) { return (obj is Quaternion other) && Equals(other); @@ -681,7 +685,7 @@ public readonly bool Equals(Quaternion other) if (Vector128.IsHardwareAccelerated) { - return Vector128.LoadUnsafe(ref Unsafe.AsRef(in X)).Equals(Vector128.LoadUnsafe(ref other.X)); + return this.AsVector128().Equals(other.AsVector128()); } return SoftwareFallback(in this, other); @@ -704,6 +708,7 @@ public override readonly int GetHashCode() /// Calculates the length of the quaternion. /// The computed length of the quaternion. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { float lengthSquared = LengthSquared(); @@ -712,9 +717,10 @@ public readonly float Length() /// Calculates the squared length of the quaternion. /// The length squared of the quaternion. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { - return X * X + Y * Y + Z * Z + W * W; + return Dot(this, this); } /// Returns a string that represents this quaternion. 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 de163d2550ee6..99295c946168b 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 @@ -234,6 +234,22 @@ public static Vector128 AsUInt32(this Vector128 vector) public static Vector128 AsUInt64(this Vector128 vector) where T : struct => vector.As(); + /// Reinterprets a as a new . + /// The plane to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 AsVector128(this Plane value) + => Unsafe.As>(ref value); + + /// Reinterprets a as a new . + /// The quaternion to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 AsVector128(this Quaternion value) + => Unsafe.As>(ref value); + /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . From a666f6cb1c8ead6662fc2dfcf29f1c2155edfefb Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 27 Jan 2023 16:25:45 -0800 Subject: [PATCH 03/30] Ensure Vector indexers are marked readonly --- .../ref/System.Numerics.Vectors.cs | 12 ++++++------ .../src/System/Numerics/Vector2.cs | 2 +- .../src/System/Numerics/Vector3.cs | 2 +- .../src/System/Numerics/Vector4.cs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) 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 ce2500eb47c84..152cf866e3ea2 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -16,7 +16,7 @@ public partial struct Matrix3x2 : System.IEquatable public float M32; public Matrix3x2(float m11, float m12, float m21, float m22, float m31, float m32) { throw null; } public static System.Numerics.Matrix3x2 Identity { get { throw null; } } - public float this[int row, int column] { get { throw null; } set { throw null; } } + public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public readonly bool IsIdentity { get { throw null; } } public System.Numerics.Vector2 Translation { readonly get { throw null; } set { } } public static System.Numerics.Matrix3x2 Add(System.Numerics.Matrix3x2 value1, System.Numerics.Matrix3x2 value2) { throw null; } @@ -72,7 +72,7 @@ public partial struct Matrix4x4 : System.IEquatable public Matrix4x4(System.Numerics.Matrix3x2 value) { throw null; } public Matrix4x4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) { throw null; } public static System.Numerics.Matrix4x4 Identity { get { throw null; } } - public float this[int row, int column] { get { throw null; } set { throw null; } } + public float this[int row, int column] { readonly get { throw null; } set { throw null; } } public readonly bool IsIdentity { get { throw null; } } public System.Numerics.Vector3 Translation { readonly get { throw null; } set { } } public static System.Numerics.Matrix4x4 Add(System.Numerics.Matrix4x4 value1, System.Numerics.Matrix4x4 value2) { throw null; } @@ -157,7 +157,7 @@ public partial struct Quaternion : System.IEquatable public Quaternion(float x, float y, float z, float w) { throw null; } public static System.Numerics.Quaternion Zero { get { throw null; } } public static System.Numerics.Quaternion Identity { get { throw null; } } - public float this[int index] { get { throw null; } set { throw null; } } + public float this[int index] { readonly get { throw null; } set { throw null; } } public readonly bool IsIdentity { get { throw null; } } public static System.Numerics.Quaternion Add(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; } public static System.Numerics.Quaternion Concatenate(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) { throw null; } @@ -396,7 +396,7 @@ public partial struct Vector2 : System.IEquatable, Syst public static System.Numerics.Vector2 One { get { throw null; } } public static System.Numerics.Vector2 UnitX { get { throw null; } } public static System.Numerics.Vector2 UnitY { get { throw null; } } - public float this[int index] { get { throw null; } set { throw null; } } + public float this[int index] { readonly get { throw null; } set { throw null; } } public static System.Numerics.Vector2 Zero { get { throw null; } } public static System.Numerics.Vector2 Abs(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 Add(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } @@ -458,7 +458,7 @@ public partial struct Vector3 : System.IEquatable, Syst public static System.Numerics.Vector3 UnitX { get { throw null; } } public static System.Numerics.Vector3 UnitY { get { throw null; } } public static System.Numerics.Vector3 UnitZ { get { throw null; } } - public float this[int index] { get { throw null; } set { throw null; } } + public float this[int index] { readonly get { throw null; } set { throw null; } } public static System.Numerics.Vector3 Zero { get { throw null; } } public static System.Numerics.Vector3 Abs(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 Add(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } @@ -522,7 +522,7 @@ public partial struct Vector4 : System.IEquatable, Syst public static System.Numerics.Vector4 UnitX { get { throw null; } } public static System.Numerics.Vector4 UnitY { get { throw null; } } public static System.Numerics.Vector4 UnitZ { get { throw null; } } - public float this[int index] { get { throw null; } set { throw null; } } + public float this[int index] { readonly get { throw null; } set { throw null; } } public static System.Numerics.Vector4 Zero { get { throw null; } } public static System.Numerics.Vector4 Abs(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 Add(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 6c6e054ba5d7f..a4ad4204802b3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -92,7 +92,7 @@ public static Vector2 UnitY /// was less than zero or greater than the number of elements. public float this[int index] { - get => GetElement(this, index); + readonly get => GetElement(this, index); set => this = WithElement(this, index, value); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 2773bbc4406f9..649143ee658dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -112,7 +112,7 @@ public static Vector3 UnitZ /// was less than zero or greater than the number of elements. public float this[int index] { - get => GetElement(this, index); + readonly get => GetElement(this, index); set => this = WithElement(this, index, value); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 485cbd43f26cb..ea9509b939d49 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -134,7 +134,7 @@ public static Vector4 UnitW /// was less than zero or greater than the number of elements. public float this[int index] { - get => GetElement(this, index); + readonly get => GetElement(this, index); set => this = WithElement(this, index, value); } From 6cc5c3dd572c4943447e7560a1ea60d7923e2ca4 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 09:29:45 -0800 Subject: [PATCH 04/30] Ensure the vector constant properties are intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 57 +++++++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 12 +++- src/coreclr/jit/simdashwintrinsiclistxarch.h | 10 ++++ .../src/System/Numerics/Quaternion.cs | 1 + .../src/System/Numerics/Vector2.cs | 2 + .../src/System/Numerics/Vector3.cs | 3 + .../src/System/Numerics/Vector4.cs | 4 ++ 7 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index c1cea20ee6916..d10c4f44e570c 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -748,6 +748,63 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewOneConNode(retType, simdBaseType); } + case NI_Vector2_get_UnitX: + case NI_Vector3_get_UnitX: + case NI_Vector4_get_UnitX: + { + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = 1.0f; + vecCon->gtSimd16Val.f32[1] = 0.0f; + vecCon->gtSimd16Val.f32[2] = 0.0f; + vecCon->gtSimd16Val.f32[3] = 0.0f; + + return vecCon; + } + + case NI_Vector2_get_UnitY: + case NI_Vector3_get_UnitY: + case NI_Vector4_get_UnitY: + { + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = 0.0f; + vecCon->gtSimd16Val.f32[1] = 1.0f; + vecCon->gtSimd16Val.f32[2] = 0.0f; + vecCon->gtSimd16Val.f32[3] = 0.0f; + + return vecCon; + } + + case NI_Vector2_get_UnitZ: + case NI_Vector3_get_UnitZ: + case NI_Vector4_get_UnitZ: + { + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = 0.0f; + vecCon->gtSimd16Val.f32[1] = 0.0f; + vecCon->gtSimd16Val.f32[2] = 1.0f; + vecCon->gtSimd16Val.f32[3] = 0.0f; + + return vecCon; + } + + case NI_Quaternion_get_Identity: + case NI_Vector2_get_UnitW: + case NI_Vector3_get_UnitW: + case NI_Vector4_get_UnitW: + { + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = 0.0f; + vecCon->gtSimd16Val.f32[1] = 0.0f; + vecCon->gtSimd16Val.f32[2] = 0.0f; + vecCon->gtSimd16Val.f32[3] = 1.0f; + + return vecCon; + } + case NI_Quaternion_get_Zero: case NI_Vector2_get_Zero: case NI_Vector3_get_Zero: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 93755b3a49ee3..b5cd998e61c13 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -51,6 +51,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -70,6 +71,8 @@ SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -93,7 +96,10 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero , NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -117,6 +123,10 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 36e285a7cf481..f7d3111b68201 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -51,6 +51,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -69,6 +70,8 @@ SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -92,6 +95,9 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -116,6 +122,10 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 86540b46f2580..226eaa707144d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -68,6 +68,7 @@ public static Quaternion Zero /// A quaternion whose values are (0, 0, 0, 1). public static Quaternion Identity { + [Intrinsic] get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index a4ad4204802b3..4f36863e7900d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -76,6 +76,7 @@ public static Vector2 One /// The vector (1,0). public static Vector2 UnitX { + [Intrinsic] get => new Vector2(1.0f, 0.0f); } @@ -83,6 +84,7 @@ public static Vector2 UnitX /// The vector (0,1). public static Vector2 UnitY { + [Intrinsic] get => new Vector2(0.0f, 1.0f); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 649143ee658dd..859fcedcaf3b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -89,6 +89,7 @@ public static Vector3 One /// The vector (1,0,0). public static Vector3 UnitX { + [Intrinsic] get => new Vector3(1.0f, 0.0f, 0.0f); } @@ -96,6 +97,7 @@ public static Vector3 UnitX /// The vector (0,1,0). public static Vector3 UnitY { + [Intrinsic] get => new Vector3(0.0f, 1.0f, 0.0f); } @@ -103,6 +105,7 @@ public static Vector3 UnitY /// The vector (0,0,1). public static Vector3 UnitZ { + [Intrinsic] get => new Vector3(0.0f, 0.0f, 1.0f); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index ea9509b939d49..dc969cb0de557 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -104,6 +104,7 @@ public static Vector4 One /// The vector (1,0,0,0). public static Vector4 UnitX { + [Intrinsic] get => new Vector4(1.0f, 0.0f, 0.0f, 0.0f); } @@ -111,6 +112,7 @@ public static Vector4 UnitX /// The vector (0,1,0,0). public static Vector4 UnitY { + [Intrinsic] get => new Vector4(0.0f, 1.0f, 0.0f, 0.0f); } @@ -118,6 +120,7 @@ public static Vector4 UnitY /// The vector (0,0,1,0). public static Vector4 UnitZ { + [Intrinsic] get => new Vector4(0.0f, 0.0f, 1.0f, 0.0f); } @@ -125,6 +128,7 @@ public static Vector4 UnitZ /// The vector (0,0,0,1). public static Vector4 UnitW { + [Intrinsic] get => new Vector4(0.0f, 0.0f, 0.0f, 1.0f); } From e9e45287e3cd7d078aa5d26c7afa268f82ecfdf9 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 09:57:28 -0800 Subject: [PATCH 05/30] Ensure that the vector GetElement and WithElement APIs are intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 28 ++++++++- src/coreclr/jit/simdashwintrinsiclistarm64.h | 18 +++--- src/coreclr/jit/simdashwintrinsiclistxarch.h | 4 ++ .../System.Private.CoreLib.Shared.projitems | 6 +- .../System/Numerics/Quaternion.Extensions.cs | 62 +++++++++++++++++++ .../src/System/Numerics/Quaternion.cs | 54 ++-------------- .../src/System/Numerics/Vector2.Extensions.cs | 62 +++++++++++++++++++ .../src/System/Numerics/Vector2.cs | 54 ++-------------- .../src/System/Numerics/Vector3.Extensions.cs | 62 +++++++++++++++++++ .../src/System/Numerics/Vector3.cs | 54 ++-------------- .../src/System/Numerics/Vector4.Extensions.cs | 62 +++++++++++++++++++ .../src/System/Numerics/Vector4.cs | 54 ++-------------- 12 files changed, 313 insertions(+), 207 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index d10c4f44e570c..717f859b26b71 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -408,6 +408,27 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, #if defined(TARGET_XARCH) bool isVectorT256 = (SimdAsHWIntrinsicInfo::lookupClassId(intrinsic) == SimdAsHWIntrinsicClassId::VectorT256); + if (isVectorT256 && (simdSize != 32)) + { + // We have a couple extension methods for Vector2/3/4 and Quaternion exposed here + // Such APIs are not actually AVX/AVX2 dependent and operate on 128-bit vectors + + switch (intrinsic) + { + case NI_VectorT256_GetElement: + case NI_VectorT256_WithElement: + { + isVectorT256 = false; + break; + } + + default: + { + break; + } + } + } + // We should have already exited early if SSE2 isn't supported assert(compIsaSupportedDebugOnly(InstructionSet_SSE2)); @@ -776,7 +797,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return vecCon; } - case NI_Vector2_get_UnitZ: case NI_Vector3_get_UnitZ: case NI_Vector4_get_UnitZ: { @@ -791,8 +811,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } case NI_Quaternion_get_Identity: - case NI_Vector2_get_UnitW: - case NI_Vector3_get_UnitW: case NI_Vector4_get_UnitW: { GenTreeVecCon* vecCon = gtNewVconNode(retType); @@ -1253,6 +1271,10 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_get_Item: + case NI_Vector2_get_Item: + case NI_Vector3_get_Item: + case NI_Vector4_get_Item: case NI_VectorT128_get_Item: case NI_VectorT128_GetElement: #if defined(TARGET_XARCH) diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index b5cd998e61c13..54addb3328dc0 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -52,6 +52,7 @@ SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -70,6 +71,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -95,10 +97,11 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -122,11 +125,12 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) -SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index f7d3111b68201..cba2abb833195 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -52,6 +52,7 @@ SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -69,6 +70,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -94,6 +96,7 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -121,6 +124,7 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index a3dc18c60dcbc..03d6724bb8ebd 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -560,12 +560,16 @@ + + + + @@ -2559,4 +2563,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs new file mode 100644 index 0000000000000..7c0e561c2edec --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Numerics +{ + public static unsafe partial class Vector + { + /// Gets the element at the specified index. + /// The quaternion to get the element from. + /// The index of the element to get. + /// The value of the element at . + /// was less than zero or greater than the number of elements. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static float GetElement(this Quaternion quaternion, int index) + { + if ((uint)(index) >= (uint)(Quaternion.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return quaternion.GetElementUnsafe(index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given quaternion. + /// The quaternion to get the remaining elements from. + /// The index of the element to set. + /// The value to set the element to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in . + /// was less than zero or greater than the number of elements. + [Intrinsic] + internal static Quaternion WithElement(this Quaternion quaternion, int index, float value) + { + if ((uint)(index) >= (uint)(Quaternion.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + Quaternion result = quaternion; + result.SetElementUnsafe(index, value); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetElementUnsafe(in this Quaternion quaternion, int index) + { + Debug.Assert((index >= 0) && (index < Quaternion.Count)); + ref float address = ref Unsafe.AsRef(in quaternion.X); + return Unsafe.Add(ref address, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SetElementUnsafe(ref this Quaternion quaternion, int index, float value) + { + Debug.Assert((index >= 0) && (index < Quaternion.Count)); + Unsafe.Add(ref quaternion.X, index) = value; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 226eaa707144d..98e4e1c8f8263 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -78,56 +78,12 @@ public static Quaternion Identity /// was less than zero or greater than the number of elements. public float this[int index] { - readonly get => GetElement(this, index); - set => this = WithElement(this, index, value); - } - - /// Gets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static float GetElement(Quaternion quaternion, int index) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - return GetElementUnsafe(ref quaternion, index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float GetElementUnsafe(ref Quaternion quaternion, int index) - { - Debug.Assert(index is >= 0 and < Count); - return Unsafe.Add(ref Unsafe.As(ref quaternion), index); - } - - /// Sets the element at the specified index. - /// The vector of the element to set. - /// The index of the element to set. - /// The value of the element to set. - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static Quaternion WithElement(Quaternion quaternion, int index, float value) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - Quaternion result = quaternion; - SetElementUnsafe(ref result, index, value); - return result; - } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => this.GetElement(index); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void SetElementUnsafe(ref Quaternion quaternion, int index, float value) - { - Debug.Assert(index is >= 0 and < Count); - Unsafe.Add(ref Unsafe.As(ref quaternion), index) = value; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this = this.WithElement(index, value); } /// Gets a value that indicates whether the current instance is the identity quaternion. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs new file mode 100644 index 0000000000000..5b57163ecad5f --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Numerics +{ + public static unsafe partial class Vector + { + /// Gets the element at the specified index. + /// The vector to get the element from. + /// The index of the element to get. + /// The value of the element at . + /// was less than zero or greater than the number of elements. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static float GetElement(this Vector2 vector, int index) + { + if ((uint)(index) >= (uint)(Vector2.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return vector.GetElementUnsafe(index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector. + /// The vector to get the remaining elements from. + /// The index of the element to set. + /// The value to set the element to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in . + /// was less than zero or greater than the number of elements. + [Intrinsic] + internal static Vector2 WithElement(this Vector2 vector, int index, float value) + { + if ((uint)(index) >= (uint)(Vector2.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + Vector2 result = vector; + result.SetElementUnsafe(index, value); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetElementUnsafe(in this Vector2 vector, int index) + { + Debug.Assert((index >= 0) && (index < Vector2.Count)); + ref float address = ref Unsafe.AsRef(in vector.X); + return Unsafe.Add(ref address, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SetElementUnsafe(ref this Vector2 vector, int index, float value) + { + Debug.Assert((index >= 0) && (index < Vector2.Count)); + Unsafe.Add(ref vector.X, index) = value; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 4f36863e7900d..9b9fd0b7e16b9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -94,56 +94,12 @@ public static Vector2 UnitY /// was less than zero or greater than the number of elements. public float this[int index] { - readonly get => GetElement(this, index); - set => this = WithElement(this, index, value); - } - - /// Gets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static float GetElement(Vector2 vector, int index) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - return GetElementUnsafe(ref vector, index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float GetElementUnsafe(ref Vector2 vector, int index) - { - Debug.Assert(index is >= 0 and < Count); - return Unsafe.Add(ref Unsafe.As(ref vector), index); - } - - /// Sets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to set. - /// The value of the element to set. - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static Vector2 WithElement(Vector2 vector, int index, float value) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - Vector2 result = vector; - SetElementUnsafe(ref result, index, value); - return result; - } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => this.GetElement(index); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void SetElementUnsafe(ref Vector2 vector, int index, float value) - { - Debug.Assert(index is >= 0 and < Count); - Unsafe.Add(ref Unsafe.As(ref vector), index) = value; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this = this.WithElement(index, value); } /// Adds two vectors together. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs new file mode 100644 index 0000000000000..2eb006eeda745 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Numerics +{ + public static unsafe partial class Vector + { + /// Gets the element at the specified index. + /// The vector to get the element from. + /// The index of the element to get. + /// The value of the element at . + /// was less than zero or greater than the number of elements. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static float GetElement(this Vector3 vector, int index) + { + if ((uint)(index) >= (uint)(Vector3.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return vector.GetElementUnsafe(index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector. + /// The vector to get the remaining elements from. + /// The index of the element to set. + /// The value to set the element to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in . + /// was less than zero or greater than the number of elements. + [Intrinsic] + internal static Vector3 WithElement(this Vector3 vector, int index, float value) + { + if ((uint)(index) >= (uint)(Vector3.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + Vector3 result = vector; + result.SetElementUnsafe(index, value); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetElementUnsafe(in this Vector3 vector, int index) + { + Debug.Assert((index >= 0) && (index < Vector3.Count)); + ref float address = ref Unsafe.AsRef(in vector.X); + return Unsafe.Add(ref address, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SetElementUnsafe(ref this Vector3 vector, int index, float value) + { + Debug.Assert((index >= 0) && (index < Vector3.Count)); + Unsafe.Add(ref vector.X, index) = value; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 859fcedcaf3b1..77ad9761106d9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -115,56 +115,12 @@ public static Vector3 UnitZ /// was less than zero or greater than the number of elements. public float this[int index] { - readonly get => GetElement(this, index); - set => this = WithElement(this, index, value); - } - - /// Gets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static float GetElement(Vector3 vector, int index) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - return GetElementUnsafe(ref vector, index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float GetElementUnsafe(ref Vector3 vector, int index) - { - Debug.Assert(index is >= 0 and < Count); - return Unsafe.Add(ref Unsafe.As(ref vector), index); - } - - /// Sets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to set. - /// The value of the element to set. - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static Vector3 WithElement(Vector3 vector, int index, float value) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - Vector3 result = vector; - SetElementUnsafe(ref result, index, value); - return result; - } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => this.GetElement(index); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void SetElementUnsafe(ref Vector3 vector, int index, float value) - { - Debug.Assert(index is >= 0 and < Count); - Unsafe.Add(ref Unsafe.As(ref vector), index) = value; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this = this.WithElement(index, value); } /// Adds two vectors together. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs new file mode 100644 index 0000000000000..143d003b96022 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Numerics +{ + public static unsafe partial class Vector + { + /// Gets the element at the specified index. + /// The vector to get the element from. + /// The index of the element to get. + /// The value of the element at . + /// was less than zero or greater than the number of elements. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static float GetElement(this Vector4 vector, int index) + { + if ((uint)(index) >= (uint)(Vector4.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + return vector.GetElementUnsafe(index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector. + /// The vector to get the remaining elements from. + /// The index of the element to set. + /// The value to set the element to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in . + /// was less than zero or greater than the number of elements. + [Intrinsic] + internal static Vector4 WithElement(this Vector4 vector, int index, float value) + { + if ((uint)(index) >= (uint)(Vector4.Count)) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + + Vector4 result = vector; + result.SetElementUnsafe(index, value); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetElementUnsafe(in this Vector4 vector, int index) + { + Debug.Assert((index >= 0) && (index < Vector4.Count)); + ref float address = ref Unsafe.AsRef(in vector.X); + return Unsafe.Add(ref address, index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void SetElementUnsafe(ref this Vector4 vector, int index, float value) + { + Debug.Assert((index >= 0) && (index < Vector4.Count)); + Unsafe.Add(ref vector.X, index) = value; + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index dc969cb0de557..c568df3b0cef8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -138,56 +138,12 @@ public static Vector4 UnitW /// was less than zero or greater than the number of elements. public float this[int index] { - readonly get => GetElement(this, index); - set => this = WithElement(this, index, value); - } - - /// Gets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to get. - /// The value of the element at . - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static float GetElement(Vector4 vector, int index) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - return GetElementUnsafe(ref vector, index); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float GetElementUnsafe(ref Vector4 vector, int index) - { - Debug.Assert(index is >= 0 and < Count); - return Unsafe.Add(ref Unsafe.As(ref vector), index); - } - - /// Sets the element at the specified index. - /// The vector of the element to get. - /// The index of the element to set. - /// The value of the element to set. - /// was less than zero or greater than the number of elements. - [Intrinsic] - internal static Vector4 WithElement(Vector4 vector, int index, float value) - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - - Vector4 result = vector; - SetElementUnsafe(ref result, index, value); - return result; - } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => this.GetElement(index); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void SetElementUnsafe(ref Vector4 vector, int index, float value) - { - Debug.Assert(index is >= 0 and < Count); - Unsafe.Add(ref Unsafe.As(ref vector), index) = value; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => this = this.WithElement(index, value); } /// Adds two vectors together. From 0d3690b45bba9790f439b5d68a35cf02db06f04d Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 10:11:30 -0800 Subject: [PATCH 06/30] Ensure vector division by scalar is intrinsic --- .../System.Private.CoreLib/src/System/Numerics/Vector2.cs | 1 + .../System.Private.CoreLib/src/System/Numerics/Vector3.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 9b9fd0b7e16b9..a7aaa48c7442f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -137,6 +137,7 @@ public float this[int index] /// The scalar value. /// The result of the division. /// The method defines the division operation for objects. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator /(Vector2 value1, float value2) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 77ad9761106d9..c1db0197f1174 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -160,6 +160,7 @@ public float this[int index] /// The scalar value. /// The result of the division. /// The method defines the division operation for objects. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator /(Vector3 value1, float value2) { From 15f804f4a04a3a7f8ba51e5d751889de463fbe9b Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 10:36:41 -0800 Subject: [PATCH 07/30] Minor cleanup to vector files --- .../src/System/Numerics/Plane.cs | 1 - .../src/System/Numerics/Vector2.cs | 60 ++++++++-------- .../src/System/Numerics/Vector3.cs | 68 +++++++++---------- .../src/System/Numerics/Vector4.cs | 68 +++++++++---------- 4 files changed, 95 insertions(+), 102 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index c962671b351d5..1f4ab2ef68dea 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs @@ -288,7 +288,6 @@ public static Plane Transform(Plane plane, Quaternion rotation) /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . /// The current instance and are equal if is a object and their and fields are equal. - [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index a7aaa48c7442f..5b26752fa272f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -1,13 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; -using System.Text; namespace System.Numerics { @@ -27,7 +25,7 @@ public partial struct Vector2 : IEquatable, IFormattable internal const int Count = 2; - /// Creates a new object whose two elements have the same value. + /// Creates a new object whose two elements have the same value. /// The value to assign to both elements. [Intrinsic] public Vector2(float value) : this(value, value) @@ -35,8 +33,8 @@ public Vector2(float value) : this(value, value) } /// Creates a vector whose elements have the specified values. - /// The value to assign to the field. - /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. [Intrinsic] public Vector2(float x, float y) { @@ -106,7 +104,7 @@ public float this[int index] /// The first vector to add. /// The second vector to add. /// The summed vector. - /// The method defines the addition operation for objects. + /// The method defines the addition operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator +(Vector2 left, Vector2 right) @@ -121,7 +119,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from dividing by . - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator /(Vector2 left, Vector2 right) @@ -136,7 +134,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The result of the division. - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator /(Vector2 value1, float value2) @@ -148,7 +146,7 @@ public float this[int index] /// The first vector to compare. /// The second vector to compare. /// if and are equal; otherwise, . - /// Two objects are equal if each value in is equal to the corresponding value in . + /// Two objects are equal if each value in is equal to the corresponding value in . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector2 left, Vector2 right) @@ -172,7 +170,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The element-wise product vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator *(Vector2 left, Vector2 right) @@ -187,7 +185,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator *(Vector2 left, float right) @@ -199,7 +197,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator *(float left, Vector2 right) @@ -211,7 +209,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from subtracting from . - /// The method defines the subtraction operation for objects. + /// The method defines the subtraction operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator -(Vector2 left, Vector2 right) @@ -225,7 +223,7 @@ public float this[int index] /// Negates the specified vector. /// The vector to negate. /// The negated vector. - /// The method defines the unary negation operation for objects. + /// The method defines the unary negation operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator -(Vector2 value) @@ -420,7 +418,7 @@ public static Vector2 Normalize(Vector2 value) public static Vector2 Reflect(Vector2 vector, Vector2 normal) { float dot = Dot(vector, normal); - return vector - (2 * dot * normal); + return vector - (2.0f * dot * normal); } /// Returns a vector whose elements are the square root of each of a specified vector's elements. @@ -524,9 +522,9 @@ public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix) /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least two elements. The method copies the vector's elements starting at index 0. - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is multidimensional. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array) { @@ -544,12 +542,12 @@ public readonly void CopyTo(float[] array) /// The destination array. /// The index at which to copy the first element of the vector. /// must have a sufficient number of elements to accommodate the two vector elements. In other words, elements and + 1 must already exist in . - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is less than zero. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is less than zero. /// -or- /// is greater than or equal to the array length. - /// is multidimensional. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array, int index) { @@ -570,7 +568,7 @@ public readonly void CopyTo(float[] array, int index) /// Copies the vector to the given .The length of the destination span must be at least 2. /// The destination span which the values are copied into. - /// If number of elements in source vector is greater than those available in destination span. + /// If number of elements in source vector is greater than those available in destination span. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(Span destination) { @@ -600,7 +598,7 @@ public readonly bool TryCopyTo(Span destination) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and their and elements are equal. + /// The current instance and are equal if is a object and their and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { @@ -610,7 +608,7 @@ public override readonly bool Equals([NotNullWhen(true)] object? obj) /// Returns a value that indicates whether this instance and another vector are equal. /// The other vector. /// if the two vectors are equal; otherwise, . - /// Two vectors are equal if their and elements are equal. + /// Two vectors are equal if their and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(Vector2 other) { @@ -644,7 +642,7 @@ public override readonly int GetHashCode() /// Returns the length of the vector. /// The vector's length. - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -654,8 +652,8 @@ public readonly float Length() /// Returns the length of the vector squared. /// The vector's length squared. - /// This operation offers better performance than a call to the method. - /// + /// This operation offers better performance than a call to the method. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -664,7 +662,7 @@ public readonly float LengthSquared() /// Returns the string representation of the current instance using default formatting. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. public override readonly string ToString() { return ToString("G", CultureInfo.CurrentCulture); @@ -673,7 +671,7 @@ public override readonly string ToString() /// Returns the string representation of the current instance using the specified format string to format individual elements. /// A standard or custom numeric format string that defines the format of individual elements. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. /// Standard Numeric Format Strings /// Custom Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format) @@ -685,7 +683,7 @@ public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericForma /// A standard or custom numeric format string that defines the format of individual elements. /// A format provider that supplies culture-specific formatting information. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. /// Custom Numeric Format Strings /// Standard Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index c1db0197f1174..3c42832bca887 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -1,13 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; -using System.Text; namespace System.Numerics { @@ -30,25 +28,25 @@ public partial struct Vector3 : IEquatable, IFormattable internal const int Count = 3; - /// Creates a new object whose three elements have the same value. + /// Creates a new object whose three elements have the same value. /// The value to assign to all three elements. [Intrinsic] public Vector3(float value) : this(value, value, value) { } - /// Creates a new object from the specified object and the specified value. + /// Creates a new object from the specified object and the specified value. /// The vector with two elements. - /// The additional value to assign to the field. + /// The additional value to assign to the field. [Intrinsic] public Vector3(Vector2 value, float z) : this(value.X, value.Y, z) { } /// Creates a vector whose elements have the specified values. - /// The value to assign to the field. - /// The value to assign to the field. - /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. [Intrinsic] public Vector3(float x, float y, float z) { @@ -127,7 +125,7 @@ public float this[int index] /// The first vector to add. /// The second vector to add. /// The summed vector. - /// The method defines the addition operation for objects. + /// The method defines the addition operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator +(Vector3 left, Vector3 right) @@ -143,7 +141,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from dividing by . - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator /(Vector3 left, Vector3 right) @@ -159,7 +157,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The result of the division. - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator /(Vector3 value1, float value2) @@ -171,7 +169,7 @@ public float this[int index] /// The first vector to compare. /// The second vector to compare. /// if and are equal; otherwise, . - /// Two objects are equal if each element in is equal to the corresponding element in . + /// Two objects are equal if each element in is equal to the corresponding element in . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector3 left, Vector3 right) @@ -196,7 +194,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The element-wise product vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator *(Vector3 left, Vector3 right) @@ -212,7 +210,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator *(Vector3 left, float right) @@ -224,7 +222,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator *(float left, Vector3 right) @@ -236,7 +234,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from subtracting from . - /// The method defines the subtraction operation for objects. + /// The method defines the subtraction operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator -(Vector3 left, Vector3 right) @@ -251,7 +249,7 @@ public float this[int index] /// Negates the specified vector. /// The vector to negate. /// The negated vector. - /// The method defines the unary negation operation for objects. + /// The method defines the unary negation operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator -(Vector3 value) @@ -372,7 +370,7 @@ public static float Dot(Vector3 vector1, Vector3 vector2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount) { - return (value1 * (1f - amount)) + (value2 * amount); + return (value1 * (1.0f - amount)) + (value2 * amount); } /// Returns a vector whose elements are the maximum of each of the pairs of elements in two specified vectors. @@ -461,7 +459,7 @@ public static Vector3 Normalize(Vector3 value) public static Vector3 Reflect(Vector3 vector, Vector3 normal) { float dot = Dot(vector, normal); - return vector - (2 * dot * normal); + return vector - (2.0f * dot * normal); } /// Returns a vector whose elements are the square root of each of a specified vector's elements. @@ -547,9 +545,9 @@ public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix) /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least three elements. The method copies the vector's elements starting at index 0. - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is multidimensional. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array) { @@ -567,12 +565,12 @@ public readonly void CopyTo(float[] array) /// The destination array. /// The index at which to copy the first element of the vector. /// must have a sufficient number of elements to accommodate the three vector elements. In other words, elements , + 1, and + 2 must already exist in . - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is less than zero. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is less than zero. /// -or- /// is greater than or equal to the array length. - /// is multidimensional. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array, int index) { @@ -593,7 +591,7 @@ public readonly void CopyTo(float[] array, int index) /// Copies the vector to the given . The length of the destination span must be at least 3. /// The destination span which the values are copied into. - /// If number of elements in source vector is greater than those available in destination span. + /// If number of elements in source vector is greater than those available in destination span. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(Span destination) { @@ -623,7 +621,7 @@ public readonly bool TryCopyTo(Span destination) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and their corresponding elements are equal. + /// The current instance and are equal if is a object and their corresponding elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { @@ -633,7 +631,7 @@ public override readonly bool Equals([NotNullWhen(true)] object? obj) /// Returns a value that indicates whether this instance and another vector are equal. /// The other vector. /// if the two vectors are equal; otherwise, . - /// Two vectors are equal if their , , and elements are equal. + /// Two vectors are equal if their , , and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(Vector3 other) { @@ -664,7 +662,7 @@ public override readonly int GetHashCode() /// Returns the length of this vector object. /// The vector's length. - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -674,8 +672,8 @@ public readonly float Length() /// Returns the length of the vector squared. /// The vector's length squared. - /// This operation offers better performance than a call to the method. - /// + /// This operation offers better performance than a call to the method. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -684,7 +682,7 @@ public readonly float LengthSquared() /// Returns the string representation of the current instance using default formatting. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. public override readonly string ToString() { return ToString("G", CultureInfo.CurrentCulture); @@ -693,7 +691,7 @@ public override readonly string ToString() /// Returns the string representation of the current instance using the specified format string to format individual elements. /// A standard or custom numeric format string that defines the format of individual elements. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. /// Standard Numeric Format Strings /// Custom Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format) @@ -705,7 +703,7 @@ public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericForma /// A standard or custom numeric format string that defines the format of individual elements. /// A format provider that supplies culture-specific formatting information. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. /// Standard Numeric Format Strings /// Custom Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index c568df3b0cef8..3a96feb7dd93c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -1,13 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; -using System.Text; namespace System.Numerics { @@ -33,14 +31,14 @@ public partial struct Vector4 : IEquatable, IFormattable internal const int Count = 4; - /// Creates a new object whose four elements have the same value. + /// Creates a new object whose four elements have the same value. /// The value to assign to all four elements. [Intrinsic] public Vector4(float value) : this(value, value, value, value) { } - /// Creates a new object from the specified object and a Z and a W component. + /// Creates a new object from the specified object and a Z and a W component. /// The vector to use for the X and Y components. /// The Z component. /// The W component. @@ -49,7 +47,7 @@ public Vector4(Vector2 value, float z, float w) : this(value.X, value.Y, z, w) { } - /// Constructs a new object from the specified object and a W component. + /// Constructs a new object from the specified object and a W component. /// The vector to use for the X, Y, and Z components. /// The W component. [Intrinsic] @@ -58,10 +56,10 @@ public Vector4(Vector3 value, float w) : this(value.X, value.Y, value.Z, w) } /// Creates a vector whose elements have the specified values. - /// The value to assign to the field. - /// The value to assign to the field. - /// The value to assign to the field. - /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. + /// The value to assign to the field. [Intrinsic] public Vector4(float x, float y, float z, float w) { @@ -92,7 +90,7 @@ public static Vector4 Zero } /// Gets a vector whose 4 elements are equal to one. - /// Returns . + /// Returns . /// A vector whose four elements are equal to one (that is, it returns the vector (1,1,1,1). public static Vector4 One { @@ -150,7 +148,7 @@ public float this[int index] /// The first vector to add. /// The second vector to add. /// The summed vector. - /// The method defines the addition operation for objects. + /// The method defines the addition operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator +(Vector4 left, Vector4 right) @@ -167,7 +165,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from dividing by . - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator /(Vector4 left, Vector4 right) @@ -184,7 +182,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The result of the division. - /// The method defines the division operation for objects. + /// The method defines the division operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator /(Vector4 value1, float value2) @@ -196,7 +194,7 @@ public float this[int index] /// The first vector to compare. /// The second vector to compare. /// if and are equal; otherwise, . - /// Two objects are equal if each element in is equal to the corresponding element in . + /// Two objects are equal if each element in is equal to the corresponding element in . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(Vector4 left, Vector4 right) @@ -222,7 +220,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The element-wise product vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(Vector4 left, Vector4 right) @@ -239,7 +237,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(Vector4 left, float right) @@ -251,7 +249,7 @@ public float this[int index] /// The vector. /// The scalar value. /// The scaled vector. - /// The method defines the multiplication operation for objects. + /// The method defines the multiplication operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(float left, Vector4 right) @@ -263,7 +261,7 @@ public float this[int index] /// The first vector. /// The second vector. /// The vector that results from subtracting from . - /// The method defines the subtraction operation for objects. + /// The method defines the subtraction operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(Vector4 left, Vector4 right) @@ -279,7 +277,7 @@ public float this[int index] /// Negates the specified vector. /// The vector to negate. /// The negated vector. - /// The method defines the unary negation operation for objects. + /// The method defines the unary negation operation for objects. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(Vector4 value) @@ -638,9 +636,9 @@ public static Vector4 Transform(Vector4 value, Quaternion rotation) /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least four elements. The method copies the vector's elements starting at index 0. - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is multidimensional. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array) { @@ -658,12 +656,12 @@ public readonly void CopyTo(float[] array) /// The destination array. /// The index at which to copy the first element of the vector. /// must have a sufficient number of elements to accommodate the four vector elements. In other words, elements through + 3 must already exist in . - /// is . - /// The number of elements in the current instance is greater than in the array. - /// is less than zero. + /// is . + /// The number of elements in the current instance is greater than in the array. + /// is less than zero. /// -or- /// is greater than or equal to the array length. - /// is multidimensional. + /// is multidimensional. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(float[] array, int index) { @@ -684,7 +682,7 @@ public readonly void CopyTo(float[] array, int index) /// Copies the vector to the given . The length of the destination span must be at least 4. /// The destination span which the values are copied into. - /// If number of elements in source vector is greater than those available in destination span. + /// If number of elements in source vector is greater than those available in destination span. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(Span destination) { @@ -714,7 +712,7 @@ public readonly bool TryCopyTo(Span destination) /// Returns a value that indicates whether this instance and another vector are equal. /// The other vector. /// if the two vectors are equal; otherwise, . - /// Two vectors are equal if their , , , and elements are equal. + /// Two vectors are equal if their , , , and elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(Vector4 other) { @@ -740,7 +738,7 @@ static bool SoftwareFallback(in Vector4 self, Vector4 other) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and their corresponding elements are equal. + /// The current instance and are equal if is a object and their corresponding elements are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { @@ -756,7 +754,7 @@ public override readonly int GetHashCode() /// Returns the length of this vector object. /// The vector's length. - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -766,8 +764,8 @@ public readonly float Length() /// Returns the length of the vector squared. /// The vector's length squared. - /// This operation offers better performance than a call to the method. - /// + /// This operation offers better performance than a call to the method. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -776,7 +774,7 @@ public readonly float LengthSquared() /// Returns the string representation of the current instance using default formatting. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using the "G" (general) format string and the formatting conventions of the current thread culture. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. public override readonly string ToString() { return ToString("G", CultureInfo.CurrentCulture); @@ -785,7 +783,7 @@ public override readonly string ToString() /// Returns the string representation of the current instance using the specified format string to format individual elements. /// A standard or custom numeric format string that defines the format of individual elements. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and the current culture's formatting conventions. The "<" and ">" characters are used to begin and end the string, and the current culture's property followed by a space is used to separate each element. /// Standard Numeric Format Strings /// Custom Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format) @@ -797,7 +795,7 @@ public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericForma /// A standard or custom numeric format string that defines the format of individual elements. /// A format provider that supplies culture-specific formatting information. /// The string representation of the current instance. - /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. + /// This method returns a string in which each element of the vector is formatted using and . The "<" and ">" characters are used to begin and end the string, and the format provider's property followed by a space is used to separate each element. /// Standard Numeric Format Strings /// Custom Numeric Format Strings public readonly string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? formatProvider) From 8cdb2f54e757c157c10fe684e0f94d14ba801dec Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 10:58:17 -0800 Subject: [PATCH 08/30] Ensure vector arithmetic functions are consistently intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 19 +++++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 21 ++++++++++++++++++- src/coreclr/jit/simdashwintrinsiclistxarch.h | 19 +++++++++++++++++ .../src/System/Numerics/Quaternion.cs | 4 ++++ .../src/System/Numerics/Vector2.cs | 8 +++++++ .../src/System/Numerics/Vector3.cs | 8 +++++++ .../src/System/Numerics/Vector4.cs | 8 +++++++ 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 717f859b26b71..cf848505a7cd4 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -947,9 +947,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Negate: case NI_Quaternion_op_UnaryNegation: + case NI_Vector2_Negate: case NI_Vector2_op_UnaryNegation: + case NI_Vector3_Negate: case NI_Vector3_op_UnaryNegation: + case NI_Vector4_Negate: case NI_Vector4_op_UnaryNegation: case NI_VectorT128_Negate: case NI_VectorT128_op_UnaryNegation: @@ -1136,9 +1140,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_Quaternion_Add: case NI_Quaternion_op_Addition: + case NI_Vector2_Add: case NI_Vector2_op_Addition: + case NI_Vector3_Add: case NI_Vector3_op_Addition: + case NI_Vector4_Add: case NI_Vector4_op_Addition: case NI_VectorT128_Add: case NI_VectorT128_op_Addition: @@ -1198,8 +1206,11 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Vector2_Divide: case NI_Vector2_op_Division: + case NI_Vector3_Divide: case NI_Vector3_op_Division: + case NI_Vector4_Divide: case NI_Vector4_op_Division: case NI_VectorT128_Divide: case NI_VectorT128_op_Division: @@ -1452,9 +1463,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Multiply: case NI_Quaternion_op_Multiply: + case NI_Vector2_Multiply: case NI_Vector2_op_Multiply: + case NI_Vector3_Multiply: case NI_Vector3_op_Multiply: + case NI_Vector4_Multiply: case NI_Vector4_op_Multiply: case NI_VectorT128_Multiply: case NI_VectorT128_op_Multiply: @@ -1562,9 +1577,13 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Subtract: case NI_Quaternion_op_Subtraction: + case NI_Vector2_Subtract: case NI_Vector2_op_Subtraction: + case NI_Vector3_Subtract: case NI_Vector3_op_Subtraction: + case NI_Vector4_Subtract: case NI_Vector4_op_Subtraction: case NI_VectorT128_Subtract: case NI_VectorT128_op_Subtraction: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 54addb3328dc0..02bb8f3224676 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -48,19 +48,22 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Quaternion Intrinsics +SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) - +SIMD_AS_HWINTRINSIC_ID(Quaternion, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -68,8 +71,10 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector2 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -78,6 +83,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -86,6 +93,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -93,9 +101,11 @@ SIMD_AS_HWINTRINSIC_NM(Vector2, Sqrt, "SquareRoot", // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector3 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -105,6 +115,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -113,6 +125,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -120,10 +133,12 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, Sqrt, "SquareRoot", // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector4 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -134,6 +149,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -142,6 +159,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) + // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index cba2abb833195..08f869dcb3543 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -48,18 +48,22 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, // {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Quaternion Intrinsics +SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -67,8 +71,10 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, op_UnaryNegation, // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector2 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -77,6 +83,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -85,6 +93,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector2, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -92,9 +101,11 @@ SIMD_AS_HWINTRINSIC_NM(Vector2, Sqrt, "SquareRoot", // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector3 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -104,6 +115,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -112,6 +125,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector3, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags @@ -119,10 +133,12 @@ SIMD_AS_HWINTRINSIC_NM(Vector3, Sqrt, "SquareRoot", // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Vector4 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, get_One, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_One, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -133,6 +149,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -141,6 +159,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, op_Multiply, SIMD_AS_HWINTRINSIC_ID(Vector4, op_Subtraction, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Subtraction, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_UnaryNegation, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_UnaryNegation, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Sqrt, "SquareRoot", 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Sqrt, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Subtract, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Subtract, NI_Illegal}, SimdAsHWIntrinsicFlag::None) // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // ISA ID Name NumArg Instructions Flags diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 98e4e1c8f8263..3e87093403ef5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -264,6 +264,7 @@ public readonly bool IsIdentity /// The first quaternion. /// The second quaternion. /// The quaternion that contains the summed values of and . + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Add(Quaternion value1, Quaternion value2) { @@ -528,6 +529,7 @@ public static Quaternion Multiply(Quaternion value1, Quaternion value2) /// The source quaternion. /// The scalar value. /// The scaled quaternion. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Multiply(Quaternion value1, float value2) { @@ -537,6 +539,7 @@ public static Quaternion Multiply(Quaternion value1, float value2) /// Reverses the sign of each component of the quaternion. /// The quaternion to negate. /// The negated quaternion. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Negate(Quaternion value) { @@ -615,6 +618,7 @@ public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, f /// The first quaternion. /// The second quaternion. /// The quaternion containing the values that result from subtracting each element in from its corresponding element in . + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Subtract(Quaternion value1, Quaternion value2) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 5b26752fa272f..eaa028a6ded15 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -248,6 +248,7 @@ public static Vector2 Abs(Vector2 value) /// The first vector to add. /// The second vector to add. /// The summed vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Add(Vector2 left, Vector2 right) { @@ -292,6 +293,7 @@ public static float DistanceSquared(Vector2 value1, Vector2 value2) /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Divide(Vector2 left, Vector2 right) { @@ -302,6 +304,7 @@ public static Vector2 Divide(Vector2 left, Vector2 right) /// The vector. /// The scalar value. /// The vector that results from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Divide(Vector2 left, float divisor) { @@ -366,6 +369,7 @@ public static Vector2 Min(Vector2 value1, Vector2 value2) /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(Vector2 left, Vector2 right) { @@ -376,6 +380,7 @@ public static Vector2 Multiply(Vector2 left, Vector2 right) /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(Vector2 left, float right) { @@ -386,6 +391,7 @@ public static Vector2 Multiply(Vector2 left, float right) /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(float left, Vector2 right) { @@ -395,6 +401,7 @@ public static Vector2 Multiply(float left, Vector2 right) /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Negate(Vector2 value) { @@ -438,6 +445,7 @@ public static Vector2 SquareRoot(Vector2 value) /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Subtract(Vector2 left, Vector2 right) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 3c42832bca887..93b385e80f7c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -275,6 +275,7 @@ public static Vector3 Abs(Vector3 value) /// The first vector to add. /// The second vector to add. /// The summed vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Add(Vector3 left, Vector3 right) { @@ -333,6 +334,7 @@ public static float DistanceSquared(Vector3 value1, Vector3 value2) /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Divide(Vector3 left, Vector3 right) { @@ -343,6 +345,7 @@ public static Vector3 Divide(Vector3 left, Vector3 right) /// The vector. /// The scalar value. /// The vector that results from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Divide(Vector3 left, float divisor) { @@ -407,6 +410,7 @@ public static Vector3 Min(Vector3 value1, Vector3 value2) /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(Vector3 left, Vector3 right) { @@ -417,6 +421,7 @@ public static Vector3 Multiply(Vector3 left, Vector3 right) /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(Vector3 left, float right) { @@ -427,6 +432,7 @@ public static Vector3 Multiply(Vector3 left, float right) /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(float left, Vector3 right) { @@ -436,6 +442,7 @@ public static Vector3 Multiply(float left, Vector3 right) /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Negate(Vector3 value) { @@ -480,6 +487,7 @@ public static Vector3 SquareRoot(Vector3 value) /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Subtract(Vector3 left, Vector3 right) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 3a96feb7dd93c..b7f10f25b3d36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -304,6 +304,7 @@ public static Vector4 Abs(Vector4 value) /// The first vector to add. /// The second vector to add. /// The summed vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Add(Vector4 left, Vector4 right) { @@ -348,6 +349,7 @@ public static float DistanceSquared(Vector4 value1, Vector4 value2) /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Divide(Vector4 left, Vector4 right) { @@ -358,6 +360,7 @@ public static Vector4 Divide(Vector4 left, Vector4 right) /// The vector. /// The scalar value. /// The vector that results from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Divide(Vector4 left, float divisor) { @@ -428,6 +431,7 @@ public static Vector4 Min(Vector4 value1, Vector4 value2) /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 left, Vector4 right) { @@ -438,6 +442,7 @@ public static Vector4 Multiply(Vector4 left, Vector4 right) /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 left, float right) { @@ -448,6 +453,7 @@ public static Vector4 Multiply(Vector4 left, float right) /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(float left, Vector4 right) { @@ -457,6 +463,7 @@ public static Vector4 Multiply(float left, Vector4 right) /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Negate(Vector4 value) { @@ -491,6 +498,7 @@ public static Vector4 SquareRoot(Vector4 value) /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Subtract(Vector4 left, Vector4 right) { From 192f814153a93d54bf37b76f4089d10808b97000 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 11:06:26 -0800 Subject: [PATCH 09/30] Ensure creating a plane from a vector4 is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 10 ++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 1 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 1 + .../src/System/Numerics/Plane.cs | 1 + 4 files changed, 13 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index cf848505a7cd4..5b4876a9c0d5d 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -1206,6 +1206,16 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Plane_CreateFromVector4: + { + assert(retType == TYP_VOID); + + copyBlkDst = op1; + copyBlkSrc = op2; + + break; + } + case NI_Vector2_Divide: case NI_Vector2_op_Division: case NI_Vector3_Divide: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 02bb8f3224676..e592b8a2fc711 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -39,6 +39,7 @@ // Plane Intrinsics SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 08f869dcb3543..24726038f7dde 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -39,6 +39,7 @@ // Plane Intrinsics SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index 1f4ab2ef68dea..57c15f4cff4c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs @@ -46,6 +46,7 @@ public Plane(Vector3 normal, float d) /// Creates a object from a specified four-dimensional vector. /// A vector whose first three elements describe the normal vector, and whose defines the distance along that normal from the origin. + [Intrinsic] public Plane(Vector4 value) { Normal = new Vector3(value.X, value.Y, value.Z); From bc510bbd87177cdb9382240da0a6f6c96dd812e8 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 11:31:48 -0800 Subject: [PATCH 10/30] Ensure accessing the Normal field of a Plane is efficient --- src/coreclr/jit/lclmorph.cpp | 85 ++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index ce52720fe33ed..775fb3f73f7ea 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1156,16 +1156,32 @@ class LocalAddressVisitor final : public GenTreeVisitor break; #ifdef FEATURE_HW_INTRINSICS + // We have two cases we want to handle: + // 1. Vector2/3/4 and Quaternion where we have 4x float fields + // 2. Plane where we have 1x Vector3 and 1x float field + case IndirTransform::GetElement: { + GenTree* hwiNode = nullptr; var_types elementType = indir->TypeGet(); - assert(elementType == TYP_FLOAT); + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + + if (elementType == TYP_FLOAT) + { + GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType)); + hwiNode = m_compiler->gtNewSimdGetElementNode(elementType, lclNode, indexNode, CORINFO_TYPE_FLOAT, + genTypeSize(varDsc), + /* isSimdAsHWIntrinsic */ true); + } + else + { + assert(elementType == TYP_SIMD12); + assert(genTypeSize(varDsc) == 16); + hwiNode = + m_compiler->gtNewSimdHWIntrinsicNode(elementType, lclNode, NI_Vector128_AsVector3, + CORINFO_TYPE_FLOAT, 16, /* isSimdAsHWIntrinsic */ true); + } - lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); - GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType)); - GenTree* hwiNode = m_compiler->gtNewSimdGetElementNode(elementType, lclNode, indexNode, - CORINFO_TYPE_FLOAT, genTypeSize(varDsc), - /* isSimdAsHWIntrinsic */ false); indir = hwiNode; *val.Use() = hwiNode; } @@ -1174,17 +1190,32 @@ class LocalAddressVisitor final : public GenTreeVisitor case IndirTransform::WithElement: { assert(user->OperIs(GT_ASG) && (user->gtGetOp1() == indir)); + + GenTree* hwiNode = nullptr; var_types elementType = indir->TypeGet(); - assert(elementType == TYP_FLOAT); - - lclNode = BashToLclVar(indir, lclNum); - GenTree* simdLclNode = m_compiler->gtNewLclvNode(lclNum, varDsc->TypeGet()); - GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType)); - GenTree* elementNode = user->gtGetOp2(); - user->AsOp()->gtOp2 = - m_compiler->gtNewSimdWithElementNode(varDsc->TypeGet(), simdLclNode, indexNode, elementNode, - CORINFO_TYPE_FLOAT, genTypeSize(varDsc), - /* isSimdAsHWIntrinsic */ false); + lclNode = BashToLclVar(indir, lclNum); + GenTree* simdLclNode = m_compiler->gtNewLclvNode(lclNum, varDsc->TypeGet()); + GenTree* elementNode = user->gtGetOp2(); + + if (elementType == TYP_FLOAT) + { + GenTree* indexNode = m_compiler->gtNewIconNode(val.Offset() / genTypeSize(elementType)); + hwiNode = m_compiler->gtNewSimdWithElementNode(varDsc->TypeGet(), simdLclNode, indexNode, + elementNode, CORINFO_TYPE_FLOAT, genTypeSize(varDsc), + /* isSimdAsHWIntrinsic */ true); + } + else + { + assert(elementType == TYP_SIMD12); + assert(varDsc->TypeGet() == TYP_SIMD16); + + GenTree* indexNode = m_compiler->gtNewIconNode(3, TYP_INT); + hwiNode = m_compiler->gtNewSimdWithElementNode(TYP_SIMD16, simdLclNode, indexNode, elementNode, + CORINFO_TYPE_FLOAT, 16, + /* isSimdAsHWIntrinsic */ true); + } + + user->AsOp()->gtOp2 = hwiNode; user->ChangeType(varDsc->TypeGet()); } break; @@ -1300,10 +1331,26 @@ class LocalAddressVisitor final : public GenTreeVisitor } #ifdef FEATURE_HW_INTRINSICS - if (varTypeIsSIMD(varDsc) && indir->TypeIs(TYP_FLOAT) && ((val.Offset() % genTypeSize(TYP_FLOAT)) == 0) && - m_compiler->IsBaselineSimdIsaSupported()) + if (varTypeIsSIMD(varDsc)) { - return isDef ? IndirTransform::WithElement : IndirTransform::GetElement; + // We have two cases we want to handle: + // 1. Vector2/3/4 and Quaternion where we have 4x float fields + // 2. Plane where we have 1x Vector3 and 1x float field + + if (indir->TypeIs(TYP_FLOAT)) + { + if (((val.Offset() % genTypeSize(TYP_FLOAT)) == 0) && m_compiler->IsBaselineSimdIsaSupported()) + { + return isDef ? IndirTransform::WithElement : IndirTransform::GetElement; + } + } + else if (indir->TypeIs(TYP_SIMD12)) + { + if ((val.Offset() == 0) && m_compiler->IsBaselineSimdIsaSupported()) + { + return isDef ? IndirTransform::WithElement : IndirTransform::GetElement; + } + } } #endif // FEATURE_HW_INTRINSICS From dd3746f3ce59cf6edd92052bfbc19fd205b8966c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 12:30:38 -0800 Subject: [PATCH 11/30] Ensure Quaternion and Plane return the correct SimdAsHWIntrinsicClassId --- src/coreclr/jit/simdashwintrinsic.cpp | 78 ++++++++++++++++++++------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 5b4876a9c0d5d..2fac6899db648 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -125,35 +125,75 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(const char* classN { assert(className != nullptr); - if ((enclosingClassName != nullptr) || (className[0] != 'V')) + if (enclosingClassName != nullptr) { + assert(!"Unrecognized SimdAsHWIntrinsic"); return SimdAsHWIntrinsicClassId::Unknown; } - if (strcmp(className, "Vector2") == 0) - { - return SimdAsHWIntrinsicClassId::Vector2; - } - if (strcmp(className, "Vector3") == 0) - { - return SimdAsHWIntrinsicClassId::Vector3; - } - if (strcmp(className, "Vector4") == 0) - { - return SimdAsHWIntrinsicClassId::Vector4; - } - if ((strcmp(className, "Vector") == 0) || (strcmp(className, "Vector`1") == 0)) + + switch (className[0]) { -#if defined(TARGET_XARCH) - if (sizeOfVectorT == 32) + case 'P': { - return SimdAsHWIntrinsicClassId::VectorT256; + if (strcmp(className, "Plane") == 0) + { + return SimdAsHWIntrinsicClassId::Plane; + } + break; } + + case 'Q': + { + if (strcmp(className, "Quaternion") == 0) + { + return SimdAsHWIntrinsicClassId::Quaternion; + } + break; + } + + case 'V': + { + if (strncmp(className, "Vector", 6) != 0) + { + break; + } + + className += 6; + + if (strcmp(className, "2") == 0) + { + return SimdAsHWIntrinsicClassId::Vector2; + } + else if (strcmp(className, "3") == 0) + { + return SimdAsHWIntrinsicClassId::Vector3; + } + else if (strcmp(className, "4") == 0) + { + return SimdAsHWIntrinsicClassId::Vector4; + } + else if ((className[0] == '\0') || (strcmp(className, "`1") == 0)) + { +#if defined(TARGET_XARCH) + if (sizeOfVectorT == 32) + { + return SimdAsHWIntrinsicClassId::VectorT256; + } #endif // TARGET_XARCH - assert(sizeOfVectorT == 16); - return SimdAsHWIntrinsicClassId::VectorT128; + assert(sizeOfVectorT == 16); + return SimdAsHWIntrinsicClassId::VectorT128; + } + break; + } + + default: + { + break; + } } + assert(!"Unrecognized SimdAsHWIntrinsic"); return SimdAsHWIntrinsicClassId::Unknown; } From 78e1317782f66407b4c72b5ad4d5def0263d3d1a Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 28 Jan 2023 14:38:55 -0800 Subject: [PATCH 12/30] Specially optimize Create(Dot(..., ...)) and Create(Sqrt(Dot(..., ...))) --- src/coreclr/jit/lowerarmarch.cpp | 38 +++++++++---- src/coreclr/jit/lowerxarch.cpp | 87 +++++++++++++++++++++-------- src/coreclr/jit/morph.cpp | 94 ++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 33 deletions(-) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 70bb2b2957dfc..a9c981e46d14f 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1604,6 +1604,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) assert(varTypeIsArithmetic(simdBaseType)); assert(simdSize != 0); + // We support the return type being a SIMD for floating-point as a special optimization + assert(varTypeIsArithmetic(node) || (varTypeIsSIMD(node) && varTypeIsFloating(simdBaseType))); + GenTree* op1 = node->Op(1); GenTree* op2 = node->Op(2); @@ -1859,19 +1862,34 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) } } - // We will be constructing the following parts: - // ... - // /--* tmp2 simd16 - // node = * HWINTRINSIC simd16 T ToScalar + if (varTypeIsSIMD(node->gtType)) + { + // We're producing a vector result, so just return the result directly - // This is roughly the following managed code: - // ... - // return tmp2.ToScalar(); + LIR::Use use; - node->ResetHWIntrinsicId((simdSize == 8) ? NI_Vector64_ToScalar : NI_Vector128_ToScalar, tmp2); + if (BlockRange().TryGetUse(node, &use)) + { + use.ReplaceWith(tmp2); + } - LowerNode(node); - return node->gtNext; + BlockRange().Remove(node); + return tmp2->gtNext; + } + else + { + // We will be constructing the following parts: + // ... + // /--* tmp2 simd16 + // node = * HWINTRINSIC simd16 T ToScalar + + // This is roughly the following managed code: + // ... + // return tmp2.ToScalar(); + + node->ResetHWIntrinsicId((simdSize == 8) ? NI_Vector64_ToScalar : NI_Vector128_ToScalar, tmp2); + return LowerNode(node); + } } #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 81940f9a90ad9..db60f2eb00d82 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -3590,6 +3590,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) assert(varTypeIsArithmetic(simdBaseType)); assert(simdSize != 0); + // We support the return type being a SIMD for floating-point as a special optimization + assert(varTypeIsArithmetic(node) || (varTypeIsSIMD(node) && varTypeIsFloating(simdBaseType))); + GenTree* op1 = node->Op(1); GenTree* op2 = node->Op(2); @@ -3753,25 +3756,36 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) if (simdSize == 8) { - idx = comp->gtNewIconNode(0x31, TYP_INT); + idx = comp->gtNewIconNode(0x3F, TYP_INT); } else if (simdSize == 12) { - idx = comp->gtNewIconNode(0x71, TYP_INT); + idx = comp->gtNewIconNode(0x7F, TYP_INT); } else { assert(simdSize == 16); - idx = comp->gtNewIconNode(0xF1, TYP_INT); + idx = comp->gtNewIconNode(0xFF, TYP_INT); } BlockRange().InsertBefore(node, idx); - tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType, - simdSize); - BlockRange().InsertAfter(idx, tmp3); - LowerNode(tmp3); + if (varTypeIsSIMD(node->gtType)) + { + // We're producing a vector result, so just emit DotProduct directly + node->ResetHWIntrinsicId(NI_SSE41_DotProduct, comp, op1, op2, idx); + } + else + { + // We're producing a scalar result, so we only need the result in element 0 + idx->AsIntCon()->gtIconVal &= 0xF1; - node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3); + tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, + simdBaseJitType, simdSize); + BlockRange().InsertAfter(idx, tmp3); + LowerNode(tmp3); + + node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3); + } return LowerNode(node); } @@ -3804,15 +3818,26 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // var tmp3 = Avx.DotProduct(op1, op2, 0x31); // return tmp3.ToScalar(); - idx = comp->gtNewIconNode(0x31, TYP_INT); + idx = comp->gtNewIconNode(0x33, TYP_INT); BlockRange().InsertBefore(node, idx); - tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType, - simdSize); - BlockRange().InsertAfter(idx, tmp3); - LowerNode(tmp3); + if (varTypeIsSIMD(node->gtType)) + { + // We're producing a vector result, so just emit DotProduct directly + node->ResetHWIntrinsicId(NI_SSE41_DotProduct, comp, op1, op2, idx); + } + else + { + // We're producing a scalar result, so we only need the result in element 0 + idx->AsIntCon()->gtIconVal &= 0x31; + + tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, + simdBaseJitType, simdSize); + BlockRange().InsertAfter(idx, tmp3); + LowerNode(tmp3); - node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3); + node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp3); + } return LowerNode(node); } @@ -4191,18 +4216,34 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) node->SetSimdSize(16); } - // We will be constructing the following parts: - // ... - // /--* tmp1 simd16 - // node = * HWINTRINSIC simd16 T ToScalar + if (varTypeIsSIMD(node->gtType)) + { + // We're producing a vector result, so just return the result directly - // This is roughly the following managed code: - // ... - // return tmp1.ToScalar(); + LIR::Use use; - node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp1); + if (BlockRange().TryGetUse(node, &use)) + { + use.ReplaceWith(tmp1); + } - return LowerNode(node); + BlockRange().Remove(node); + return tmp1->gtNext; + } + else + { + // We will be constructing the following parts: + // ... + // /--* tmp1 simd16 + // node = * HWINTRINSIC simd16 T ToScalar + + // This is roughly the following managed code: + // ... + // return tmp1.ToScalar(); + + node->ResetHWIntrinsicId(NI_Vector128_ToScalar, tmp1); + return LowerNode(node); + } } //---------------------------------------------------------------------------------------------- diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c2aab0c11c7d0..fa03aacb2c594 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -10738,6 +10738,100 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node) return vecCon; } + NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + + switch (intrinsicId) + { +#if defined(TARGET_ARM64) + case NI_Vector64_Create: +#endif // TARGET_ARM64 + case NI_Vector128_Create: + { + // The `Dot` API returns a scalar. However, many common usages require it to + // be then immediately broadcast back to a vector so that it can be used in + // a subsequent operation. One of the most common is normalizing a vector + // which is effectively `value / value.Length` where `Length` is + // `Sqrt(Dot(value, value))` + // + // In order to ensure that developers can still utilize this efficiently, we + // will look for two common patterns: + // * Create(Dot(..., ...)) + // * Create(Sqrt(Dot(..., ...))) + // + // When these exist, we'll avoid converting to a scalar at all and just + // keep everything as a vector. However, we only do this for Vector64/Vector128 + // and only for float/double. + // + // We don't do this for Vector256 since that is xarch only and doesn't trivially + // support operations which cross the upper and lower 128-bit lanes + + if (node->GetOperandCount() != 1) + { + break; + } + + if (!varTypeIsFloating(node->GetSimdBaseType())) + { + break; + } + + GenTree* op1 = node->Op(1); + GenTree* sqrt = nullptr; + + if (op1->OperIs(GT_INTRINSIC)) + { + if (op1->AsIntrinsic()->gtIntrinsicName != NI_System_Math_Sqrt) + { + break; + } + + sqrt = op1; + op1 = op1->gtGetOp1(); + } + + if (!op1->OperIs(GT_HWINTRINSIC)) + { + break; + } + + GenTreeHWIntrinsic* hwop1 = op1->AsHWIntrinsic(); + +#if defined(TARGET_ARM64) + if ((hwop1->GetHWIntrinsicId() != NI_Vector64_Dot) && (hwop1->GetHWIntrinsicId() != NI_Vector128_Dot)) +#else + if (hwop1->GetHWIntrinsicId() != NI_Vector128_Dot) +#endif + { + break; + } + + unsigned simdSize = node->GetSimdSize(); + var_types simdType = getSIMDTypeForSize(simdSize); + + hwop1->gtType = simdType; + + if (sqrt != nullptr) + { + CorInfoType simdBaseJitType = node->GetSimdBaseJitType(); + node = gtNewSimdSqrtNode(simdType, hwop1, simdBaseJitType, simdSize, node->IsSimdAsHWIntrinsic()) + ->AsHWIntrinsic(); + DEBUG_DESTROY_NODE(sqrt); + } + else + { + node = hwop1; + } + + INDEBUG(node->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + return node; + } + + default: + { + break; + } + } + return node; } From 623c44076a615620794d65f15f6e4066a092d9e5 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 06:08:12 -0800 Subject: [PATCH 13/30] Ensure vector clamp is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 10 ++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 3 +++ src/coreclr/jit/simdashwintrinsiclistxarch.h | 3 +++ .../src/System/Numerics/Vector2.cs | 1 + .../src/System/Numerics/Vector3.cs | 1 + .../src/System/Numerics/Vector4.cs | 1 + 6 files changed, 19 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 2fac6899db648..9f591d63f1626 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -1691,6 +1691,16 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, switch (intrinsic) { + case NI_Vector2_Clamp: + case NI_Vector3_Clamp: + case NI_Vector4_Clamp: + { + GenTree* maxNode = gtNewSimdMaxNode(retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + return gtNewSimdMinNode(retType, maxNode, op3, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_ConditionalSelect: #if defined(TARGET_XARCH) case NI_VectorT256_ConditionalSelect: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index e592b8a2fc711..448386798a24c 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -73,6 +73,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Subtract, // Vector2 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -103,6 +104,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Subtract, // Vector3 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) @@ -135,6 +137,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Subtract, // Vector4 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 24726038f7dde..3997e3baaf0f3 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -73,6 +73,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Subtract, // Vector2 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector2, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -103,6 +104,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Subtract, // Vector3 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector3, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) @@ -135,6 +137,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Subtract, // Vector4 Intrinsics SIMD_AS_HWINTRINSIC_ID(Vector4, Abs, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Abs, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index eaa028a6ded15..f334c8da2df1d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -260,6 +260,7 @@ public static Vector2 Add(Vector2 left, Vector2 right) /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 93b385e80f7c7..7a1b1c005376c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -287,6 +287,7 @@ public static Vector3 Add(Vector3 left, Vector3 right) /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index b7f10f25b3d36..c2ea4bbd1c852 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -316,6 +316,7 @@ public static Vector4 Add(Vector4 left, Vector4 right) /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) { From 20db9dc7ac44d8e198cdf26bd9f7a56737dccf8b Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 06:46:59 -0800 Subject: [PATCH 14/30] Ensure vector lerp is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 59 +++++++++++++++++++ src/coreclr/jit/simdashwintrinsic.h | 9 +++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 3 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 3 + .../src/System/Numerics/Vector2.cs | 1 + .../src/System/Numerics/Vector3.cs | 1 + .../src/System/Numerics/Vector4.cs | 1 + 7 files changed, 77 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 9f591d63f1626..3ce6cb422f472 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -374,6 +374,8 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, 2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); } + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); @@ -1158,6 +1160,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, 2 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); } + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); argType = JITtype2varType(strip(info.compCompHnd->getArgType(sig, arg2, &argClass))); op2 = getArgForHWIntrinsic(argType, argClass); @@ -1664,6 +1668,12 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, 3 DEBUGARG("Spilling op1 side effects for SimdAsHWIntrinsic")); } + if (SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic) && (newobjThis == nullptr)) + { + impSpillSideEffect(true, verCurrentState.esStackDepth - + 2 DEBUGARG("Spilling op2 side effects for SimdAsHWIntrinsic")); + } + CORINFO_ARG_LIST_HANDLE arg2 = isInstanceMethod ? argList : info.compCompHnd->getArgNext(argList); CORINFO_ARG_LIST_HANDLE arg3 = info.compCompHnd->getArgNext(arg2); @@ -1710,6 +1720,53 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Vector2_Lerp: + case NI_Vector3_Lerp: + case NI_Vector4_Lerp: + { + // We generate nodes equivalent to `(op1 * (1.0f - op3)) + (op2 * op3)` + // optimizing for xarch by doing a single broadcast and for arm64 by + // using multiply by scalar + + assert(simdBaseType == TYP_FLOAT); + +#if defined(TARGET_XARCH) + // op3 = broadcast(op3) + op3 = gtNewSimdCreateBroadcastNode(retType, op3, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); +#endif // TARGET_XARCH + + // clonedOp3 = op3 + GenTree* clonedOp3; + op3 = impCloneExpr(op3, &clonedOp3, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op3 for vector lerp")); + +#if defined(TARGET_XARCH) + // op3 = 1.0f - op3 + GenTree* oneCon = gtNewOneConNode(retType, simdBaseType); + op3 = gtNewSimdBinOpNode(GT_SUB, retType, oneCon, op3, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); +#elif defined(TARGET_ARM64) + // op3 = 1.0f - op3 + GenTree* oneCon = gtNewOneConNode(simdBaseType); + op3 = gtNewOperNode(GT_SUB, TYP_FLOAT, oneCon, op3); +#else +#error Unsupported platform +#endif + + // op1 *= op3 + op1 = gtNewSimdBinOpNode(GT_MUL, retType, op1, op3, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + // op2 *= clonedOp3 + op2 = gtNewSimdBinOpNode(GT_MUL, retType, op2, clonedOp3, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + // return op1 + op2 + return gtNewSimdBinOpNode(GT_ADD, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_StoreUnsafeIndex: #if defined(TARGET_XARCH) case NI_VectorT256_StoreUnsafeIndex: @@ -1839,6 +1896,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { assert(isInstanceMethod); assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)); + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); if (newobjThis == nullptr) { @@ -1959,6 +2017,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { assert(isInstanceMethod); assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)); + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); if (newobjThis == nullptr) { diff --git a/src/coreclr/jit/simdashwintrinsic.h b/src/coreclr/jit/simdashwintrinsic.h index a7792d766eb32..556e937afe9ba 100644 --- a/src/coreclr/jit/simdashwintrinsic.h +++ b/src/coreclr/jit/simdashwintrinsic.h @@ -36,6 +36,9 @@ enum class SimdAsHWIntrinsicFlag : unsigned int // Indicates that side effects need to be spilled for op1 SpillSideEffectsOp1 = 0x20, + + // Indicates that side effects need to be spilled for op2 + SpillSideEffectsOp2 = 0x40, }; inline SimdAsHWIntrinsicFlag operator~(SimdAsHWIntrinsicFlag value) @@ -147,6 +150,12 @@ struct SimdAsHWIntrinsicInfo SimdAsHWIntrinsicFlag flags = lookupFlags(id); return (flags & SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) == SimdAsHWIntrinsicFlag::SpillSideEffectsOp1; } + + static bool SpillSideEffectsOp2(NamedIntrinsic id) + { + SimdAsHWIntrinsicFlag flags = lookupFlags(id); + return (flags & SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) == SimdAsHWIntrinsicFlag::SpillSideEffectsOp2; + } }; #endif // _SIMD_AS_HWINTRINSIC_H_ diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 448386798a24c..e5438edf9e457 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -83,6 +83,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -116,6 +117,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -151,6 +153,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 3997e3baaf0f3..2680d15e45d77 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -83,6 +83,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -116,6 +117,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -151,6 +153,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index f334c8da2df1d..16e734975d08a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -332,6 +332,7 @@ public static float Dot(Vector2 value1, Vector2 value2) /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 7a1b1c005376c..b9988afd85fe3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -371,6 +371,7 @@ public static float Dot(Vector3 vector1, Vector3 vector2) /// The second vector. /// A value between 0 and 1 that indicates the weight of . /// The interpolated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index c2ea4bbd1c852..bef086aaac560 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -390,6 +390,7 @@ public static float Dot(Vector4 vector1, Vector4 vector2) /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount) { From 186bf95bb6a4c21da21e5479799cb0ecb9e6a61e Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 06:57:31 -0800 Subject: [PATCH 15/30] Ensure vector length is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 29 +++++++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 8 +++++ src/coreclr/jit/simdashwintrinsiclistxarch.h | 8 +++++ .../src/System/Numerics/Quaternion.cs | 2 ++ .../src/System/Numerics/Vector2.cs | 2 ++ .../src/System/Numerics/Vector3.cs | 2 ++ .../src/System/Numerics/Vector4.cs | 2 ++ 7 files changed, 53 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 3ce6cb422f472..b13482d3724e8 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -943,6 +943,35 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdFloorNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Length: + case NI_Vector2_Length: + case NI_Vector3_Length: + case NI_Vector4_Length: + { + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector length")); + + op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + return new (this, GT_INTRINSIC) GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, + NO_METHOD_HANDLE); + } + + case NI_Quaternion_LengthSquared: + case NI_Vector2_LengthSquared: + case NI_Vector3_LengthSquared: + case NI_Vector4_LengthSquared: + { + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector length squared")); + + return gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_Load: case NI_VectorT128_LoadUnsafe: #if defined(TARGET_XARCH) diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index e5438edf9e457..103f3b74c9bab 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -56,6 +56,8 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -83,6 +85,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector2, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -117,6 +121,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector3, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -153,6 +159,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector4, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 2680d15e45d77..f2d15057e8713 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -56,6 +56,8 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -83,6 +85,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, get_One, SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitX, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitX, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector2, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector2, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector2, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -117,6 +121,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitX, SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitY, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitY, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector3, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector3, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector3, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -153,6 +159,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitY, SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitZ, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitZ, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_UnitW, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_UnitW, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) +SIMD_AS_HWINTRINSIC_ID(Vector4, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Vector4, Lerp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Lerp, NI_Illegal}, SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::SpillSideEffectsOp2) SIMD_AS_HWINTRINSIC_ID(Vector4, Max, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Max, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 3e87093403ef5..28b6a7b5bf8c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -669,6 +669,7 @@ public override readonly int GetHashCode() /// Calculates the length of the quaternion. /// The computed length of the quaternion. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -678,6 +679,7 @@ public readonly float Length() /// Calculates the squared length of the quaternion. /// The length squared of the quaternion. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 16e734975d08a..23dfe3b4a4cff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -653,6 +653,7 @@ public override readonly int GetHashCode() /// Returns the length of the vector. /// The vector's length. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -664,6 +665,7 @@ public readonly float Length() /// The vector's length squared. /// This operation offers better performance than a call to the method. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index b9988afd85fe3..315ba8b163b8f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -673,6 +673,7 @@ public override readonly int GetHashCode() /// Returns the length of this vector object. /// The vector's length. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -684,6 +685,7 @@ public readonly float Length() /// The vector's length squared. /// This operation offers better performance than a call to the method. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index bef086aaac560..e3b94533267ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -765,6 +765,7 @@ public override readonly int GetHashCode() /// Returns the length of this vector object. /// The vector's length. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -776,6 +777,7 @@ public readonly float Length() /// The vector's length squared. /// This operation offers better performance than a call to the method. /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { From a22827f0a9c55ad72c17d18bc1ca7b0342eec0ef Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 07:13:29 -0800 Subject: [PATCH 16/30] Ensure vector normalize is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 23 ++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 5 +++ src/coreclr/jit/simdashwintrinsiclistxarch.h | 5 +++ .../src/System/Numerics/Quaternion.cs | 31 ++++++++++++------- .../src/System/Numerics/Vector2.cs | 1 + .../src/System/Numerics/Vector3.cs | 1 + .../src/System/Numerics/Vector4.cs | 1 + 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index b13482d3724e8..a96ec2c470929 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -1037,6 +1037,28 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Normalize: + case NI_Vector2_Normalize: + case NI_Vector3_Normalize: + case NI_Vector4_Normalize: + { + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector normalize (1)")); + + GenTree* clonedOp2; + clonedOp1 = impCloneExpr(clonedOp1, &clonedOp2, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for vector normalize (2)")); + + op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + op1 = gtNewSimdSqrtNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); + + return gtNewSimdBinOpNode(GT_DIV, retType, clonedOp2, op1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_OnesComplement: case NI_VectorT128_op_OnesComplement: #if defined(TARGET_XARCH) @@ -1289,6 +1311,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Quaternion_Divide: case NI_Vector2_Divide: case NI_Vector2_op_Division: case NI_Vector3_Divide: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 103f3b74c9bab..30446c34f1e63 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -52,6 +52,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -60,6 +61,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -92,6 +94,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Max, SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -128,6 +131,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Max, SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -166,6 +170,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Max, SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index f2d15057e8713..0cebeed33c9be 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -52,6 +52,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -60,6 +61,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -92,6 +94,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Max, SIMD_AS_HWINTRINSIC_ID(Vector2, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -128,6 +131,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Max, SIMD_AS_HWINTRINSIC_ID(Vector3, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -166,6 +170,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Max, SIMD_AS_HWINTRINSIC_ID(Vector4, Min, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Min, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Negate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Negate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, Normalize, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Normalize, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Addition, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Addition, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Division, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Division, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 28b6a7b5bf8c1..4f0b73dabb641 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -437,6 +437,22 @@ public static Quaternion Divide(Quaternion value1, Quaternion value2) return value1 / value2; } + /// Divides the specified quaternion by a specified scalar value. + /// The quaternion. + /// The scalar value. + /// The quaternion that results from the division. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Quaternion Divide(Quaternion left, float divisor) + { + return new Quaternion( + left.X / divisor, + left.Y / divisor, + left.Z / divisor, + left.W / divisor + ); + } + /// Calculates the dot product of two quaternions. /// The first quaternion. /// The second quaternion. @@ -549,20 +565,11 @@ public static Quaternion Negate(Quaternion value) /// Divides each component of a specified by its length. /// The quaternion to normalize. /// The normalized quaternion. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Normalize(Quaternion value) { - Quaternion ans; - - float ls = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; - - float invNorm = 1.0f / MathF.Sqrt(ls); - - ans.X = value.X * invNorm; - ans.Y = value.Y * invNorm; - ans.Z = value.Z * invNorm; - ans.W = value.W * invNorm; - - return ans; + return Divide(value, value.Length()); } /// Interpolates between two quaternions, using spherical linear interpolation. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 23dfe3b4a4cff..6a7114fe4639b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -413,6 +413,7 @@ public static Vector2 Negate(Vector2 value) /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Normalize(Vector2 value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 315ba8b163b8f..7aaf2dd51f360 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -454,6 +454,7 @@ public static Vector3 Negate(Vector3 value) /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Normalize(Vector3 value) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index e3b94533267ad..356f8a5e17f87 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -475,6 +475,7 @@ public static Vector4 Negate(Vector4 value) /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Normalize(Vector4 vector) { From db1541b112c9845289e8671090ebbb7d3bb65b5a Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 07:20:30 -0800 Subject: [PATCH 17/30] Ensure vector distance is intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 33 +++++++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 6 ++++ src/coreclr/jit/simdashwintrinsiclistxarch.h | 6 ++++ .../src/System/Numerics/Vector2.cs | 2 ++ .../src/System/Numerics/Vector3.cs | 2 ++ .../src/System/Numerics/Vector4.cs | 2 ++ 6 files changed, 51 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index a96ec2c470929..05673673d008c 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -935,6 +935,39 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCeilNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } + case NI_Vector2_Distance: + case NI_Vector3_Distance: + case NI_Vector4_Distance: + { + op1 = gtNewSimdBinOpNode(GT_SUB, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone diff for vector distance")); + + op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + return new (this, GT_INTRINSIC) GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, + NO_METHOD_HANDLE); + } + + case NI_Vector2_DistanceSquared: + case NI_Vector3_DistanceSquared: + case NI_Vector4_DistanceSquared: + { + op1 = gtNewSimdBinOpNode(GT_SUB, retType, op1, op2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone diff for vector distance squared")); + + return gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_VectorT128_Floor: #if defined(TARGET_XARCH) case NI_VectorT256_Floor: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 30446c34f1e63..81dc46a692ee0 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -80,6 +80,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Add, SIMD_AS_HWINTRINSIC_ID(Vector2, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector2, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -116,6 +118,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -154,6 +158,8 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 0cebeed33c9be..1e994dcfcaab0 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -80,6 +80,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector2, Add, SIMD_AS_HWINTRINSIC_ID(Vector2, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector2, Create, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector2, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector2, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector2, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector2, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector2_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -116,6 +118,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) @@ -154,6 +158,8 @@ SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 6a7114fe4639b..b8368238946ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -272,6 +272,7 @@ public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector2 value1, Vector2 value2) { @@ -283,6 +284,7 @@ public static float Distance(Vector2 value1, Vector2 value2) /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector2 value1, Vector2 value2) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 7aaf2dd51f360..3b624fb91d3b5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -313,6 +313,7 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector3 value1, Vector3 value2) { @@ -324,6 +325,7 @@ public static float Distance(Vector3 value1, Vector3 value2) /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector3 value1, Vector3 value2) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 356f8a5e17f87..0e275640c1fc0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -328,6 +328,7 @@ public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector4 value1, Vector4 value2) { @@ -339,6 +340,7 @@ public static float Distance(Vector4 value1, Vector4 value2) /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector4 value1, Vector4 value2) { From 22629026bfdc51ea211ae469224060b3655956bd Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 07:42:05 -0800 Subject: [PATCH 18/30] Optimize the vector transform by matrix methods --- .../src/System/Numerics/Vector2.cs | 53 +++++++++++++------ .../src/System/Numerics/Vector3.cs | 25 +++++---- .../src/System/Numerics/Vector4.cs | 33 +++++++----- 3 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index b8368238946ce..e57dee217803f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -430,7 +430,7 @@ public static Vector2 Normalize(Vector2 value) public static Vector2 Reflect(Vector2 vector, Vector2 normal) { float dot = Dot(vector, normal); - return vector - (2.0f * dot * normal); + return vector - (2.0f * (dot * normal)); } /// Returns a vector whose elements are the square root of each of a specified vector's elements. @@ -464,10 +464,18 @@ public static Vector2 Subtract(Vector2 left, Vector2 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Transform(Vector2 position, Matrix3x2 matrix) { - return new Vector2( - (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M31, - (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M32 - ); + return Transform(position, in matrix.AsImpl()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector2 Transform(Vector2 position, in Matrix3x2.Impl matrix) + { + Vector2 result = matrix.X * position.X; + + result += matrix.Y * position.Y; + result += matrix.Z; + + return result; } /// Transforms a vector by a specified 4x4 matrix. @@ -477,10 +485,7 @@ public static Vector2 Transform(Vector2 position, Matrix3x2 matrix) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Transform(Vector2 position, Matrix4x4 matrix) { - return new Vector2( - (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41, - (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42 - ); + return Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector2(); } /// Transforms a vector by the specified Quaternion rotation value. @@ -513,10 +518,17 @@ public static Vector2 Transform(Vector2 value, Quaternion rotation) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix) { - return new Vector2( - (normal.X * matrix.M11) + (normal.Y * matrix.M21), - (normal.X * matrix.M12) + (normal.Y * matrix.M22) - ); + return TransformNormal(normal, in matrix.AsImpl()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector2 TransformNormal(Vector2 normal, in Matrix3x2.Impl matrix) + { + Vector2 result = matrix.X * normal.X; + + result += matrix.Y * normal.Y; + + return result; } /// Transforms a vector normal by the given 4x4 matrix. @@ -526,10 +538,17 @@ public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix) { - return new Vector2( - (normal.X * matrix.M11) + (normal.Y * matrix.M21), - (normal.X * matrix.M12) + (normal.Y * matrix.M22) - ); + return TransformNormal(normal, in matrix.AsImpl()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector2 TransformNormal(Vector2 normal, in Matrix4x4.Impl matrix) + { + Vector4 result = matrix.X * normal.X; + + result += matrix.Y * normal.Y; + + return result.AsVector128().AsVector2(); } /// Copies the elements of the vector to a specified array. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 3b624fb91d3b5..c4739ce80502c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -471,7 +471,7 @@ public static Vector3 Normalize(Vector3 value) public static Vector3 Reflect(Vector3 vector, Vector3 normal) { float dot = Dot(vector, normal); - return vector - (2.0f * dot * normal); + return vector - (2.0f * (dot * normal)); } /// Returns a vector whose elements are the square root of each of a specified vector's elements. @@ -506,11 +506,7 @@ public static Vector3 Subtract(Vector3 left, Vector3 right) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Transform(Vector3 position, Matrix4x4 matrix) { - return new Vector3( - (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41, - (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42, - (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43 - ); + return Vector4.Transform(position, in matrix.AsImpl()).AsVector128().AsVector3(); } /// Transforms a vector by the specified Quaternion rotation value. @@ -548,11 +544,18 @@ public static Vector3 Transform(Vector3 value, Quaternion rotation) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix) { - return new Vector3( - (normal.X * matrix.M11) + (normal.Y * matrix.M21) + (normal.Z * matrix.M31), - (normal.X * matrix.M12) + (normal.Y * matrix.M22) + (normal.Z * matrix.M32), - (normal.X * matrix.M13) + (normal.Y * matrix.M23) + (normal.Z * matrix.M33) - ); + return TransformNormal(normal, in matrix.AsImpl()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector3 TransformNormal(Vector3 normal, in Matrix4x4.Impl matrix) + { + Vector4 result = matrix.X * normal.X; + + result += matrix.Y * normal.Y; + result += matrix.Z * normal.Z; + + return result.AsVector128().AsVector3(); } /// Copies the elements of the vector to a specified array. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 0e275640c1fc0..831b4f50d2556 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -516,13 +516,17 @@ public static Vector4 Subtract(Vector4 left, Vector4 right) /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Transform(Vector2 position, Matrix4x4 matrix) + => Transform(position, in matrix.AsImpl()); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector4 Transform(Vector2 position, in Matrix4x4.Impl matrix) { - return new Vector4( - (position.X * matrix.M11) + (position.Y * matrix.M21) + matrix.M41, - (position.X * matrix.M12) + (position.Y * matrix.M22) + matrix.M42, - (position.X * matrix.M13) + (position.Y * matrix.M23) + matrix.M43, - (position.X * matrix.M14) + (position.Y * matrix.M24) + matrix.M44 - ); + Vector4 result = matrix.X * position.X; + + result += matrix.Y * position.Y; + result += matrix.W; + + return result; } /// Transforms a two-dimensional vector by the specified Quaternion rotation value. @@ -560,13 +564,18 @@ public static Vector4 Transform(Vector2 value, Quaternion rotation) /// The transformed vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Transform(Vector3 position, Matrix4x4 matrix) + => Transform(position, in matrix.AsImpl()); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector4 Transform(Vector3 position, in Matrix4x4.Impl matrix) { - return new Vector4( - (position.X * matrix.M11) + (position.Y * matrix.M21) + (position.Z * matrix.M31) + matrix.M41, - (position.X * matrix.M12) + (position.Y * matrix.M22) + (position.Z * matrix.M32) + matrix.M42, - (position.X * matrix.M13) + (position.Y * matrix.M23) + (position.Z * matrix.M33) + matrix.M43, - (position.X * matrix.M14) + (position.Y * matrix.M24) + (position.Z * matrix.M34) + matrix.M44 - ); + Vector4 result = matrix.X * position.X; + + result += matrix.Y * position.Y; + result += matrix.Z * position.Z; + result += matrix.W; + + return result; } /// Transforms a three-dimensional vector by the specified Quaternion rotation value. From 05abc18cfc39d012cc85c23a97fa44d692aac72d Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 08:03:05 -0800 Subject: [PATCH 19/30] Ensure quaternion conjugate and inverse are intrinsic --- src/coreclr/jit/simdashwintrinsic.cpp | 42 +++++++++++++++++++ src/coreclr/jit/simdashwintrinsiclistarm64.h | 2 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 3 ++ .../src/System/Numerics/Quaternion.cs | 41 +++++++++--------- 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 05673673d008c..7c1893788dd25 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -935,6 +935,19 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdCeilNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Conjugate: + { + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = -1.0f; + vecCon->gtSimd16Val.f32[1] = -1.0f; + vecCon->gtSimd16Val.f32[2] = -1.0f; + vecCon->gtSimd16Val.f32[3] = +1.0f; + + return gtNewSimdBinOpNode(GT_MUL, retType, op1, vecCon, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_Vector2_Distance: case NI_Vector3_Distance: case NI_Vector4_Distance: @@ -976,6 +989,35 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, return gtNewSimdFloorNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } + case NI_Quaternion_Inverse: + { + GenTree* clonedOp1; + op1 = impCloneExpr(op1, &clonedOp1, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for quaternion inverse (1)")); + + GenTree* clonedOp2; + clonedOp1 = impCloneExpr(clonedOp1, &clonedOp2, NO_CLASS_HANDLE, CHECK_SPILL_ALL, + nullptr DEBUGARG("Clone op1 for quaternion inverse (2)")); + + GenTreeVecCon* vecCon = gtNewVconNode(retType); + + vecCon->gtSimd16Val.f32[0] = -1.0f; + vecCon->gtSimd16Val.f32[1] = -1.0f; + vecCon->gtSimd16Val.f32[2] = -1.0f; + vecCon->gtSimd16Val.f32[3] = +1.0f; + + GenTree* conjugate = gtNewSimdBinOpNode(GT_MUL, retType, op1, vecCon, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + op1 = gtNewSimdDotProdNode(retType, clonedOp1, clonedOp2, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + + op1 = gtNewSimdSqrtNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); + + return gtNewSimdBinOpNode(GT_DIV, retType, conjugate, op1, simdBaseJitType, simdSize, + /* isSimdAsHWIntrinsic */ true); + } + case NI_Quaternion_Length: case NI_Vector2_Length: case NI_Vector3_Length: diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 81dc46a692ee0..dfd81083ce99b 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -50,6 +50,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Quaternion Intrinsics SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Conjugate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Conjugate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -57,6 +58,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Inverse, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Inverse, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 1e994dcfcaab0..40c29f9998e84 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -50,6 +50,8 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Quaternion Intrinsics SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Conjugate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Conjugate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -57,6 +59,7 @@ SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Item, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Item, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Zero, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Zero, NI_Illegal}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(Quaternion, Inverse, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Inverse, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Length, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Length, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, LengthSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_LengthSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod) SIMD_AS_HWINTRINSIC_ID(Quaternion, Multiply, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Multiply, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 4f0b73dabb641..2fcce3c93f959 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -309,16 +309,11 @@ public static Quaternion Concatenate(Quaternion value1, Quaternion value2) /// Returns the conjugate of a specified quaternion. /// The quaternion. /// A new quaternion that is the conjugate of . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Conjugate(Quaternion value) { - Quaternion ans; - - ans.X = -value.X; - ans.Y = -value.Y; - ans.Z = -value.Z; - ans.W = value.W; - - return ans; + return Multiply(value, new Vector4(-1.0f, -1.0f, -1.0f, 1.0f)); } /// Creates a quaternion from a unit vector and an angle to rotate around the vector. @@ -470,23 +465,15 @@ public static float Dot(Quaternion quaternion1, Quaternion quaternion2) /// Returns the inverse of a quaternion. /// The quaternion. /// The inverted quaternion. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Inverse(Quaternion value) { // -1 ( a -v ) // q = ( ------------- ------------- ) // ( a^2 + |v|^2 , a^2 + |v|^2 ) - Quaternion ans; - - float ls = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; - float invNorm = 1.0f / ls; - - ans.X = -value.X * invNorm; - ans.Y = -value.Y * invNorm; - ans.Z = -value.Z * invNorm; - ans.W = value.W * invNorm; - - return ans; + return Divide(Conjugate(value), value.Length()); } /// Performs a linear interpolation between two quaternions based on a value that specifies the weighting of the second quaternion. @@ -541,6 +528,22 @@ public static Quaternion Multiply(Quaternion value1, Quaternion value2) return value1 * value2; } + /// Returns a new quaternion whose values are the product of each pair of elements in specified quaternion and vector. + /// The quaternion. + /// The vector. + /// The element-wise product vector. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Quaternion Multiply(Quaternion value1, Vector4 value2) + { + return new Quaternion( + value1.X * value2.X, + value1.Y * value2.Y, + value1.Z * value2.Z, + value1.W * value2.W + ); + } + /// Returns the quaternion that results from scaling all the components of a specified quaternion by a scalar factor. /// The source quaternion. /// The scalar value. From 6bf2e672993ced0f789907e3d265e15d4985574a Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 08:37:37 -0800 Subject: [PATCH 20/30] Fixing assert, formatting, and build failure --- src/coreclr/jit/gentree.cpp | 5 +++-- src/coreclr/jit/simdashwintrinsic.cpp | 14 +++++++------- src/coreclr/jit/simdashwintrinsiclistxarch.h | 1 - .../src/System/Numerics/Quaternion.cs | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index feec2becd40ff..039fccd0292af 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21394,7 +21394,6 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types type, bool isSimdAsHWIntrinsic) { assert(IsBaselineSimdIsaSupportedDebugOnly()); - assert(varTypeIsArithmetic(type)); var_types simdType = getSIMDTypeForSize(simdSize); assert(varTypeIsSIMD(simdType)); @@ -21406,7 +21405,9 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types type, assert(op2->TypeIs(simdType)); var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); - assert(JITtype2varType(simdBaseJitType) == type); + + // We support the return type being a SIMD for floating-point as a special optimization + assert(varTypeIsArithmetic(type) || (varTypeIsSIMD(type) && varTypeIsFloating(simdBaseType))); NamedIntrinsic intrinsic = NI_Illegal; diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 7c1893788dd25..0cdae4dfbc73b 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -962,8 +962,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); - return new (this, GT_INTRINSIC) GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, - NO_METHOD_HANDLE); + return new (this, GT_INTRINSIC) + GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, NO_METHOD_HANDLE); } case NI_Vector2_DistanceSquared: @@ -1030,8 +1030,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, op1 = gtNewSimdDotProdNode(retType, op1, clonedOp1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); - return new (this, GT_INTRINSIC) GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, - NO_METHOD_HANDLE); + return new (this, GT_INTRINSIC) + GenTreeIntrinsic(simdBaseType, op1, NI_System_Math_Sqrt, NO_METHOD_HANDLE); } case NI_Quaternion_LengthSquared: @@ -1871,12 +1871,12 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, #if defined(TARGET_XARCH) // op3 = 1.0f - op3 GenTree* oneCon = gtNewOneConNode(retType, simdBaseType); - op3 = gtNewSimdBinOpNode(GT_SUB, retType, oneCon, op3, simdBaseJitType, simdSize, + op3 = gtNewSimdBinOpNode(GT_SUB, retType, oneCon, op3, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); #elif defined(TARGET_ARM64) // op3 = 1.0f - op3 GenTree* oneCon = gtNewOneConNode(simdBaseType); - op3 = gtNewOperNode(GT_SUB, TYP_FLOAT, oneCon, op3); + op3 = gtNewOperNode(GT_SUB, TYP_FLOAT, oneCon, op3); #else #error Unsupported platform #endif @@ -1950,7 +1950,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, std::move(nodeBuilder), NI_Vector128_Create, simdBaseJitType, 16, /* isSimdAsHWIntrinsic */ true); #elif defined(TARGET_ARM64) - copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op2, op3, NI_Vector64_Create, simdBaseJitType, + copyBlkSrc = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op2, op3, NI_Vector64_Create, simdBaseJitType, 8, /* isSimdAsHWIntrinsic */ true); #else #error Unsupported platform diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index 40c29f9998e84..b4cf132ed00cc 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -52,7 +52,6 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Conjugate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Conjugate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 2fcce3c93f959..9d84d70479040 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -529,8 +529,8 @@ public static Quaternion Multiply(Quaternion value1, Quaternion value2) } /// Returns a new quaternion whose values are the product of each pair of elements in specified quaternion and vector. - /// The quaternion. - /// The vector. + /// The quaternion. + /// The vector. /// The element-wise product vector. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] From 5ca919aa0db31694295b5f8399e82430cd523837 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 29 Jan 2023 10:45:07 -0800 Subject: [PATCH 21/30] Ensure Quaternion.Inverse uses LengthSquared not Length --- src/coreclr/jit/simdashwintrinsic.cpp | 2 -- .../System.Private.CoreLib/src/System/Numerics/Quaternion.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 0cdae4dfbc73b..8fea21e198ea5 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -1012,8 +1012,6 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, op1 = gtNewSimdDotProdNode(retType, clonedOp1, clonedOp2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); - op1 = gtNewSimdSqrtNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); - return gtNewSimdBinOpNode(GT_DIV, retType, conjugate, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ true); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs index 9d84d70479040..594491fcd218d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.cs @@ -473,7 +473,7 @@ public static Quaternion Inverse(Quaternion value) // q = ( ------------- ------------- ) // ( a^2 + |v|^2 , a^2 + |v|^2 ) - return Divide(Conjugate(value), value.Length()); + return Divide(Conjugate(value), value.LengthSquared()); } /// Performs a linear interpolation between two quaternions based on a value that specifies the weighting of the second quaternion. From 9bc980613acb234579b6e0b656048244a4413014 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 30 Jan 2023 08:47:19 -0800 Subject: [PATCH 22/30] Ensure Create APIs are correctly imported as intrinsic --- src/coreclr/jit/lclmorph.cpp | 9 ++++++--- src/coreclr/jit/simdashwintrinsic.cpp | 2 +- src/coreclr/jit/simdashwintrinsiclistarm64.h | 12 ++++++------ src/coreclr/jit/simdashwintrinsiclistxarch.h | 12 ++++++------ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 775fb3f73f7ea..0e610ebf95c72 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1209,10 +1209,13 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(elementType == TYP_SIMD12); assert(varDsc->TypeGet() == TYP_SIMD16); + // We inverse the operands here and take elementNode as the main value and simdLclNode[3] as the + // new value. This gives us a new TYP_SIMD16 with all elements in the right spots + GenTree* indexNode = m_compiler->gtNewIconNode(3, TYP_INT); - hwiNode = m_compiler->gtNewSimdWithElementNode(TYP_SIMD16, simdLclNode, indexNode, elementNode, - CORINFO_TYPE_FLOAT, 16, - /* isSimdAsHWIntrinsic */ true); + hwiNode = + m_compiler->gtNewSimdWithElementNode(TYP_SIMD16, elementNode, indexNode, simdLclNode, + CORINFO_TYPE_FLOAT, 16, /* isSimdAsHWIntrinsic */ true); } user->AsOp()->gtOp2 = hwiNode; diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 8fea21e198ea5..8e6b906cf8117 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -284,7 +284,7 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic, if (SimdAsHWIntrinsicInfo::BaseTypeFromThisArg(intrinsic)) { - assert(simdBaseJitType == CORINFO_TYPE_UNDEF); + assert((simdBaseJitType == CORINFO_TYPE_UNDEF) || (simdBaseJitType == CORINFO_TYPE_VALUECLASS)); simdBaseJitType = getBaseJitTypeAndSizeOfSIMDType(clsHnd, &simdSize); } } diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index dfd81083ce99b..ff4bebaf465cc 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -38,8 +38,8 @@ // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Plane Intrinsics SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -52,7 +52,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Conjugate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Conjugate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -119,7 +119,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Add, SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -158,8 +158,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Add, SIMD_AS_HWINTRINSIC_ID(Vector4, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) +SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index b4cf132ed00cc..7ad571f4a2216 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -38,8 +38,8 @@ // ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // Plane Intrinsics SIMD_AS_HWINTRINSIC_NM(Plane, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) +SIMD_AS_HWINTRINSIC_NM(Plane, CreateFromVector4, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_CreateFromVector4, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Plane, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Equality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Equality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Plane_op_Inequality, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -52,7 +52,7 @@ SIMD_AS_HWINTRINSIC_ID(Plane, op_Inequality, SIMD_AS_HWINTRINSIC_ID(Quaternion, Add, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Add, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Conjugate, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Conjugate, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Quaternion, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Quaternion, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Quaternion, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, Dot, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_Dot, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Quaternion, get_Identity, 0, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Quaternion_get_Identity, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -119,7 +119,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector3, Add, SIMD_AS_HWINTRINSIC_ID(Vector3, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector3, Create, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector3, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Vector3, CreateFromVector2, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector3, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector3, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector3_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) @@ -158,8 +158,8 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, Add, SIMD_AS_HWINTRINSIC_ID(Vector4, Clamp, 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Clamp, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(Vector4, Create, ".ctor", 5, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Create, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) SIMD_AS_HWINTRINSIC_NM(Vector4, CreateBroadcast, ".ctor", 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateBroadcast, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) -SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1) +SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector2, ".ctor", 4, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector2, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) +SIMD_AS_HWINTRINSIC_NM(Vector4, CreateFromVector3, ".ctor", 3, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_CreateFromVector3, NI_Illegal}, SimdAsHWIntrinsicFlag::InstanceMethod | SimdAsHWIntrinsicFlag::SpillSideEffectsOp1 | SimdAsHWIntrinsicFlag::BaseTypeFromThisArg) SIMD_AS_HWINTRINSIC_ID(Vector4, Distance, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Distance, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, DistanceSquared, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_DistanceSquared, NI_Illegal}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(Vector4, Divide, 2, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Vector4_Divide, NI_Illegal}, SimdAsHWIntrinsicFlag::None) From 43e229d3d384faa809c772febe65b7068b94e986 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 30 Jan 2023 14:40:41 -0800 Subject: [PATCH 23/30] Ensure we don't assert for AltJit --- src/coreclr/jit/simdashwintrinsic.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 8e6b906cf8117..3e0a768857903 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -127,7 +127,6 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(const char* classN if (enclosingClassName != nullptr) { - assert(!"Unrecognized SimdAsHWIntrinsic"); return SimdAsHWIntrinsicClassId::Unknown; } @@ -193,7 +192,6 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(const char* classN } } - assert(!"Unrecognized SimdAsHWIntrinsic"); return SimdAsHWIntrinsicClassId::Unknown; } From b92fc1d4ae0a2a66046b4e434081c7dd315c1a4b Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 30 Jan 2023 16:38:49 -0800 Subject: [PATCH 24/30] Ensure lowering DotProd doesn't break CSE for scalar vs vector results --- src/coreclr/jit/lowerxarch.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index db60f2eb00d82..5586eb28c9bb6 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -3777,7 +3777,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) else { // We're producing a scalar result, so we only need the result in element 0 - idx->AsIntCon()->gtIconVal &= 0xF1; + // + // However, doing that would break/limit CSE and requires a partial write so + // it's better to just broadcast the value to the entire vector tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType, simdSize); @@ -3829,7 +3831,9 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) else { // We're producing a scalar result, so we only need the result in element 0 - idx->AsIntCon()->gtIconVal &= 0x31; + // + // However, doing that would break/limit CSE and requires a partial write so + // it's better to just broadcast the value to the entire vector tmp3 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, idx, NI_SSE41_DotProduct, simdBaseJitType, simdSize); From a498ac76525dcb24a15c51cddf836af7c1035a92 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 30 Jan 2023 17:23:52 -0800 Subject: [PATCH 25/30] Minimally fixup Mono for the new intrinsics --- src/mono/mono/mini/simd-intrinsics.c | 43 ++++++++++++++++++++++++++++ src/mono/mono/mini/simd-methods.h | 11 +++++++ 2 files changed, 54 insertions(+) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index cad1e0756b6f6..69aeffc9c2ece 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1834,18 +1834,30 @@ static guint16 vector2_methods[] = { SN_ctor, SN_Abs, SN_Add, + SN_Clamp, SN_CopyTo, + SN_Distance, + SN_DistanceSquared, SN_Divide, SN_Dot, SN_GetElement, + SN_Length, + SN_LengthSquared, + SN_Lerp, SN_Max, SN_Min, SN_Multiply, + SN_Negate, + SN_Normalize, SN_SquareRoot, SN_Subtract, SN_WithElement, SN_get_Item, SN_get_One, + SN_get_UnitX, + SN_get_UnitY, + SN_get_UnitZ, + SN_get_UnitW, SN_get_Zero, SN_op_Addition, SN_op_Division, @@ -1962,6 +1974,13 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f } case SN_get_Zero: return emit_xzero (cfg, klass); + case SN_get_UnitX: + case SN_get_UnitY: + case SN_get_UnitZ: + case SN_get_UnitW: { + // FIXME: + return NULL; + } case SN_get_One: { static const float r4_one = 1.0f; @@ -2034,6 +2053,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f return NULL; #endif } + case SN_Negate: case SN_op_UnaryNegation: { #if defined(TARGET_ARM64) || defined(TARGET_AMD64) return emit_simd_ins (cfg, klass, OP_NEGATION, args [0]->dreg, -1); @@ -2078,6 +2098,29 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f case SN_CopyTo: // FIXME: return NULL; + case SN_Clamp: { + if (!(!fsig->hasthis && fsig->param_count == 3 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type) && mono_metadata_type_equal (fsig->params [2], type))) + return NULL; + + MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg); + max->inst_c0 = OP_FMAX; + max->inst_c1 = MONO_TYPE_R4; + + MonoInst *min = emit_simd_ins (cfg, klass, OP_XBINOP, max->dreg, args[2]->dreg); + min->inst_c0 = OP_FMIN; + min->inst_c1 = MONO_TYPE_R4; + + return min; + } + case SN_Distance: + case SN_DistanceSquared: + case SN_Length: + case SN_LengthSquared: + case SN_Lerp: + case SN_Normalize: { + // FIXME: + return NULL; + } default: g_assert_not_reached (); } diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index 1a6a429137ee0..dbde5741fff2c 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -1,5 +1,8 @@ METHOD2(".ctor", ctor) +METHOD(Clamp) METHOD(CopyTo) +METHOD(Distance) +METHOD(DistanceSquared) METHOD(Equals) METHOD(GreaterThan) METHOD(GreaterThanAll) @@ -13,10 +16,14 @@ METHOD(LessThanAny) METHOD(LessThanOrEqual) METHOD(LessThanOrEqualAll) METHOD(LessThanOrEqualAny) +METHOD(Length) +METHOD(LengthSquared) +METHOD(Lerp) METHOD(Min) METHOD(Max) METHOD(MinScalar) METHOD(MaxScalar) +METHOD(Normalize) METHOD(PopCount) METHOD(LeadingZeroCount) METHOD(get_Count) @@ -25,6 +32,10 @@ METHOD(get_IsSupported) METHOD(get_AllBitsSet) METHOD(get_Item) METHOD(get_One) +METHOD(get_UnitX) +METHOD(get_UnitY) +METHOD(get_UnitZ) +METHOD(get_UnitW) METHOD(get_Zero) METHOD(op_Addition) METHOD(op_BitwiseAnd) From 338cca7251320edb0c6c4eb87d8b330a5c679265 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 31 Jan 2023 10:05:23 -0800 Subject: [PATCH 26/30] Ensure SN_GetElement doesn't raise an assert --- src/mono/mono/mini/simd-intrinsics.c | 53 +++++++++++++++++++--------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 69aeffc9c2ece..7a02eca80bf6b 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1123,8 +1123,22 @@ is_create_from_half_vectors_overload (MonoMethodSignature *fsig) static gboolean is_element_type_primitive (MonoType *vector_type) { - MonoType *element_type = get_vector_t_elem_type (vector_type); - return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type); + if (vector_type->type == MONO_TYPE_GENERICINST) + { + MonoType *element_type = get_vector_t_elem_type (vector_type); + return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type); + } + else + { + MonoClass *klass = mono_class_from_mono_type_internal (vector_type); + g_assert ( + !strcmp (m_class_get_name (klass), "Plane") || + !strcmp (m_class_get_name (klass), "Quaternion") || + !strcmp (m_class_get_name (klass), "Vector2") || + !strcmp (m_class_get_name (klass), "Vector3") || + !strcmp (m_class_get_name (klass), "Vector4")); + return TRUE; + } } static MonoInst* @@ -1414,17 +1428,34 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi #endif } case SN_GetElement: { + int esize; + MonoType *etype; + if (!is_element_type_primitive (fsig->params [0])) return NULL; MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); - MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; + int size = mono_class_value_size (arg_class, NULL); - int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + + if (fsig->params [0]->type == MONO_TYPE_GENERICINST) + { + etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; + esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + } + else + { + // This exists to handle the static extension methods for Vector2/3/4 and Quaterion + // which live on System.Numerics.Vector + + etype = m_class_get_byval_arg (mono_defaults.single_class); + esize = 4; + } + int elems = size / esize; MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems); MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException"); - int extract_op = type_to_xextract_op (arg0_type); - return emit_simd_ins_for_sig (cfg, klass, extract_op, -1, arg0_type, fsig, args); + int extract_op = type_to_xextract_op (etype->type); + return emit_simd_ins_for_sig (cfg, klass, extract_op, -1, etype->type, fsig, args); } case SN_GetLower: case SN_GetUpper: { @@ -1962,16 +1993,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f ins->inst_c1 = ty; return ins; } - case SN_GetElement: { - g_assert (!fsig->hasthis && fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && fsig->params [1]->type == MONO_TYPE_I4); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len); - MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException"); - MonoTypeEnum ty = etype->type; - int opcode = type_to_xextract_op (ty); - ins = emit_simd_ins (cfg, klass, opcode, args [0]->dreg, args [1]->dreg); - ins->inst_c1 = ty; - return ins; - } case SN_get_Zero: return emit_xzero (cfg, klass); case SN_get_UnitX: From d54eaf2c2d56582ba548eef59df13632113eccff Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 31 Jan 2023 13:14:27 -0800 Subject: [PATCH 27/30] Ensure get_UnitW is ordered correctly for Mono --- src/mono/mono/mini/simd-intrinsics.c | 2 +- src/mono/mono/mini/simd-methods.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 7a02eca80bf6b..f8ae5eae895c9 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1885,10 +1885,10 @@ static guint16 vector2_methods[] = { SN_WithElement, SN_get_Item, SN_get_One, + SN_get_UnitW, SN_get_UnitX, SN_get_UnitY, SN_get_UnitZ, - SN_get_UnitW, SN_get_Zero, SN_op_Addition, SN_op_Division, diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index dbde5741fff2c..e8d4af1c875ac 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -32,10 +32,10 @@ METHOD(get_IsSupported) METHOD(get_AllBitsSet) METHOD(get_Item) METHOD(get_One) +METHOD(get_UnitW) METHOD(get_UnitX) METHOD(get_UnitY) METHOD(get_UnitZ) -METHOD(get_UnitW) METHOD(get_Zero) METHOD(op_Addition) METHOD(op_BitwiseAnd) From fa1e62cae611dbf25dc97d2a7e5624513c426a2c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 31 Jan 2023 19:16:05 -0800 Subject: [PATCH 28/30] Try to fix SN_GetElement --- src/mono/mono/mini/simd-intrinsics.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index f8ae5eae895c9..b3d65f8cc1a30 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1428,34 +1428,33 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi #endif } case SN_GetElement: { - int esize; - MonoType *etype; - + int elems; + if (!is_element_type_primitive (fsig->params [0])) return NULL; + MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); - - int size = mono_class_value_size (arg_class, NULL); - + if (fsig->params [0]->type == MONO_TYPE_GENERICINST) { - etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; - esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; + int size = mono_class_value_size (arg_class, NULL); + int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + elems = size / esize; } else { // This exists to handle the static extension methods for Vector2/3/4 and Quaterion // which live on System.Numerics.Vector - etype = m_class_get_byval_arg (mono_defaults.single_class); - esize = 4; + arg0_type = MONO_TYPE_R4; + elems = 4; } - int elems = size / esize; MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems); MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException"); - int extract_op = type_to_xextract_op (etype->type); - return emit_simd_ins_for_sig (cfg, klass, extract_op, -1, etype->type, fsig, args); + int extract_op = type_to_xextract_op (arg0_type); + return emit_simd_ins_for_sig (cfg, klass, extract_op, -1, arg0_type, fsig, args); } case SN_GetLower: case SN_GetUpper: { From 4084de15970b34ce2962576018dcfbc0b4367a28 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 31 Jan 2023 19:20:09 -0800 Subject: [PATCH 29/30] Fix SN_WithElement for Mono --- src/mono/mono/mini/simd-intrinsics.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index b3d65f8cc1a30..98c16b0bcb257 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1696,13 +1696,29 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return emit_simd_ins_for_sig (cfg, klass, op, 0, arg0_type, fsig, args); } case SN_WithElement: { + int elems; + if (!is_element_type_primitive (fsig->params [0])) return NULL; + MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); - MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; - int size = mono_class_value_size (arg_class, NULL); - int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - int elems = size / esize; + + if (fsig->params [0]->type == MONO_TYPE_GENERICINST) + { + MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; + int size = mono_class_value_size (arg_class, NULL); + int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + elems = size / esize; + } + else + { + // This exists to handle the static extension methods for Vector2/3/4 and Quaterion + // which live on System.Numerics.Vector + + arg0_type = MONO_TYPE_R4; + elems = 4; + } + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, elems); MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException"); int insert_op = type_to_xinsert_op (arg0_type); From cba1d2f28672ccf21a8f52ce09c8095bb6f415c2 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 1 Feb 2023 14:21:37 -0800 Subject: [PATCH 30/30] Resolving mono formatting feedback --- src/mono/mono/mini/simd-intrinsics.c | 32 ++++++---------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 98c16b0bcb257..816c0e1972051 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1123,13 +1123,10 @@ is_create_from_half_vectors_overload (MonoMethodSignature *fsig) static gboolean is_element_type_primitive (MonoType *vector_type) { - if (vector_type->type == MONO_TYPE_GENERICINST) - { + if (vector_type->type == MONO_TYPE_GENERICINST) { MonoType *element_type = get_vector_t_elem_type (vector_type); return MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type); - } - else - { + } else { MonoClass *klass = mono_class_from_mono_type_internal (vector_type); g_assert ( !strcmp (m_class_get_name (klass), "Plane") || @@ -1435,15 +1432,12 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); - if (fsig->params [0]->type == MONO_TYPE_GENERICINST) - { + if (fsig->params [0]->type == MONO_TYPE_GENERICINST) { MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; int size = mono_class_value_size (arg_class, NULL); int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); elems = size / esize; - } - else - { + } else { // This exists to handle the static extension methods for Vector2/3/4 and Quaterion // which live on System.Numerics.Vector @@ -1703,15 +1697,12 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); - if (fsig->params [0]->type == MONO_TYPE_GENERICINST) - { + if (fsig->params [0]->type == MONO_TYPE_GENERICINST) { MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; int size = mono_class_value_size (arg_class, NULL); int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); elems = size / esize; - } - else - { + } else { // This exists to handle the static extension methods for Vector2/3/4 and Quaterion // which live on System.Numerics.Vector @@ -1886,7 +1877,6 @@ static guint16 vector2_methods[] = { SN_DistanceSquared, SN_Divide, SN_Dot, - SN_GetElement, SN_Length, SN_LengthSquared, SN_Lerp, @@ -1897,7 +1887,6 @@ static guint16 vector2_methods[] = { SN_Normalize, SN_SquareRoot, SN_Subtract, - SN_WithElement, SN_get_Item, SN_get_One, SN_get_UnitW, @@ -2042,15 +2031,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f ins->dreg = dreg; return ins; } - case SN_WithElement: { - g_assert (!fsig->hasthis && fsig->param_count == 3 && fsig->params [1]->type == MONO_TYPE_I4 && fsig->params [2]->type == MONO_TYPE_R4); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len); - MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "ArgumentOutOfRangeException"); - ins = emit_simd_ins (cfg, klass, OP_XINSERT_R4, args [0]->dreg, args [2]->dreg); - ins->sreg3 = args [1]->dreg; - ins->inst_c1 = MONO_TYPE_R4; - return ins; - } case SN_Add: case SN_Divide: case SN_Multiply: