From 465748c7941d3e48c263eb8b0f1e9e5a68f00950 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 22 May 2026 09:10:56 -0700 Subject: [PATCH 1/5] Ensure the other compilers consistently handle both get_IsHardwareAccelerated and get_IsSupported --- src/coreclr/interpreter/compiler.cpp | 76 +++++++++++++----- src/coreclr/interpreter/intrinsics.cpp | 10 ++- .../System/Runtime/Intrinsics/Vector128_1.cs | 13 +-- .../System/Runtime/Intrinsics/Vector256_1.cs | 13 +-- .../System/Runtime/Intrinsics/Vector512_1.cs | 13 +-- .../System/Runtime/Intrinsics/Vector64_1.cs | 13 +-- src/mono/mono/mini/interp/transform-simd.c | 79 +++++++++++++------ src/mono/mono/mini/interp/transform.c | 32 ++++++-- src/mono/mono/mini/simd-intrinsics.c | 8 +- 9 files changed, 155 insertions(+), 102 deletions(-) diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 095fb63c5f3e39..5114d86a6909eb 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -765,7 +765,7 @@ int32_t InterpCompiler::CreateVarExplicit(InterpType interpType, CORINFO_CLASS_H m_varsCapacity *= 2; if (m_varsCapacity < 16) m_varsCapacity = 16; - + m_pVars = getAllocator(IMK_Var).allocateZeroed(m_varsCapacity); if (oldVars != NULL) { @@ -791,7 +791,7 @@ void InterpCompiler::EnsureStack(int additional) m_stackCapacity *= 2; if (m_stackCapacity < 4) m_stackCapacity = 4; - + m_pStackBase = new (getAllocator(IMK_StackInfo)) StackInfo[m_stackCapacity]; if (oldStackBase != NULL) { @@ -2026,23 +2026,23 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base uint32_t currentIntervalMapOffset = intervalMapsOffset; const uint32_t asyncSuspendDataSectionEnd = asyncSuspendDataOffset + asyncSuspendDataSectionSize; const uint32_t intervalMapsSectionEnd = intervalMapsOffset + intervalMapsSectionSize; - + InterpByteCodeStart* pByteCodeStart = (InterpByteCodeStart*)rxBase; - + for (int32_t i = 0; i < m_asyncSuspendDataItems.GetSize(); i++) { assert(currentAsyncOffset + sizeof(InterpAsyncSuspendData) <= asyncSuspendDataSectionEnd); InterpAsyncSuspendData* srcData = m_asyncSuspendDataItems.Get(i); InterpAsyncSuspendData* dstDataRW = (InterpAsyncSuspendData*)(rwBase + currentAsyncOffset); - + // Copy the struct memcpy(dstDataRW, srcData, sizeof(InterpAsyncSuspendData)); - + // Fix up the methodStartIP to point to the final bytecode start dstDataRW->methodStartIP = pByteCodeStart; dstDataRW->resumeInfo.DiagnosticIP += (TARGET_SIZE_T)pByteCodeStart; - + // Fix up interval map pointers if they exist // Note: The interval maps were allocated via AllocMethodData in the old model, // we need to copy them to the new allocation and fix up the pointers @@ -2055,14 +2055,14 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base uint32_t mapSize = (uint32_t)count * sizeof(InterpIntervalMapEntry); assert(currentIntervalMapOffset + mapSize <= intervalMapsSectionEnd); - + InterpIntervalMapEntry* dstMapRW = (InterpIntervalMapEntry*)(rwBase + currentIntervalMapOffset); InterpIntervalMapEntry* dstMapRX = (InterpIntervalMapEntry*)(rxBase + currentIntervalMapOffset); memcpy(dstMapRW, srcData->liveLocalsIntervals, mapSize); dstDataRW->liveLocalsIntervals = dstMapRX; currentIntervalMapOffset += mapSize; } - + if (srcData->zeroedLocalsIntervals != nullptr) { // Count entries @@ -2072,7 +2072,7 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base uint32_t mapSize = (uint32_t)count * sizeof(InterpIntervalMapEntry); assert(currentIntervalMapOffset + mapSize <= intervalMapsSectionEnd); - + InterpIntervalMapEntry* dstMapRW = (InterpIntervalMapEntry*)(rwBase + currentIntervalMapOffset); InterpIntervalMapEntry* dstMapRX = (InterpIntervalMapEntry*)(rxBase + currentIntervalMapOffset); memcpy(dstMapRW, srcData->zeroedLocalsIntervals, mapSize); @@ -2121,7 +2121,7 @@ InterpMethod* InterpCompiler::FinalizeMethodData(void* baseAddressRW, void* base { DataItemAsyncSuspendRef ref = m_dataItemAsyncSuspendRefs.Get(i); // Calculate the final address of this async suspend data in the RX allocation - InterpAsyncSuspendData* finalAddr = (InterpAsyncSuspendData*)(rxBase + asyncSuspendDataOffset + + InterpAsyncSuspendData* finalAddr = (InterpAsyncSuspendData*)(rxBase + asyncSuspendDataOffset + ref.asyncSuspendDataIndex * sizeof(InterpAsyncSuspendData)); pDataItemsRW[ref.dataItemIndex] = finalAddr; } @@ -3562,6 +3562,44 @@ bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, bool nonVirtualCa m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); return true; + case NI_IsSupported_Type: + { + CORINFO_CLASS_HANDLE typeArgHnd = m_compHnd->getTypeInstantiationArgument(clsHnd, 0); + CorInfoType simdBaseJitType = m_compHnd->getTypeForPrimitiveNumericClass(typeArgHnd); + + AddIns(INTOP_LDC_I4); + + switch (simdBaseJitType) + { + case CORINFO_TYPE_BYTE: + case CORINFO_TYPE_UBYTE: + case CORINFO_TYPE_SHORT: + case CORINFO_TYPE_USHORT: + case CORINFO_TYPE_INT: + case CORINFO_TYPE_UINT: + case CORINFO_TYPE_LONG: + case CORINFO_TYPE_ULONG: + case CORINFO_TYPE_FLOAT: + case CORINFO_TYPE_DOUBLE: + case CORINFO_TYPE_NATIVEINT: + case CORINFO_TYPE_NATIVEUINT: + { + m_pLastNewIns->data[0] = true; + break; + } + + default: + { + m_pLastNewIns->data[0] = false; + break; + } + } + + PushStackType(StackTypeI4, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + return true; + } + case NI_PRIMITIVE_ConvertToIntegerNative: { CHECK_STACK(1); @@ -4423,7 +4461,7 @@ void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunc { if (m_compHnd->pInvokeMarshalingRequired(NULL, callSiteSig)) { - // If we remove this restriction, we should handle the track transitions scenario by forcing a + // If we remove this restriction, we should handle the track transitions scenario by forcing a // p/invoke marshaling calli stub even when not needed. BADCODE("PInvoke marshalling for calli is not supported in interpreted code"); } @@ -6011,7 +6049,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation } InterpType interpType = m_pVars[var].interpType; CORINFO_CLASS_HANDLE clsHnd = m_pVars[var].clsHnd; - + int32_t alignUNUSED; int32_t size = GetInterpTypeStackSize(clsHnd, interpType, &alignUNUSED); @@ -6058,7 +6096,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation SetSlotToTrue(objRefSlots, currentOffset + slotInfo.m_offsetBytes); } } - + currentOffset += size; } @@ -6099,7 +6137,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation suspendData->suspensionPointIndex = suspensionPointIndex; CORINFO_ASYNC_INFO asyncInfo; m_compHnd->getAsyncInfo(&asyncInfo); - + GetDataForHelperFtn(CORINFO_HELP_ALLOC_CONTINUATION); suspendData->continuationTypeHnd = continuationTypeHnd; AllocateIntervalMapData_ForVars(&suspendData->liveLocalsIntervals, liveVars); @@ -6232,13 +6270,13 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation AddIns(handleContinuationOpcode); int32_t suspendDataIndex = GetDataItemIndex(suspendData); - + // Track this data item -> async suspend data reference for fixup during finalization DataItemAsyncSuspendRef ref; ref.dataItemIndex = suspendDataIndex; ref.asyncSuspendDataIndex = m_asyncSuspendDataItems.GetSize() - 1; // suspendData was just added m_dataItemAsyncSuspendRefs.Add(ref); - + m_pLastNewIns->data[0] = suspendDataIndex; m_pLastNewIns->data[1] = GetDataForHelperFtn(helperFuncForAllocatingContinuation); PushInterpType(InterpTypeO, NULL); @@ -6279,7 +6317,7 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation // Add location to resume to. The implementation of this opcode will: // - restore the data captured // - If there is an exception, throw it - // - if there is a captured exec context, call the restoration function. + // - if there is a captured exec context, call the restoration function. AddIns(INTOP_HANDLE_CONTINUATION_RESUME); m_pLastNewIns->data[0] = suspendDataIndex; @@ -9930,7 +9968,7 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) BADCODE("CEE_JMP in synchronized or async method"); } EmitCall(m_pConstrainedToken, readonly, true /* tailcall */, false /*newObj*/, false /*isCalli*/); - EmitRet(methodInfo); // The tail-call infrastructure in the interpreter is not 100% guaranteed to do a + EmitRet(methodInfo); // The tail-call infrastructure in the interpreter is not 100% guaranteed to do a // tail-call, so inject the ret logic here to cover that case. linkBBlocks = false; break; diff --git a/src/coreclr/interpreter/intrinsics.cpp b/src/coreclr/interpreter/intrinsics.cpp index 0bdcb718d5b6e7..1c855558f3aa29 100644 --- a/src/coreclr/interpreter/intrinsics.cpp +++ b/src/coreclr/interpreter/intrinsics.cpp @@ -80,8 +80,14 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp else if (!strcmp(namespaceName, "System.Runtime.Intrinsics")) { // Vector128 etc - if (HAS_PREFIX(className, "Vector") && !strcmp(methodName, "get_IsHardwareAccelerated")) - return NI_IsSupported_False; + if (HAS_PREFIX(className, "Vector")) + { + if (!strcmp(methodName, "get_IsHardwareAccelerated")) + return NI_IsSupported_False; + + if (!strcmp(methodName, "get_IsSupported")) + return NI_IsSupported_Type; + } // Fall back to managed implementation for everything else. return NI_Illegal; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs index c4da470bb3f20c..244ea695071e9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs @@ -82,18 +82,7 @@ public static bool IsSupported [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (typeof(T) == typeof(byte)) - || (typeof(T) == typeof(double)) - || (typeof(T) == typeof(short)) - || (typeof(T) == typeof(int)) - || (typeof(T) == typeof(long)) - || (typeof(T) == typeof(nint)) - || (typeof(T) == typeof(sbyte)) - || (typeof(T) == typeof(float)) - || (typeof(T) == typeof(ushort)) - || (typeof(T) == typeof(uint)) - || (typeof(T) == typeof(ulong)) - || (typeof(T) == typeof(nuint)); + return Scalar.IsSupported; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs index 39c3404eff5d0d..e8583987454580 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs @@ -81,18 +81,7 @@ public static bool IsSupported [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (typeof(T) == typeof(byte)) - || (typeof(T) == typeof(double)) - || (typeof(T) == typeof(short)) - || (typeof(T) == typeof(int)) - || (typeof(T) == typeof(long)) - || (typeof(T) == typeof(nint)) - || (typeof(T) == typeof(sbyte)) - || (typeof(T) == typeof(float)) - || (typeof(T) == typeof(ushort)) - || (typeof(T) == typeof(uint)) - || (typeof(T) == typeof(ulong)) - || (typeof(T) == typeof(nuint)); + return Scalar.IsSupported; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs index e408bc81abd35b..a63cd92c5e6dcc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs @@ -81,18 +81,7 @@ public static bool IsSupported [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (typeof(T) == typeof(byte)) - || (typeof(T) == typeof(double)) - || (typeof(T) == typeof(short)) - || (typeof(T) == typeof(int)) - || (typeof(T) == typeof(long)) - || (typeof(T) == typeof(nint)) - || (typeof(T) == typeof(sbyte)) - || (typeof(T) == typeof(float)) - || (typeof(T) == typeof(ushort)) - || (typeof(T) == typeof(uint)) - || (typeof(T) == typeof(ulong)) - || (typeof(T) == typeof(nuint)); + return Scalar.IsSupported; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index d863f0543f1323..1a243dcc6facd4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -81,18 +81,7 @@ public static bool IsSupported [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (typeof(T) == typeof(byte)) - || (typeof(T) == typeof(double)) - || (typeof(T) == typeof(short)) - || (typeof(T) == typeof(int)) - || (typeof(T) == typeof(long)) - || (typeof(T) == typeof(nint)) - || (typeof(T) == typeof(sbyte)) - || (typeof(T) == typeof(float)) - || (typeof(T) == typeof(ushort)) - || (typeof(T) == typeof(uint)) - || (typeof(T) == typeof(ulong)) - || (typeof(T) == typeof(nuint)); + return Scalar.IsSupported; } } diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index 6f689433361847..d58a5aa92de8ee 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -56,7 +56,7 @@ lookup_intrins (guint16 *intrinsics, int size, const char *cmethod_name) // These items need to be in ASCII order, which means alphabetical order where lowercase is after uppercase // i.e. all 'get_' and 'op_' need to come after regular title-case names -static guint16 sri_vector128_methods [] = { +static guint16 sri_vector_methods [] = { SN_AndNot, SN_As, SN_AsByte, @@ -96,10 +96,11 @@ static guint16 sri_vector128_methods [] = { SN_get_IsHardwareAccelerated, }; -static guint16 sri_vector128_t_methods [] = { +static guint16 sri_vector_t_methods [] = { SN_EqualsFloatingPoint, SN_get_AllBitsSet, SN_get_Count, + SN_get_IsSupported, SN_get_One, SN_get_Zero, SN_op_Addition, @@ -122,6 +123,7 @@ static guint16 sn_vector_t_methods [] = { SN_ctor, SN_get_AllBitsSet, SN_get_Count, + SN_get_IsSupported, SN_get_One, SN_get_Zero, SN_op_Addition, @@ -220,11 +222,18 @@ static const char * strip_explicit_isimd_prefix (const char *cmethod_name) { if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible // but, they all prefix the qualified name of the interface first, so we'll check for that and // skip the prefix before trying to resolve the method. - if (strncmp (cmethod_name + 45, "Runtime.Intrinsics.Vector128,T>.", 35) == 0) { - cmethod_name += 80; + + if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { + cmethod_name += 79; + } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || + (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { + cmethod_name += 80; + } } else if (strncmp(cmethod_name + 45, "Numerics.Vector,T>.", 22) == 0) { cmethod_name += 67; } @@ -249,6 +258,9 @@ emit_common_simd_operations (TransformData *td, int id, int atype, int vector_si interp_add_ins (td, MINT_LDC_I4_S); td->last_ins->data [0] = vector_size / arg_size; return TRUE; + case SN_get_IsSupported: + interp_add_ins (td, MINT_LDC_I4_1); + return TRUE; case SN_get_One: if (atype == MONO_TYPE_I1 || atype == MONO_TYPE_U1) { interp_add_ins (td, MINT_SIMD_V128_LDC); @@ -408,11 +420,9 @@ get_common_simd_info (MonoClass *vector_klass, MonoMethodSignature *csignature, if (!mono_class_is_ginst (vector_klass)) return FALSE; MonoType *arg_type = mono_class_get_context (vector_klass)->class_inst->type_argv [0]; - if (!mono_type_is_primitive (arg_type)) + if (!MONO_TYPE_IS_VECTOR_PRIMITIVE (arg_type)) return FALSE; *atype = arg_type->type; - if (*atype == MONO_TYPE_BOOLEAN) - return FALSE; *vector_size = mono_class_value_size (vector_klass, NULL); if (*vector_size != SIZEOF_V128) return FALSE; @@ -512,7 +522,7 @@ emit_vector_create (TransformData *td, MonoMethodSignature *csignature, MonoClas } static gboolean -emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) +emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) { if (csignature->hasthis) return FALSE; @@ -523,18 +533,13 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature #endif const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name); - int id = lookup_intrins (sri_vector128_methods, sizeof (sri_vector128_methods), cmethod_name); + int id = lookup_intrins (sri_vector_methods, sizeof (sri_vector_methods), cmethod_name); if (id == -1) return FALSE; MonoClass *vector_klass = NULL; int vector_size = 0; - if (id == SN_get_IsHardwareAccelerated) { - interp_add_ins (td, MINT_LDC_I4_1); - goto opcode_added; - } - gint16 simd_opcode = -1; gint16 simd_intrins = -1; @@ -548,8 +553,20 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature MonoTypeEnum atype; int arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { + if (id == SN_get_IsHardwareAccelerated) { + interp_add_ins (td, MINT_LDC_I4_0); + goto opcode_added; + } return FALSE; + } + + g_assert (vector_size == 128); + + if (id == SN_get_IsHardwareAccelerated) { + interp_add_ins (td, MINT_LDC_I4_1); + goto opcode_added; + } switch (id) { case SN_AndNot: @@ -729,7 +746,7 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature } static gboolean -emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) +emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) { #ifdef HOST_BROWSER if (emit_sri_packedsimd (td, cmethod, csignature)) @@ -738,10 +755,10 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name); bool explicitly_implemented = cmethod_name != cmethod->name; - int id = lookup_intrins (sri_vector128_t_methods, sizeof (sri_vector128_t_methods), cmethod->name); + int id = lookup_intrins (sri_vector_t_methods, sizeof (sri_vector_t_methods), cmethod->name); if (id == -1) { if (explicitly_implemented) { - return emit_sri_vector128 (td, cmethod, csignature); + return emit_sri_vector (td, cmethod, csignature); } else { return FALSE; } @@ -755,8 +772,13 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur MonoTypeEnum atype; int vector_size, arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { + if (id == SN_get_IsSupported) { + interp_add_ins (td, MINT_LDC_I4_0); + goto opcode_added; + } return FALSE; + } if (emit_common_simd_operations (td, id, atype, vector_size, arg_size, scalar_arg, &simd_opcode, &simd_intrins)) goto opcode_added; @@ -785,7 +807,7 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name); if (id == -1) { if (explicitly_implemented) { - return emit_sri_vector128 (td, cmethod, csignature); + return emit_sri_vector (td, cmethod, csignature); } else { return FALSE; } @@ -801,8 +823,13 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c MonoTypeEnum atype; int vector_size, arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { + if (id == SN_get_IsSupported) { + interp_add_ins (td, MINT_LDC_I4_0); + goto opcode_added; + } return FALSE; + } if (emit_common_simd_operations (td, id, atype, vector_size, arg_size, scalar_arg, &simd_opcode, &simd_intrins)) { goto opcode_added; @@ -1337,13 +1364,13 @@ interp_emit_simd_intrinsics (TransformData *td, MonoMethod *cmethod, MonoMethodS class_name = m_class_get_name (cmethod->klass); if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { - if (!strcmp (class_name, "Vector128")) - return emit_sri_vector128 (td, cmethod, csignature); - else if (!strcmp (class_name, "Vector128`1")) - return emit_sri_vector128_t (td, cmethod, csignature); + if (!strcmp (class_name, "Vector64") || !strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector256") || !strcmp (class_name, "Vector512")) + return emit_sri_vector (td, cmethod, csignature); + if (!strcmp (class_name, "Vector64`1") || !strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector256`1") || !strcmp (class_name, "Vector512`1")) + return emit_sri_vector_t (td, cmethod, csignature); } else if (!strcmp (class_ns, "System.Numerics")) { if (!strcmp (class_name, "Vector")) - return emit_sri_vector128 (td, cmethod, csignature); + return emit_sri_vector (td, cmethod, csignature); else if (!strcmp (class_name, "Vector`1")) return emit_sn_vector_t (td, cmethod, csignature, newobj); else if (!strcmp (class_name, "Vector4")) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index e27b3e2daa26a9..c5ee0dab944439 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2677,9 +2677,19 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas *op = MINT_LDC_I4_0; } else if (in_corlib && (!strncmp ("System.Runtime.Intrinsics", klass_name_space, 25))) { if (klass_name_space[25] == '\0' && - !strncmp ("Vector", klass_name, 6) && - !strcmp (tm, "get_IsHardwareAccelerated")) { - *op = MINT_LDC_I4_0; + !strncmp ("Vector", klass_name, 6)) { + if (!strcmp (tm, "get_IsHardwareAccelerated")) { + *op = MINT_LDC_I4_0; + } else if (!strcmp (tm, "get_IsSupported")) { + if (mono_class_is_ginst (target_method->klass)) { + MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + *op = MINT_LDC_I4_1; + } else { + *op = MINT_LDC_I4_0; + } + } + } } else if (klass_name_space[25] == '.') { if (!strncmp ("Arm", klass_name_space + 26, 3) || !strncmp ("X86", klass_name_space + 26, 3)) { @@ -2712,9 +2722,19 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } } } else if (in_corlib && !strncmp ("System.Numerics", klass_name_space, 15)) { - if (!strcmp ("Vector", klass_name) && - !strcmp (tm, "get_IsHardwareAccelerated")) { - *op = MINT_LDC_I4_0; + if (!strcmp ("Vector", klass_name)) { + if (!strcmp (tm, "get_IsHardwareAccelerated")) { + *op = MINT_LDC_I4_0; + } else if (!strcmp (tm, "get_IsSupported")) { + if (mono_class_is_ginst (target_method->klass)) { + MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + *op = MINT_LDC_I4_1; + } else { + *op = MINT_LDC_I4_0; + } + } + } } else if (!strcmp ("BitOperations", klass_name)) { int arg_type = (csignature->param_count > 0) ? csignature->params [0]->type : MONO_TYPE_VOID; if ((!strcmp (tm, "RotateLeft") || !strcmp (tm, "RotateRight")) && MINT_IS_LDC_I4 (td->last_ins->opcode)) { diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 21295764fad806..7f226a2d826afa 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -2020,8 +2020,14 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi else return NULL; - if (vector_size == 256 || vector_size == 512) + if (vector_size == 256 || vector_size == 512) { + if (id == SN_get_IsHardwareAccelerated) { + MonoInst* ins; + EMIT_NEW_ICONST (cfg, ins, 0); + return ins; + } return NULL; + } if (!(cfg->opt & MONO_OPT_SIMD)) return NULL; From 6902f05da8a7f73e1bb83ae0bf2380283a2610a7 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 22 May 2026 09:30:16 -0700 Subject: [PATCH 2/5] Resolve PR feedback --- src/mono/mono/mini/interp/transform-simd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index d58a5aa92de8ee..72c65760a10062 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -561,7 +561,7 @@ emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs return FALSE; } - g_assert (vector_size == 128); + g_assert (vector_size == SIZEOF_V128); if (id == SN_get_IsHardwareAccelerated) { interp_add_ins (td, MINT_LDC_I4_1); @@ -771,10 +771,12 @@ emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature * MonoClass *vector_klass = cmethod->klass; MonoTypeEnum atype; - int vector_size, arg_size, scalar_arg; + int vector_size = 0; + int arg_size, scalar_arg; if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { if (id == SN_get_IsSupported) { - interp_add_ins (td, MINT_LDC_I4_0); + // we return without setting vector_size if atype is unsupported + interp_add_ins (td, vector_size == 0 ? MINT_LDC_I4_0 : MINT_LDC_I4_1); goto opcode_added; } return FALSE; @@ -822,10 +824,12 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c return FALSE; MonoTypeEnum atype; - int vector_size, arg_size, scalar_arg; + int vector_size = 0; + int arg_size, scalar_arg; if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { if (id == SN_get_IsSupported) { - interp_add_ins (td, MINT_LDC_I4_0); + // we return without setting vector_size if atype is unsupported + interp_add_ins (td, vector_size == 0 ? MINT_LDC_I4_0 : MINT_LDC_I4_1); goto opcode_added; } return FALSE; From 1067f70db4f65c5a78534518feceffd48b4e4893 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 22 May 2026 11:15:08 -0700 Subject: [PATCH 3/5] Add another path to mono for handling get_IsSupported --- src/mono/mono/mini/interp/transform.c | 32 ++++++++++++++------------- src/mono/mono/mini/intrinsics.c | 13 +++++++++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index c5ee0dab944439..d6f1b633568527 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2681,13 +2681,13 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas if (!strcmp (tm, "get_IsHardwareAccelerated")) { *op = MINT_LDC_I4_0; } else if (!strcmp (tm, "get_IsSupported")) { - if (mono_class_is_ginst (target_method->klass)) { - MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { - *op = MINT_LDC_I4_1; - } else { - *op = MINT_LDC_I4_0; - } + g_assert (mono_class_is_ginst (target_method->klass)); + + MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + *op = MINT_LDC_I4_1; + } else { + *op = MINT_LDC_I4_0; } } } else if (klass_name_space[25] == '.') { @@ -2725,14 +2725,16 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas if (!strcmp ("Vector", klass_name)) { if (!strcmp (tm, "get_IsHardwareAccelerated")) { *op = MINT_LDC_I4_0; - } else if (!strcmp (tm, "get_IsSupported")) { - if (mono_class_is_ginst (target_method->klass)) { - MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { - *op = MINT_LDC_I4_1; - } else { - *op = MINT_LDC_I4_0; - } + } + } else if (!strcmp ("Vector`1", klass_name)) { + if (!strcmp (tm, "get_IsSupported")) { + g_assert (mono_class_is_ginst (target_method->klass)); + + MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + *op = MINT_LDC_I4_1; + } else { + *op = MINT_LDC_I4_0; } } } else if (!strcmp ("BitOperations", klass_name)) { diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 6ec87adc090b77..5064c0b66db118 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -2436,6 +2436,19 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->type = STACK_I4; return ins; } + + if (!strcmp (cmethod_name, "get_IsSupported")) { + g_assert (mono_class_is_ginst (cmethod->klass)); + + MonoType *element_type = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + EMIT_NEW_ICONST (cfg, ins, 1); + } else { + EMIT_NEW_ICONST (cfg, ins, 0); + } + ins->type = STACK_I4; + return ins; + } } // On FullAOT, return false for RuntimeFeature: From 5c552c0ccb4ba5d79f7b8538f69297c8bcdf364c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 22 May 2026 11:58:17 -0700 Subject: [PATCH 4/5] Handle more edge cases --- src/coreclr/interpreter/intrinsics.cpp | 3 +++ src/mono/mono/mini/interp/transform-simd.c | 2 +- src/mono/mono/mini/intrinsics.c | 15 ++++++++------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/coreclr/interpreter/intrinsics.cpp b/src/coreclr/interpreter/intrinsics.cpp index 1c855558f3aa29..8460b89a378b16 100644 --- a/src/coreclr/interpreter/intrinsics.cpp +++ b/src/coreclr/interpreter/intrinsics.cpp @@ -74,6 +74,9 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp if (!strcmp(className, "Vector") && !strcmp(methodName, "get_IsHardwareAccelerated")) return NI_IsSupported_False; + if (!strcmp(className, "Vector`1") && !strcmp(methodName, "get_IsSupported")) + return NI_IsSupported_Type; + // Fall back to managed implementation for everything else. return NI_Illegal; } diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index 72c65760a10062..2622b89c21e36d 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -755,7 +755,7 @@ emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature * const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name); bool explicitly_implemented = cmethod_name != cmethod->name; - int id = lookup_intrins (sri_vector_t_methods, sizeof (sri_vector_t_methods), cmethod->name); + int id = lookup_intrins (sri_vector_t_methods, sizeof (sri_vector_t_methods), cmethod_name); if (id == -1) { if (explicitly_implemented) { return emit_sri_vector (td, cmethod, csignature); diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 5064c0b66db118..30841b66f5bd86 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -2438,14 +2438,15 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } if (!strcmp (cmethod_name, "get_IsSupported")) { - g_assert (mono_class_is_ginst (cmethod->klass)); - - MonoType *element_type = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { - EMIT_NEW_ICONST (cfg, ins, 1); - } else { - EMIT_NEW_ICONST (cfg, ins, 0); + if (mono_class_is_ginst (cmethod->klass)) { + MonoType *element_type = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + EMIT_NEW_ICONST (cfg, ins, 1); + ins->type = STACK_I4; + return ins; + } } + EMIT_NEW_ICONST (cfg, ins, 0); ins->type = STACK_I4; return ins; } From a59cf9dcaae729d1390fe85a32ed7c870d5562ab Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 22 May 2026 17:00:15 -0700 Subject: [PATCH 5/5] Leave mono interp to handling get_IsSupported only via the central fallback --- src/mono/mono/mini/interp/transform-simd.c | 87 +++++++--------------- src/mono/mono/mini/interp/transform.c | 18 +++-- src/mono/mono/mini/intrinsics.c | 18 +++-- 3 files changed, 53 insertions(+), 70 deletions(-) diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index 2622b89c21e36d..6f689433361847 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -56,7 +56,7 @@ lookup_intrins (guint16 *intrinsics, int size, const char *cmethod_name) // These items need to be in ASCII order, which means alphabetical order where lowercase is after uppercase // i.e. all 'get_' and 'op_' need to come after regular title-case names -static guint16 sri_vector_methods [] = { +static guint16 sri_vector128_methods [] = { SN_AndNot, SN_As, SN_AsByte, @@ -96,11 +96,10 @@ static guint16 sri_vector_methods [] = { SN_get_IsHardwareAccelerated, }; -static guint16 sri_vector_t_methods [] = { +static guint16 sri_vector128_t_methods [] = { SN_EqualsFloatingPoint, SN_get_AllBitsSet, SN_get_Count, - SN_get_IsSupported, SN_get_One, SN_get_Zero, SN_op_Addition, @@ -123,7 +122,6 @@ static guint16 sn_vector_t_methods [] = { SN_ctor, SN_get_AllBitsSet, SN_get_Count, - SN_get_IsSupported, SN_get_One, SN_get_Zero, SN_op_Addition, @@ -222,18 +220,11 @@ static const char * strip_explicit_isimd_prefix (const char *cmethod_name) { if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector APIs to still be expanded where possible // but, they all prefix the qualified name of the interface first, so we'll check for that and // skip the prefix before trying to resolve the method. - - if (strncmp(cmethod_name + 70, "64,T>.", 9) == 0) { - cmethod_name += 79; - } else if ((strncmp(cmethod_name + 70, "128,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "256,T>.", 10) == 0) || - (strncmp(cmethod_name + 70, "512,T>.", 10) == 0)) { - cmethod_name += 80; - } + if (strncmp (cmethod_name + 45, "Runtime.Intrinsics.Vector128,T>.", 35) == 0) { + cmethod_name += 80; } else if (strncmp(cmethod_name + 45, "Numerics.Vector,T>.", 22) == 0) { cmethod_name += 67; } @@ -258,9 +249,6 @@ emit_common_simd_operations (TransformData *td, int id, int atype, int vector_si interp_add_ins (td, MINT_LDC_I4_S); td->last_ins->data [0] = vector_size / arg_size; return TRUE; - case SN_get_IsSupported: - interp_add_ins (td, MINT_LDC_I4_1); - return TRUE; case SN_get_One: if (atype == MONO_TYPE_I1 || atype == MONO_TYPE_U1) { interp_add_ins (td, MINT_SIMD_V128_LDC); @@ -420,9 +408,11 @@ get_common_simd_info (MonoClass *vector_klass, MonoMethodSignature *csignature, if (!mono_class_is_ginst (vector_klass)) return FALSE; MonoType *arg_type = mono_class_get_context (vector_klass)->class_inst->type_argv [0]; - if (!MONO_TYPE_IS_VECTOR_PRIMITIVE (arg_type)) + if (!mono_type_is_primitive (arg_type)) return FALSE; *atype = arg_type->type; + if (*atype == MONO_TYPE_BOOLEAN) + return FALSE; *vector_size = mono_class_value_size (vector_klass, NULL); if (*vector_size != SIZEOF_V128) return FALSE; @@ -522,7 +512,7 @@ emit_vector_create (TransformData *td, MonoMethodSignature *csignature, MonoClas } static gboolean -emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) +emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) { if (csignature->hasthis) return FALSE; @@ -533,13 +523,18 @@ emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs #endif const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name); - int id = lookup_intrins (sri_vector_methods, sizeof (sri_vector_methods), cmethod_name); + int id = lookup_intrins (sri_vector128_methods, sizeof (sri_vector128_methods), cmethod_name); if (id == -1) return FALSE; MonoClass *vector_klass = NULL; int vector_size = 0; + if (id == SN_get_IsHardwareAccelerated) { + interp_add_ins (td, MINT_LDC_I4_1); + goto opcode_added; + } + gint16 simd_opcode = -1; gint16 simd_intrins = -1; @@ -553,20 +548,8 @@ emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs MonoTypeEnum atype; int arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { - if (id == SN_get_IsHardwareAccelerated) { - interp_add_ins (td, MINT_LDC_I4_0); - goto opcode_added; - } + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) return FALSE; - } - - g_assert (vector_size == SIZEOF_V128); - - if (id == SN_get_IsHardwareAccelerated) { - interp_add_ins (td, MINT_LDC_I4_1); - goto opcode_added; - } switch (id) { case SN_AndNot: @@ -746,7 +729,7 @@ emit_sri_vector (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs } static gboolean -emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) +emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature) { #ifdef HOST_BROWSER if (emit_sri_packedsimd (td, cmethod, csignature)) @@ -755,10 +738,10 @@ emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature * const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name); bool explicitly_implemented = cmethod_name != cmethod->name; - int id = lookup_intrins (sri_vector_t_methods, sizeof (sri_vector_t_methods), cmethod_name); + int id = lookup_intrins (sri_vector128_t_methods, sizeof (sri_vector128_t_methods), cmethod->name); if (id == -1) { if (explicitly_implemented) { - return emit_sri_vector (td, cmethod, csignature); + return emit_sri_vector128 (td, cmethod, csignature); } else { return FALSE; } @@ -771,16 +754,9 @@ emit_sri_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature * MonoClass *vector_klass = cmethod->klass; MonoTypeEnum atype; - int vector_size = 0; - int arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { - if (id == SN_get_IsSupported) { - // we return without setting vector_size if atype is unsupported - interp_add_ins (td, vector_size == 0 ? MINT_LDC_I4_0 : MINT_LDC_I4_1); - goto opcode_added; - } + int vector_size, arg_size, scalar_arg; + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) return FALSE; - } if (emit_common_simd_operations (td, id, atype, vector_size, arg_size, scalar_arg, &simd_opcode, &simd_intrins)) goto opcode_added; @@ -809,7 +785,7 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name); if (id == -1) { if (explicitly_implemented) { - return emit_sri_vector (td, cmethod, csignature); + return emit_sri_vector128 (td, cmethod, csignature); } else { return FALSE; } @@ -824,16 +800,9 @@ emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *c return FALSE; MonoTypeEnum atype; - int vector_size = 0; - int arg_size, scalar_arg; - if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) { - if (id == SN_get_IsSupported) { - // we return without setting vector_size if atype is unsupported - interp_add_ins (td, vector_size == 0 ? MINT_LDC_I4_0 : MINT_LDC_I4_1); - goto opcode_added; - } + int vector_size, arg_size, scalar_arg; + if (!get_common_simd_info (vector_klass, csignature, &atype, &vector_size, &arg_size, &scalar_arg)) return FALSE; - } if (emit_common_simd_operations (td, id, atype, vector_size, arg_size, scalar_arg, &simd_opcode, &simd_intrins)) { goto opcode_added; @@ -1368,13 +1337,13 @@ interp_emit_simd_intrinsics (TransformData *td, MonoMethod *cmethod, MonoMethodS class_name = m_class_get_name (cmethod->klass); if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { - if (!strcmp (class_name, "Vector64") || !strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector256") || !strcmp (class_name, "Vector512")) - return emit_sri_vector (td, cmethod, csignature); - if (!strcmp (class_name, "Vector64`1") || !strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector256`1") || !strcmp (class_name, "Vector512`1")) - return emit_sri_vector_t (td, cmethod, csignature); + if (!strcmp (class_name, "Vector128")) + return emit_sri_vector128 (td, cmethod, csignature); + else if (!strcmp (class_name, "Vector128`1")) + return emit_sri_vector128_t (td, cmethod, csignature); } else if (!strcmp (class_ns, "System.Numerics")) { if (!strcmp (class_name, "Vector")) - return emit_sri_vector (td, cmethod, csignature); + return emit_sri_vector128 (td, cmethod, csignature); else if (!strcmp (class_name, "Vector`1")) return emit_sn_vector_t (td, cmethod, csignature, newobj); else if (!strcmp (class_name, "Vector4")) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index d6f1b633568527..756e31e561beec 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2683,10 +2683,13 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } else if (!strcmp (tm, "get_IsSupported")) { g_assert (mono_class_is_ginst (target_method->klass)); - MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + // Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified + MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) { *op = MINT_LDC_I4_1; - } else { + } else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) { + // Happens often in gshared code *op = MINT_LDC_I4_0; } } @@ -2730,10 +2733,13 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas if (!strcmp (tm, "get_IsSupported")) { g_assert (mono_class_is_ginst (target_method->klass)); - MonoType *element_type = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + // Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified + MonoType *etype = mono_class_get_context (target_method->klass)->class_inst->type_argv [0]; + + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) { *op = MINT_LDC_I4_1; - } else { + } else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) { + // Happens often in gshared code *op = MINT_LDC_I4_0; } } diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 30841b66f5bd86..c6ccaf7d0701db 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -2439,16 +2439,24 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign if (!strcmp (cmethod_name, "get_IsSupported")) { if (mono_class_is_ginst (cmethod->klass)) { - MonoType *element_type = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; - if (MONO_TYPE_IS_VECTOR_PRIMITIVE (element_type)) { + // Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified + MonoType *etype = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; + + if (MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) { EMIT_NEW_ICONST (cfg, ins, 1); ins->type = STACK_I4; return ins; + } else if (mini_type_get_underlying_type (etype)->type == MONO_TYPE_OBJECT) { + // Happens often in gshared code + EMIT_NEW_ICONST (cfg, ins, 0); + ins->type = STACK_I4; + return ins; } + } else { + EMIT_NEW_ICONST (cfg, ins, 0); + ins->type = STACK_I4; + return ins; } - EMIT_NEW_ICONST (cfg, ins, 0); - ins->type = STACK_I4; - return ins; } }