From baa7617de72331c4c4100e2abaee27d9ac43bd32 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Apr 2022 09:48:37 -0700 Subject: [PATCH 1/3] Consider Type.IsByRefLike an intrinsic when possible --- src/coreclr/jit/fgbasic.cpp | 1 + src/coreclr/jit/importer.cpp | 30 +++++++++++++++++++ src/coreclr/jit/namedintrinsiclist.h | 1 + .../System.Private.CoreLib/src/System/Type.cs | 4 +-- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 8151dff192377a..632978641b9ee1 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -1160,6 +1160,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed // These are foldable if the first argument is a constant case NI_System_Type_get_IsValueType: + case NI_System_Type_get_IsByRefLike: case NI_System_Type_GetTypeFromHandle: case NI_System_String_get_Length: case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness: diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 54cedb357958ba..d42a21e47c4853 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4311,6 +4311,32 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, break; } + case NI_System_Type_get_IsByRefLike: + { + // Optimize + // + // call Type.GetTypeFromHandle (which is replaced with CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) + // call Type.IsByRefLike + // + // to `true` or `false` + // e.g. `typeof(Span).IsByRefLike` => `true` + if (impStackTop().val->IsCall()) + { + GenTreeCall* call = impStackTop().val->AsCall(); + if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE)) + { + CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(call->gtCallArgs->GetNode()); + if (hClass != NO_CLASS_HANDLE) + { + retNode = gtNewIconNode( + (info.compCompHnd->getClassAttribs(hClass) & CORINFO_FLG_BYREF_LIKE) ? 1 : 0); + impPopStack(); // drop CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE call + } + } + } + break; + } + case NI_System_Threading_Thread_get_ManagedThreadId: { if (impStackTop().val->OperIs(GT_RET_EXPR)) @@ -5251,6 +5277,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_Type_get_IsValueType; } + else if (strcmp(methodName, "get_IsByRefLike") == 0) + { + result = NI_System_Type_get_IsByRefLike; + } else if (strcmp(methodName, "IsAssignableFrom") == 0) { result = NI_System_Type_IsAssignableFrom; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 7f66f33e41d2e1..8d5a2f29b1c789 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -56,6 +56,7 @@ enum NamedIntrinsic : unsigned short NI_System_Threading_Thread_get_CurrentThread, NI_System_Threading_Thread_get_ManagedThreadId, NI_System_Type_get_IsValueType, + NI_System_Type_get_IsByRefLike, NI_System_Type_IsAssignableFrom, NI_System_Type_IsAssignableTo, NI_System_Type_op_Equality, diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index f92f977a0f1c6e..cf1b6e32f480a2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -51,7 +51,7 @@ protected Type() { } public virtual bool IsSZArray => throw NotImplemented.ByDesign; public virtual bool IsVariableBoundArray => IsArray && !IsSZArray; - public virtual bool IsByRefLike => throw new NotSupportedException(SR.NotSupported_SubclassOverride); + public virtual bool IsByRefLike { [Intrinsic] get => throw new NotSupportedException(SR.NotSupported_SubclassOverride); } public bool HasElementType => HasElementTypeImpl(); protected abstract bool HasElementTypeImpl(); @@ -110,10 +110,10 @@ public virtual Type[] GetGenericParameterConstraints() public bool IsPrimitive => IsPrimitiveImpl(); protected abstract bool IsPrimitiveImpl(); public bool IsValueType { [Intrinsic] get => IsValueTypeImpl(); } + protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType)); [Intrinsic] public bool IsAssignableTo([NotNullWhen(true)] Type? targetType) => targetType?.IsAssignableFrom(this) ?? false; - protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType)); public virtual bool IsSignatureType => false; From 78c0469b0ac49129f2077a8162ea620e954d6f82 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Apr 2022 10:52:02 -0700 Subject: [PATCH 2/3] Collapse IsValueType and IsByRefLike intrinsic logic --- src/coreclr/jit/importer.cpp | 54 ++++++++++++++---------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index d42a21e47c4853..c580ca33313adf 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4282,44 +4282,16 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, } case NI_System_Type_get_IsValueType: - { - // Optimize - // - // call Type.GetTypeFromHandle (which is replaced with CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) - // call Type.IsValueType - // - // to `true` or `false` - // e.g. `typeof(int).IsValueType` => `true` - if (impStackTop().val->IsCall()) - { - GenTreeCall* call = impStackTop().val->AsCall(); - if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE)) - { - CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(call->gtCallArgs->GetNode()); - if (hClass != NO_CLASS_HANDLE) - { - retNode = - gtNewIconNode((eeIsValueClass(hClass) && - // pointers are not value types (e.g. typeof(int*).IsValueType is false) - info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR) - ? 1 - : 0); - impPopStack(); // drop CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE call - } - } - } - break; - } - case NI_System_Type_get_IsByRefLike: { // Optimize // // call Type.GetTypeFromHandle (which is replaced with CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) - // call Type.IsByRefLike + // call Type.IsXXX // // to `true` or `false` - // e.g. `typeof(Span).IsByRefLike` => `true` + // e.g., `typeof(int).IsValueType` => `true` + // e.g., `typeof(Span).IsByRefLike` => `true` if (impStackTop().val->IsCall()) { GenTreeCall* call = impStackTop().val->AsCall(); @@ -4328,8 +4300,24 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(call->gtCallArgs->GetNode()); if (hClass != NO_CLASS_HANDLE) { - retNode = gtNewIconNode( - (info.compCompHnd->getClassAttribs(hClass) & CORINFO_FLG_BYREF_LIKE) ? 1 : 0); + switch (ni) + { + case NI_System_Type_get_IsValueType: + retNode = + gtNewIconNode((eeIsValueClass(hClass) && + // pointers are not value types (e.g. typeof(int*).IsValueType is false) + info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR) + ? 1 + : 0); + break; + case NI_System_Type_get_IsByRefLike: + retNode = gtNewIconNode( + (info.compCompHnd->getClassAttribs(hClass) & CORINFO_FLG_BYREF_LIKE) ? 1 : 0); + break; + default: + NO_WAY("Intrinsic not supported in this path."); + } + impPopStack(); // drop CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE call } } From fc6a80d879759ea5c085279c69a836c3b2862e1e Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Apr 2022 12:15:57 -0700 Subject: [PATCH 3/3] Apply style updates --- src/coreclr/jit/importer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index c580ca33313adf..88be725e8b26ff 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4303,12 +4303,12 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, switch (ni) { case NI_System_Type_get_IsValueType: - retNode = - gtNewIconNode((eeIsValueClass(hClass) && - // pointers are not value types (e.g. typeof(int*).IsValueType is false) - info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR) - ? 1 - : 0); + retNode = gtNewIconNode( + (eeIsValueClass(hClass) && + // pointers are not value types (e.g. typeof(int*).IsValueType is false) + info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR) + ? 1 + : 0); break; case NI_System_Type_get_IsByRefLike: retNode = gtNewIconNode(