Fix struct assignment where types differ
authorCarol Eidt <carol.eidt@microsoft.com>
Thu, 31 Oct 2019 15:16:37 +0000 (08:16 -0700)
committerCarol Eidt <carol.eidt@microsoft.com>
Thu, 31 Oct 2019 15:16:37 +0000 (08:16 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/3220c89e9e5e9b4879efa941c3d04c0debcee41c

src/coreclr/src/jit/importer.cpp

index dea6d81..8d33f43 100644 (file)
@@ -1170,7 +1170,6 @@ GenTree* Compiler::impAssignStructPtr(GenTree*             destAddr,
                                       BasicBlock*          block       /* = NULL */
                                       )
 {
-    var_types destType;
     GenTree*  dest      = nullptr;
     unsigned  destFlags = 0;
 
@@ -1182,23 +1181,6 @@ GenTree* Compiler::impAssignStructPtr(GenTree*             destAddr,
     assert(src->OperIs(GT_LCL_VAR, GT_FIELD, GT_IND, GT_OBJ, GT_CALL, GT_MKREFANY, GT_RET_EXPR, GT_COMMA) ||
            (src->TypeGet() != TYP_STRUCT && (src->OperIsSimdOrHWintrinsic() || src->OperIs(GT_LCL_FLD))));
 
-    if (destAddr->OperGet() == GT_ADDR)
-    {
-        GenTree* destNode = destAddr->gtGetOp1();
-        // If the actual destination is a local, or already a block node, or is a node that
-        // will be morphed, don't insert an OBJ(ADDR).
-        if (destNode->gtOper == GT_INDEX || destNode->OperIsBlk() ||
-            ((destNode->OperGet() == GT_LCL_VAR) && (destNode->TypeGet() == src->TypeGet())))
-        {
-            dest = destNode;
-        }
-        destType = destNode->TypeGet();
-    }
-    else
-    {
-        destType = src->TypeGet();
-    }
-
     var_types asgType = src->TypeGet();
 
     if (src->gtOper == GT_CALL)
@@ -1309,13 +1291,6 @@ GenTree* Compiler::impAssignStructPtr(GenTree*             destAddr,
             src->gtType  = genActualType(returnType);
             call->gtType = src->gtType;
 
-            // If we've changed the type, and it no longer matches a local destination,
-            // we must use an indirection.
-            if ((dest != nullptr) && (dest->OperGet() == GT_LCL_VAR) && (dest->TypeGet() != asgType))
-            {
-                dest = nullptr;
-            }
-
             // !!! The destination could be on stack. !!!
             // This flag will let us choose the correct write barrier.
             destFlags = GTF_IND_TGTANYWHERE;
@@ -1407,6 +1382,19 @@ GenTree* Compiler::impAssignStructPtr(GenTree*             destAddr,
         asgType     = impNormStructType(structHnd);
         src->gtType = asgType;
     }
+    if ((dest == nullptr) && (destAddr->OperGet() == GT_ADDR))
+    {
+        GenTree* destNode = destAddr->gtGetOp1();
+        // If the actual destination is a local, or already a block node, or is a node that
+        // will be morphed, don't insert an OBJ(ADDR) if it already has the right type.
+        CORINFO_CLASS_HANDLE destClass = gtGetStructHandleIfPresent(destNode);
+        if ((destClass == structHnd) && (destNode->TypeGet() == asgType) &&
+            ((destNode->gtOper == GT_INDEX) || destNode->OperIsBlk() || (destNode->OperGet() == GT_LCL_VAR)))
+        {
+            dest = destNode;
+        }
+    }
+
     if (dest == nullptr)
     {
         if (asgType == TYP_STRUCT)