From e669325a8325817eaa7bc981452d804005bec12e Mon Sep 17 00:00:00 2001 From: Sebastian Nickolls Date: Fri, 3 Oct 2025 12:38:18 +0000 Subject: [PATCH] Pass Vector by reference when InstructionSet_VectorT is available Prevents Vector being treated as a 128-bit HFA when the new SVE instruction set for Vector is available. A new HFA type for SVE-backed Vector will be implemented in place of this. Also take some time to improve the HFA recognition code. HFA type can be decided immediately from the class name for fixed size types. Create a central function for this decision. --- src/coreclr/inc/cor.h | 8 +++++ src/coreclr/vm/class.cpp | 66 ++++++++++++++++++++---------------- src/coreclr/vm/codeman.h | 8 +++++ src/coreclr/vm/methodtable.h | 6 ++-- 4 files changed, 56 insertions(+), 32 deletions(-) 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