From acd4855de9be7b51c853c4e5c719aa456a4865c9 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 17 Dec 2020 04:42:02 +0300 Subject: [PATCH] RyuJIT: Don't emit cast helpers for (T)array.Clone() (#45311) Note that Array.Clone()'s return type is the same as the type of its first operand. This allows optimization of casts on the result of calls to Clone(). --- src/coreclr/jit/gentree.cpp | 8 ++++++++ src/coreclr/jit/importer.cpp | 7 +++++++ src/coreclr/jit/namedintrinsiclist.h | 1 + src/libraries/System.Private.CoreLib/src/System/Array.cs | 1 + 4 files changed, 17 insertions(+) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 1ed01b16f4122..5b9a88c1d6a89 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17757,6 +17757,14 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b case GT_CALL: { GenTreeCall* call = tree->AsCall(); + if (call->gtFlags & CORINFO_FLG_JIT_INTRINSIC) + { + if (lookupNamedIntrinsic(call->gtCallMethHnd) == NI_System_Array_Clone) + { + objClass = gtGetClassHandle(call->gtCallThisArg->GetNode(), pIsExact, pIsNonNull); + break; + } + } if (call->IsInlineCandidate()) { // For inline candidates, we've already cached the return diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index ff6556dab12b6..aa75207070bd3 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4809,6 +4809,13 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) result = NI_System_GC_KeepAlive; } } + else if (strcmp(className, "Array") == 0) + { + if (strcmp(methodName, "Clone") == 0) + { + result = NI_System_Array_Clone; + } + } else if (strcmp(className, "Type") == 0) { if (strcmp(methodName, "get_IsValueType") == 0) diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 4e851fb19a7f2..c223307eebe9f 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -43,6 +43,7 @@ enum NamedIntrinsic : unsigned short NI_System_Type_get_IsValueType, NI_System_Type_IsAssignableFrom, NI_System_Type_IsAssignableTo, + NI_System_Array_Clone, // These are used by HWIntrinsics but are defined more generally // to allow dead code optimization and handle the recursion case diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.cs b/src/libraries/System.Private.CoreLib/src/System/Array.cs index 1e0fca689b40c..85d353343aa6f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.cs @@ -319,6 +319,7 @@ void IList.RemoveAt(int index) // Make a new array which is a shallow copy of the original array. // + [Intrinsic] public object Clone() { return MemberwiseClone();