Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 53 additions & 26 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,39 @@ private uint getClassNumInstanceFields(CORINFO_CLASS_STRUCT_* cls)
throw new InvalidOperationException();
}

//------------------------------------------------------------------------
// IsSimdIntrinsicType: Check whether a type is one of the SIMD types that the
// JIT considers to be a primitive.
//
// Arguments:
// type - The type to check.
//
// Return Value:
// True if the type is a SIMD type; otherwise false.
//
// Remarks:
// This is an explicit allow list mirroring the types recognized by
// Compiler::getBaseTypeAndSizeOfSIMDType. The other intrinsic types in these
// namespaces (Decimal32/Decimal64/Decimal128, Matrix3x2/Matrix4x4) are laid
// out like any other struct, so the JIT needs their fields reported.
//
private static bool IsSimdIntrinsicType(MetadataType type)
{
if (VectorFieldLayoutAlgorithm.IsVectorType(type) || VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(type))
{
return true;
}

if (!type.IsIntrinsic || type.Namespace != "System.Numerics"u8)
{
return false;
}

Utf8Span name = type.Name;
return name == "Vector2"u8 || name == "Vector3"u8 || name == "Vector4"u8 ||
name == "Quaternion"u8 || name == "Plane"u8;
}

private GetTypeLayoutResult GetTypeLayoutHelper(MetadataType type, uint parentIndex, uint baseOffs, FieldDesc field, CORINFO_TYPE_LAYOUT_NODE* treeNodes, nuint maxTreeNodes, nuint* numTreeNodes)
{
if (*numTreeNodes >= maxTreeNodes)
Expand Down Expand Up @@ -2711,37 +2744,31 @@ private GetTypeLayoutResult GetTypeLayoutHelper(MetadataType type, uint parentIn
#endif

// The intrinsic SIMD/HW SIMD types have a lot of fields that the JIT does
// not care about since they are considered primitives by the JIT. The IEEE 754
// decimal floating-point types are the System.Numerics intrinsics that are not
// SIMD, so the JIT lays them out like any other struct and needs their fields.
if (type.IsIntrinsic && !type.IsDecimalFloatingPointOrHasDecimalFloatingPointFields)
// not care about since they are considered primitives by the JIT.
if (IsSimdIntrinsicType(type))
{
Utf8Span ns = type.Namespace;
if (ns == "System.Runtime.Intrinsics"u8 || ns == "System.Numerics"u8)
parNode->simdTypeHnd = ObjectToHandle(type);
if (parentIndex != uint.MaxValue)
{
parNode->simdTypeHnd = ObjectToHandle(type);
if (parentIndex != uint.MaxValue)
{
#if READYTORUN
if (NeedsTypeLayoutCheck(type))
{
// We cannot allow the JIT to call getClassSize for
// arbitrary types of fields as it will insert a fixup
// that we may not be able to encode. We could skip the
// field, but that will make prejit promotion different
// from the runtime promotion. We could also change the
// JIT to avoid calling getClassSize and just use the
// size from the returned node, but for that we would
// need to be sure that the type layout check fixup
// added in getTypeLayout is sufficient to guarantee
// the size of all these intrinsically handled SIMD
// types.
return GetTypeLayoutResult.Failure;
}
if (NeedsTypeLayoutCheck(type))
{
// We cannot allow the JIT to call getClassSize for
// arbitrary types of fields as it will insert a fixup
// that we may not be able to encode. We could skip the
// field, but that will make prejit promotion different
// from the runtime promotion. We could also change the
// JIT to avoid calling getClassSize and just use the
// size from the returned node, but for that we would
// need to be sure that the type layout check fixup
// added in getTypeLayout is sufficient to guarantee
// the size of all these intrinsically handled SIMD
// types.
return GetTypeLayoutResult.Failure;
}
#endif

return GetTypeLayoutResult.Success;
}
return GetTypeLayoutResult.Success;
}
}

Expand Down
75 changes: 61 additions & 14 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,62 @@ CEEInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
return result;
}

//------------------------------------------------------------------------
// IsSimdIntrinsicType: Check whether a type is one of the SIMD types that the
// JIT considers to be a primitive.
//
// Arguments:
// pMT - The type to check.
//
// Return Value:
// True if the type is a SIMD type; otherwise false.
//
// Remarks:
// This is an explicit allow list mirroring the types recognized by
// Compiler::getBaseTypeAndSizeOfSIMDType. The other intrinsic types in these
// namespaces (Decimal32/Decimal64/Decimal128, Matrix3x2/Matrix4x4) are laid
// out like any other struct, so the JIT needs their fields reported.
//
static bool IsSimdIntrinsicType(MethodTable* pMT)
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
FORBID_FAULT;
}
CONTRACTL_END;

if (!pMT->IsIntrinsicType())
{
return false;
}

LPCUTF8 nsName;
LPCUTF8 className = pMT->GetFullyQualifiedNameInfo(&nsName);

// GetFullyQualifiedNameInfo returns NULL on failure and can legitimately report a NULL namespace.
if ((className == NULL) || (nsName == NULL))
{
return false;
}

if (strcmp(nsName, "System.Runtime.Intrinsics") == 0)
{
return (strcmp(className, "Vector128`1") == 0) || (strcmp(className, "Vector64`1") == 0) ||
(strcmp(className, "Vector256`1") == 0) || (strcmp(className, "Vector512`1") == 0);
}

if (strcmp(nsName, "System.Numerics") == 0)
{
return (strcmp(className, "Vector`1") == 0) || (strcmp(className, "Vector2") == 0) ||
(strcmp(className, "Vector3") == 0) || (strcmp(className, "Vector4") == 0) ||
(strcmp(className, "Quaternion") == 0) || (strcmp(className, "Plane") == 0);
}

return false;
}

static GetTypeLayoutResult GetTypeLayoutHelper(
MethodTable* pMT,
unsigned parentIndex,
Expand Down Expand Up @@ -2023,22 +2079,13 @@ static GetTypeLayoutResult GetTypeLayoutHelper(
parNode.hasSignificantPadding = pClass->HasExplicitFieldOffsetLayout() || pClass->HasExplicitSize();

// The intrinsic SIMD/HW SIMD types have a lot of fields that the JIT does
// not care about since they are considered primitives by the JIT. The IEEE 754
// decimal floating-point types are the System.Numerics intrinsics that are not
// SIMD, so the JIT lays them out like any other struct and needs their fields.
if (pMT->IsIntrinsicType() && !pMT->IsDecimalFloatingPointOrHasDecimalFloatingPointFields())
// not care about since they are considered primitives by the JIT.
if (IsSimdIntrinsicType(pMT))
{
const char* nsName;
pMT->GetFullyQualifiedNameInfo(&nsName);

if ((strcmp(nsName, "System.Runtime.Intrinsics") == 0) ||
(strcmp(nsName, "System.Numerics") == 0))
parNode.simdTypeHnd = CORINFO_CLASS_HANDLE(pMT);
if (parentIndex != UINT32_MAX)
{
parNode.simdTypeHnd = CORINFO_CLASS_HANDLE(pMT);
if (parentIndex != UINT32_MAX)
{
return GetTypeLayoutResult::Success;
}
return GetTypeLayoutResult::Success;
}
}

Expand Down
Loading