diff --git a/src/coreclr/inc/cor.h b/src/coreclr/inc/cor.h index 4b9e9fe6953f02..ad333d1dee5060 100644 --- a/src/coreclr/inc/cor.h +++ b/src/coreclr/inc/cor.h @@ -1665,6 +1665,14 @@ FORCEINLINE int CorIsPrimitiveType(CorElementType elementtype) return (elementtype < ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_I || elementtype == ELEMENT_TYPE_U); } +// Returns true if the element type is a real or integer type. +FORCEINLINE bool CorIsNumericalType(CorElementType elementType) +{ + return ((elementType >= ELEMENT_TYPE_I1) && (elementType <= ELEMENT_TYPE_R8)) + || (elementType == ELEMENT_TYPE_I) + || (elementType == ELEMENT_TYPE_U); +} + // Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are // turned on. For now, it is checking for ELEMENT_TYPE_PTR and ELEMENT_TYPE_BYREF diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index c532eae900b5b4..da52694e0a7162 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -1685,45 +1685,64 @@ bool MethodTable::IsHFA() #endif // !FEATURE_HFA //******************************************************************************* -int MethodTable::GetVectorSize() +CorInfoHFAElemType MethodTable::GetVectorHFA() { // This is supported for finding HVA types for Arm64. In order to support the altjit, // we support this on 64-bit platforms (i.e. Arm64 and X64). + CorInfoHFAElemType hfaType = CORINFO_HFA_ELEM_NONE; #ifdef TARGET_64BIT if (IsIntrinsicType()) { LPCUTF8 namespaceName; LPCUTF8 className = GetFullyQualifiedNameInfo(&namespaceName); - int vectorSize = 0; if (strcmp(className, "Vector`1") == 0) { _ASSERTE(strcmp(namespaceName, "System.Numerics") == 0); - vectorSize = GetNumInstanceFieldBytes(); +#ifdef TARGET_ARM64 + if (ExecutionManager::GetEEJitManager()->UseScalableVectorT()) + { + // TODO-SVE: This forces Vector to be passed by reference. Implement + // CORINFO_HFA_ELEM_VECTORT so we can pass Vector in SVE registers. + return CORINFO_HFA_ELEM_NONE; + } +#endif + switch (GetNumInstanceFieldBytes()) + { + case 8: + hfaType = CORINFO_HFA_ELEM_VECTOR64; + break; + case 16: + hfaType = CORINFO_HFA_ELEM_VECTOR128; + break; + default: + _ASSERTE(!"Invalid Vector size"); + break; + } } else if (strcmp(className, "Vector128`1") == 0) { _ASSERTE(strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); - vectorSize = 16; + hfaType = CORINFO_HFA_ELEM_VECTOR128; } else if (strcmp(className, "Vector64`1") == 0) { _ASSERTE(strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); - vectorSize = 8; + hfaType = CORINFO_HFA_ELEM_VECTOR64; } - if (vectorSize != 0) + + if (hfaType != CORINFO_HFA_ELEM_NONE) { - // We need to verify that T (the element or "base" type) is a primitive type. + // We need to verify that T (the element or "base" type) is a numerical type. TypeHandle typeArg = GetInstantiation()[0]; - CorElementType corType = typeArg.GetSignatureCorElementType(); - if (((corType >= ELEMENT_TYPE_I1) && (corType <= ELEMENT_TYPE_R8)) || (corType == ELEMENT_TYPE_I) || (corType == ELEMENT_TYPE_U)) + if (!CorIsNumericalType(typeArg.GetSignatureCorElementType())) { - return vectorSize; + return CORINFO_HFA_ELEM_NONE; } } } #endif // TARGET_64BIT - return 0; + return hfaType; } //******************************************************************************* @@ -1745,10 +1764,11 @@ CorInfoHFAElemType MethodTable::GetHFAType() _ASSERTE(pMT->IsValueType()); _ASSERTE(pMT->GetNumInstanceFields() > 0); - int vectorSize = pMT->GetVectorSize(); - if (vectorSize != 0) + CorInfoHFAElemType hfaType = pMT->GetVectorHFA(); + + if (hfaType != CORINFO_HFA_ELEM_NONE) { - return (vectorSize == 8) ? CORINFO_HFA_ELEM_VECTOR64 : CORINFO_HFA_ELEM_VECTOR128; + return hfaType; } PTR_FieldDesc pFirstField = pMT->GetApproxFieldDescListRaw(); @@ -1817,7 +1837,7 @@ EEClass::CheckForHFA() // The opaque Vector types appear to have multiple fields, but need to be treated // as an opaque type of a single vector. - if (GetMethodTable()->GetVectorSize() != 0) + if (GetMethodTable()->GetVectorHFA() != CORINFO_HFA_ELEM_NONE) { #if defined(FEATURE_HFA) GetMethodTable()->SetIsHFA(); @@ -1843,27 +1863,13 @@ EEClass::CheckForHFA() { case ELEMENT_TYPE_VALUETYPE: { -#ifdef TARGET_ARM64 MethodTable* pMT; #if defined(FEATURE_HFA) pMT = pByValueClassCache[i]; #else pMT = pFD->LookupApproxFieldTypeHandle().AsMethodTable(); #endif - int thisElemSize = pMT->GetVectorSize(); - if (thisElemSize != 0) - { - fieldHFAType = (thisElemSize == 8) ? CORINFO_HFA_ELEM_VECTOR64 : CORINFO_HFA_ELEM_VECTOR128; - } - else -#endif // TARGET_ARM64 - { -#if defined(FEATURE_HFA) - fieldHFAType = pByValueClassCache[i]->GetHFAType(); -#else - fieldHFAType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); -#endif - } + fieldHFAType = pMT->GetHFAType(); int requiredAlignment; switch (fieldHFAType) diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 4a663b9df29e68..48b7cdb3ef1d88 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -2221,6 +2221,14 @@ class EEJitManager final : public EECodeGenManager return m_CPUCompileFlags; } +#if defined(TARGET_ARM64) + inline bool UseScalableVectorT() + { + LIMITED_METHOD_CONTRACT; + return m_CPUCompileFlags.GetInstructionSetFlags().HasInstructionSet(InstructionSet_VectorT); + } +#endif + private : Crst m_JitLoadLock; diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index b99dcb293337be..68075da370726e 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2045,8 +2045,10 @@ class MethodTable bool IsHFA(); #endif // FEATURE_HFA - // Returns the size in bytes of this type if it is a HW vector type; 0 otherwise. - int GetVectorSize(); + // Returns the HFA type for this type, if it is a valid HW vector type. + // Floating point HFA types will return CORINFO_HFA_ELEM_NONE. + // Vector classes with invalid generic parameters return CORINFO_HFA_ELEM_NONE. + CorInfoHFAElemType GetVectorHFA(); // Get the HFA type. This is supported both with FEATURE_HFA, in which case it // depends on the cached bit on the class, or without, in which case it is recomputed