From: Tanner Gooding Date: Thu, 2 Feb 2023 06:21:11 +0000 (-0800) Subject: Improve the codegen of the vector accelerated `System.Numerics.*` types (#81335) X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~4273 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=90401dde75a71d8e5ea24b351cffd6424b1051db;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Improve the codegen of the vector accelerated `System.Numerics.*` types (#81335) * Allow Quaternion and Plane to be imported as TYP_SIMD16 * Add some minimal intrinsification of Quaternion and Plane * Ensure Vector indexers are marked readonly * Ensure the vector constant properties are intrinsic * Ensure that the vector GetElement and WithElement APIs are intrinsic * Ensure vector division by scalar is intrinsic * Minor cleanup to vector files * Ensure vector arithmetic functions are consistently intrinsic * Ensure creating a plane from a vector4 is intrinsic * Ensure accessing the Normal field of a Plane is efficient * Ensure Quaternion and Plane return the correct SimdAsHWIntrinsicClassId * Specially optimize Create(Dot(..., ...)) and Create(Sqrt(Dot(..., ...))) * Ensure vector clamp is intrinsic * Ensure vector lerp is intrinsic * Ensure vector length is intrinsic * Ensure vector normalize is intrinsic * Ensure vector distance is intrinsic * Optimize the vector transform by matrix methods * Ensure quaternion conjugate and inverse are intrinsic * Fixing assert, formatting, and build failure * Ensure Quaternion.Inverse uses LengthSquared not Length * Ensure Create APIs are correctly imported as intrinsic * Ensure we don't assert for AltJit * Ensure lowering DotProd doesn't break CSE for scalar vs vector results * Minimally fixup Mono for the new intrinsics * Ensure SN_GetElement doesn't raise an assert * Ensure get_UnitW is ordered correctly for Mono * Try to fix SN_GetElement * Fix SN_WithElement for Mono * Resolving mono formatting feedback --- diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 2632ab5..74cf4e3 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -8417,6 +8417,8 @@ private: 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; @@ -8494,23 +8496,54 @@ private: 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: @@ -8540,6 +8573,7 @@ private: default: assert(!"Didn't find a class handle for simdType"); } + return NO_CLASS_HANDLE; } @@ -8617,9 +8651,39 @@ private: // 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/gentree.cpp b/src/coreclr/jit/gentree.cpp index 0a51c1c..f386a63 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21407,7 +21407,6 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types type, bool isSimdAsHWIntrinsic) { assert(IsBaselineSimdIsaSupportedDebugOnly()); - assert(varTypeIsArithmetic(type)); var_types simdType = getSIMDTypeForSize(simdSize); assert(varTypeIsSIMD(simdType)); @@ -21419,7 +21418,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/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index ce52720..0e610eb 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1156,16 +1156,32 @@ private: 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,35 @@ private: 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); + + // 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, elementNode, indexNode, simdLclNode, + CORINFO_TYPE_FLOAT, 16, /* isSimdAsHWIntrinsic */ true); + } + + user->AsOp()->gtOp2 = hwiNode; user->ChangeType(varDsc->TypeGet()); } break; @@ -1300,10 +1334,26 @@ private: } #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 diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 70bb2b2..a9c981e 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 81940f9..5586eb2 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,38 @@ 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 + // + // 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 - 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 +3820,28 @@ 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 + // + // 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 - 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); } @@ -4191,18 +4220,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 77453e0..f3db2e8 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -10795,6 +10795,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; } diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index d73d4d7..323300a 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 diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 6d36289..3e0a768 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -125,33 +125,71 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(const char* classN { assert(className != nullptr); - if ((enclosingClassName != nullptr) || (className[0] != 'V')) + if (enclosingClassName != nullptr) { 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; + } } return SimdAsHWIntrinsicClassId::Unknown; @@ -244,7 +282,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); } } @@ -334,6 +372,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); @@ -408,6 +448,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)); @@ -748,6 +809,61 @@ 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_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_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: case NI_Vector4_get_Zero: @@ -817,6 +933,52 @@ 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: + { + 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: @@ -825,6 +987,62 @@ 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); + + return gtNewSimdBinOpNode(GT_DIV, retType, conjugate, 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) @@ -871,8 +1089,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: @@ -885,6 +1108,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) @@ -1037,6 +1282,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); @@ -1059,8 +1306,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: @@ -1120,8 +1372,22 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Plane_CreateFromVector4: + { + assert(retType == TYP_VOID); + + copyBlkDst = op1; + copyBlkSrc = op2; + + break; + } + + case NI_Quaternion_Divide: + 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: @@ -1134,6 +1400,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 +1423,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: @@ -1189,6 +1459,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) @@ -1254,6 +1528,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,8 +1640,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: @@ -1473,8 +1754,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: @@ -1505,6 +1791,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); @@ -1532,6 +1824,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: @@ -1541,6 +1843,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: @@ -1597,7 +1946,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 @@ -1608,6 +1957,8 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } + case NI_Plane_CreateFromVector3: + case NI_Quaternion_CreateFromVector3: case NI_Vector3_CreateFromVector2: case NI_Vector4_CreateFromVector3: { @@ -1668,6 +2019,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { assert(isInstanceMethod); assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)); + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); if (newobjThis == nullptr) { @@ -1788,6 +2140,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { assert(isInstanceMethod); assert(SimdAsHWIntrinsicInfo::SpillSideEffectsOp1(intrinsic)); + assert(!SimdAsHWIntrinsicInfo::SpillSideEffectsOp2(intrinsic)); if (newobjThis == nullptr) { @@ -1824,6 +2177,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 f14b087..556e937 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, @@ -34,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) @@ -145,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 80e37fc..ff4beba 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -36,15 +36,69 @@ // 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 | 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) + +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// 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_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 | 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) +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) +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) +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 +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // 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, 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) 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, 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) +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) @@ -53,6 +107,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 @@ -60,14 +115,29 @@ 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_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) 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_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_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, 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) +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) @@ -76,6 +146,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 @@ -83,15 +154,31 @@ 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_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) 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_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, 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) +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) @@ -100,6 +187,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 24671df..7ad571f 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -36,15 +36,69 @@ // 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 | 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) + +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +// 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_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 | 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) +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) +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) +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 +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* // 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, 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) 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, 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) +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) @@ -53,6 +107,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 @@ -60,14 +115,29 @@ 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_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) 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) +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) +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) @@ -76,6 +146,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 @@ -83,15 +154,31 @@ 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_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) 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) +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) +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) @@ -100,6 +187,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.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index ce2500e..152cf86 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics 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.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index a3dc18c..03d6724 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/Plane.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Plane.cs index f60f32c..57c15f4 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,38 @@ namespace System.Numerics /// 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. + [Intrinsic] 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 +109,17 @@ namespace System.Numerics /// 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 +139,7 @@ namespace System.Numerics } } - /// 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 +158,7 @@ namespace System.Numerics } } - /// 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 +200,7 @@ namespace System.Numerics /// 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 +219,7 @@ namespace System.Numerics /// 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 +263,22 @@ namespace System.Numerics /// 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 +288,7 @@ namespace System.Numerics /// 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. [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) { @@ -295,7 +298,7 @@ namespace System.Numerics /// 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics } /// 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.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Quaternion.Extensions.cs new file mode 100644 index 0000000..7c0e561 --- /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 1546153..594491f 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 @@ using System.Runtime.Intrinsics; 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 @@ namespace System.Numerics /// 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 @@ namespace System.Numerics /// 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 @@ namespace System.Numerics /// A quaternion whose values are (0, 0, 0, 0). public static Quaternion Zero { + [Intrinsic] get => default; } @@ -65,7 +68,8 @@ namespace System.Numerics /// A quaternion whose values are (0, 0, 0, 1). public static Quaternion Identity { - get => new Quaternion(0, 0, 0, 1); + [Intrinsic] + get => new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); } /// Gets or sets the element at the specified index. @@ -74,61 +78,17 @@ namespace System.Numerics /// was less than zero or greater than the number of elements. public float this[int index] { - get => GetElement(this, index); - set => this = WithElement(this, index, value); - } + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + readonly get => this.GetElement(index); - /// 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; - } - - [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. /// if the current instance is the identity quaternion; otherwise, . - /// + /// public readonly bool IsIdentity { get => this == Identity; @@ -138,24 +98,24 @@ namespace System.Numerics /// 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 +159,9 @@ namespace System.Numerics /// 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 +174,8 @@ namespace System.Numerics /// 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 +185,7 @@ namespace System.Numerics /// 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,56 +219,52 @@ namespace System.Numerics /// 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. /// 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) { @@ -349,23 +309,18 @@ namespace System.Numerics /// 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. /// 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; @@ -477,38 +432,48 @@ namespace System.Numerics 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. /// 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. /// 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.LengthSquared()); } /// Performs a linear interpolation between two quaternions based on a value that specifies the weighting of the second quaternion. @@ -563,10 +528,27 @@ namespace System.Numerics 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. /// The scaled quaternion. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Multiply(Quaternion value1, float value2) { @@ -576,29 +558,21 @@ namespace System.Numerics /// 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) { 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. + [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. @@ -654,6 +628,7 @@ namespace System.Numerics /// 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) { @@ -663,7 +638,7 @@ namespace System.Numerics /// 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 +656,7 @@ namespace System.Numerics 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 +679,8 @@ namespace System.Numerics /// Calculates the length of the quaternion. /// The computed length of the quaternion. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { float lengthSquared = LengthSquared(); @@ -712,9 +689,11 @@ namespace System.Numerics /// Calculates the squared length of the quaternion. /// The length squared of the quaternion. + [Intrinsic] + [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/Numerics/Vector2.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs new file mode 100644 index 0000000..5b57163 --- /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 6c6e054..e57dee2 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics } /// 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) { @@ -76,6 +74,7 @@ namespace System.Numerics /// The vector (1,0). public static Vector2 UnitX { + [Intrinsic] get => new Vector2(1.0f, 0.0f); } @@ -83,6 +82,7 @@ namespace System.Numerics /// The vector (0,1). public static Vector2 UnitY { + [Intrinsic] get => new Vector2(0.0f, 1.0f); } @@ -92,63 +92,19 @@ namespace System.Numerics /// was less than zero or greater than the number of elements. public float this[int index] { - 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. /// 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) @@ -163,7 +119,7 @@ namespace System.Numerics /// 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) @@ -178,7 +134,8 @@ namespace System.Numerics /// 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) { @@ -189,7 +146,7 @@ namespace System.Numerics /// 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) @@ -213,7 +170,7 @@ namespace System.Numerics /// 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) @@ -228,7 +185,7 @@ namespace System.Numerics /// 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) @@ -240,7 +197,7 @@ namespace System.Numerics /// 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) @@ -252,7 +209,7 @@ namespace System.Numerics /// 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) @@ -266,7 +223,7 @@ namespace System.Numerics /// 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) @@ -291,6 +248,7 @@ namespace System.Numerics /// 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) { @@ -302,6 +260,7 @@ namespace System.Numerics /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) { @@ -313,6 +272,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector2 value1, Vector2 value2) { @@ -324,6 +284,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector2 value1, Vector2 value2) { @@ -335,6 +296,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Divide(Vector2 left, Vector2 right) { @@ -345,6 +307,7 @@ namespace System.Numerics /// The vector. /// The scalar value. /// The vector that results from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Divide(Vector2 left, float divisor) { @@ -371,6 +334,7 @@ namespace System.Numerics /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount) { @@ -409,6 +373,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(Vector2 left, Vector2 right) { @@ -419,6 +384,7 @@ namespace System.Numerics /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(Vector2 left, float right) { @@ -429,6 +395,7 @@ namespace System.Numerics /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Multiply(float left, Vector2 right) { @@ -438,6 +405,7 @@ namespace System.Numerics /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Negate(Vector2 value) { @@ -447,6 +415,7 @@ namespace System.Numerics /// 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) { @@ -461,7 +430,7 @@ namespace System.Numerics 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. @@ -481,6 +450,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Subtract(Vector2 left, Vector2 right) { @@ -494,10 +464,18 @@ namespace System.Numerics [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. @@ -507,10 +485,7 @@ namespace System.Numerics [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. @@ -543,10 +518,17 @@ namespace System.Numerics [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. @@ -556,18 +538,25 @@ namespace System.Numerics [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. /// 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) { @@ -585,12 +574,12 @@ namespace System.Numerics /// 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) { @@ -611,7 +600,7 @@ namespace System.Numerics /// 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) { @@ -641,7 +630,7 @@ namespace System.Numerics /// 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) { @@ -651,7 +640,7 @@ namespace System.Numerics /// 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) { @@ -685,7 +674,8 @@ namespace System.Numerics /// Returns the length of the vector. /// The vector's length. - /// + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -695,8 +685,9 @@ namespace System.Numerics /// 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. + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -705,7 +696,7 @@ namespace System.Numerics /// 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); @@ -714,7 +705,7 @@ namespace System.Numerics /// 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) @@ -726,7 +717,7 @@ namespace System.Numerics /// 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.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs new file mode 100644 index 0000000..2eb006e --- /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 2773bbc..c4739ce 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 @@ namespace System.Numerics 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) { @@ -89,6 +87,7 @@ namespace System.Numerics /// The vector (1,0,0). public static Vector3 UnitX { + [Intrinsic] get => new Vector3(1.0f, 0.0f, 0.0f); } @@ -96,6 +95,7 @@ namespace System.Numerics /// The vector (0,1,0). public static Vector3 UnitY { + [Intrinsic] get => new Vector3(0.0f, 1.0f, 0.0f); } @@ -103,6 +103,7 @@ namespace System.Numerics /// The vector (0,0,1). public static Vector3 UnitZ { + [Intrinsic] get => new Vector3(0.0f, 0.0f, 1.0f); } @@ -112,63 +113,19 @@ namespace System.Numerics /// was less than zero or greater than the number of elements. public float this[int index] { - 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. /// 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) @@ -184,7 +141,7 @@ namespace System.Numerics /// 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) @@ -200,7 +157,8 @@ namespace System.Numerics /// 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) { @@ -211,7 +169,7 @@ namespace System.Numerics /// 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) @@ -236,7 +194,7 @@ namespace System.Numerics /// 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) @@ -252,7 +210,7 @@ namespace System.Numerics /// 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) @@ -264,7 +222,7 @@ namespace System.Numerics /// 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) @@ -276,7 +234,7 @@ namespace System.Numerics /// 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) @@ -291,7 +249,7 @@ namespace System.Numerics /// 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) @@ -317,6 +275,7 @@ namespace System.Numerics /// 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) { @@ -328,6 +287,7 @@ namespace System.Numerics /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) { @@ -353,6 +313,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector3 value1, Vector3 value2) { @@ -364,6 +325,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector3 value1, Vector3 value2) { @@ -375,6 +337,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Divide(Vector3 left, Vector3 right) { @@ -385,6 +348,7 @@ namespace System.Numerics /// The vector. /// The scalar value. /// The vector that results from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Divide(Vector3 left, float divisor) { @@ -409,10 +373,11 @@ namespace System.Numerics /// 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) { - 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. @@ -449,6 +414,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(Vector3 left, Vector3 right) { @@ -459,6 +425,7 @@ namespace System.Numerics /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(Vector3 left, float right) { @@ -469,6 +436,7 @@ namespace System.Numerics /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Multiply(float left, Vector3 right) { @@ -478,6 +446,7 @@ namespace System.Numerics /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Negate(Vector3 value) { @@ -487,6 +456,7 @@ namespace System.Numerics /// 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) { @@ -501,7 +471,7 @@ namespace System.Numerics 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. @@ -522,6 +492,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Subtract(Vector3 left, Vector3 right) { @@ -535,11 +506,7 @@ namespace System.Numerics [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. @@ -577,19 +544,26 @@ namespace System.Numerics [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. /// 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) { @@ -607,12 +581,12 @@ namespace System.Numerics /// 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) { @@ -633,7 +607,7 @@ namespace System.Numerics /// 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) { @@ -663,7 +637,7 @@ namespace System.Numerics /// 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) { @@ -673,7 +647,7 @@ namespace System.Numerics /// 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) { @@ -704,7 +678,8 @@ namespace System.Numerics /// Returns the length of this vector object. /// The vector's length. - /// + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -714,8 +689,9 @@ namespace System.Numerics /// 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. + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -724,7 +700,7 @@ namespace System.Numerics /// 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); @@ -733,7 +709,7 @@ namespace System.Numerics /// 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) @@ -745,7 +721,7 @@ namespace System.Numerics /// 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.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs new file mode 100644 index 0000000..143d003 --- /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 485cbd4..831b4f5 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 @@ namespace System.Numerics 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 @@ namespace System.Numerics { } - /// 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 @@ namespace System.Numerics } /// 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 @@ namespace System.Numerics } /// 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 { @@ -104,6 +102,7 @@ namespace System.Numerics /// The vector (1,0,0,0). public static Vector4 UnitX { + [Intrinsic] get => new Vector4(1.0f, 0.0f, 0.0f, 0.0f); } @@ -111,6 +110,7 @@ namespace System.Numerics /// The vector (0,1,0,0). public static Vector4 UnitY { + [Intrinsic] get => new Vector4(0.0f, 1.0f, 0.0f, 0.0f); } @@ -118,6 +118,7 @@ namespace System.Numerics /// The vector (0,0,1,0). public static Vector4 UnitZ { + [Intrinsic] get => new Vector4(0.0f, 0.0f, 1.0f, 0.0f); } @@ -125,6 +126,7 @@ namespace System.Numerics /// The vector (0,0,0,1). public static Vector4 UnitW { + [Intrinsic] get => new Vector4(0.0f, 0.0f, 0.0f, 1.0f); } @@ -134,63 +136,19 @@ namespace System.Numerics /// was less than zero or greater than the number of elements. public float this[int index] { - 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. /// 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) @@ -207,7 +165,7 @@ namespace System.Numerics /// 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) @@ -224,7 +182,7 @@ namespace System.Numerics /// 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) @@ -236,7 +194,7 @@ namespace System.Numerics /// 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) @@ -262,7 +220,7 @@ namespace System.Numerics /// 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) @@ -279,7 +237,7 @@ namespace System.Numerics /// 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) @@ -291,7 +249,7 @@ namespace System.Numerics /// 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) @@ -303,7 +261,7 @@ namespace System.Numerics /// 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) @@ -319,7 +277,7 @@ namespace System.Numerics /// 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) @@ -346,6 +304,7 @@ namespace System.Numerics /// 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) { @@ -357,6 +316,7 @@ namespace System.Numerics /// The minimum value. /// The maximum value. /// The restricted vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) { @@ -368,6 +328,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Distance(Vector4 value1, Vector4 value2) { @@ -379,6 +340,7 @@ namespace System.Numerics /// The first point. /// The second point. /// The distance squared. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float DistanceSquared(Vector4 value1, Vector4 value2) { @@ -390,6 +352,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The vector resulting from the division. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Divide(Vector4 left, Vector4 right) { @@ -400,6 +363,7 @@ namespace System.Numerics /// 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 +392,7 @@ namespace System.Numerics /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Lerp(Vector4 value1, Vector4 value2, float amount) { @@ -470,6 +435,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The element-wise product vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 left, Vector4 right) { @@ -480,6 +446,7 @@ namespace System.Numerics /// The vector to multiply. /// The scalar value. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 left, float right) { @@ -490,6 +457,7 @@ namespace System.Numerics /// The scaled value. /// The vector. /// The scaled vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(float left, Vector4 right) { @@ -499,6 +467,7 @@ namespace System.Numerics /// Negates a specified vector. /// The vector to negate. /// The negated vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Negate(Vector4 value) { @@ -508,6 +477,7 @@ namespace System.Numerics /// 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) { @@ -533,6 +503,7 @@ namespace System.Numerics /// The first vector. /// The second vector. /// The difference vector. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Subtract(Vector4 left, Vector4 right) { @@ -545,13 +516,17 @@ namespace System.Numerics /// 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. @@ -589,13 +564,18 @@ namespace System.Numerics /// 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. @@ -678,9 +658,9 @@ namespace System.Numerics /// 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) { @@ -698,12 +678,12 @@ namespace System.Numerics /// 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) { @@ -724,7 +704,7 @@ namespace System.Numerics /// 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) { @@ -754,7 +734,7 @@ namespace System.Numerics /// 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) { @@ -780,7 +760,7 @@ namespace System.Numerics /// 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) { @@ -796,7 +776,8 @@ namespace System.Numerics /// Returns the length of this vector object. /// The vector's length. - /// + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float Length() { @@ -806,8 +787,9 @@ namespace System.Numerics /// 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. + /// + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly float LengthSquared() { @@ -816,7 +798,7 @@ namespace System.Numerics /// 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); @@ -825,7 +807,7 @@ namespace System.Numerics /// 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) @@ -837,7 +819,7 @@ namespace System.Numerics /// 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/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index de163d2..99295c9 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 @@ namespace System.Runtime.Intrinsics 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 . diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index cad1e07..816c0e1 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1123,8 +1123,19 @@ 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,13 +1425,26 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi #endif } case SN_GetElement: { + 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 extract_op = type_to_xextract_op (arg0_type); @@ -1666,13 +1690,26 @@ 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); @@ -1834,18 +1871,28 @@ 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_UnitW, + SN_get_UnitX, + SN_get_UnitY, + SN_get_UnitZ, SN_get_Zero, SN_op_Addition, SN_op_Division, @@ -1950,18 +1997,15 @@ 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: + 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; @@ -1987,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: @@ -2034,6 +2069,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 +2114,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 1a6a429..e8d4af1 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_UnitW) +METHOD(get_UnitX) +METHOD(get_UnitY) +METHOD(get_UnitZ) METHOD(get_Zero) METHOD(op_Addition) METHOD(op_BitwiseAnd)