JIT: Fix new helper calls for some block copies involving promoted locals (#86246)
authorJakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Mon, 15 May 2023 21:56:53 +0000 (23:56 +0200)
committerGitHub <noreply@github.com>
Mon, 15 May 2023 21:56:53 +0000 (23:56 +0200)
The change in #85620 was missing a check for the case where the
destination is not on stack but the source is. The backend still uses a
helper call for this case.

The field-by-field case would also usually involve helper calls since it
would normally need write barriers; however, the exception were for
byref fields, so Span<T>/ReadOnlySpan<T> were particularly affected.

src/coreclr/jit/morphblock.cpp

index fca0c73..329e9c1 100644 (file)
@@ -830,10 +830,13 @@ void MorphCopyBlockHelper::MorphStructCases()
         // A simple heuristic when field by field copy is preferred:
         // - if fields can be enregistered;
         // - if the struct has only one field.
+        // - if the copy involves GC pointers and the destination isn't stack (backend uses a helper for these block
+        // copies)
         bool dstFldIsProfitable =
             ((m_dstVarDsc != nullptr) && (!m_dstVarDsc->lvDoNotEnregister || (m_dstVarDsc->lvFieldCnt == 1)));
-        bool srcFldIsProfitable =
-            ((m_srcVarDsc != nullptr) && (!m_srcVarDsc->lvDoNotEnregister || (m_srcVarDsc->lvFieldCnt == 1)));
+        bool srcFldIsProfitable = ((m_srcVarDsc != nullptr) && (!m_srcVarDsc->lvDoNotEnregister ||
+                                                                (m_srcVarDsc->HasGCPtr() && (m_dstVarDsc == nullptr)) ||
+                                                                (m_srcVarDsc->lvFieldCnt == 1)));
         // Are both dest and src promoted structs?
         if (m_dstDoFldAsg && m_srcDoFldAsg && (dstFldIsProfitable || srcFldIsProfitable))
         {