BasicBlock* block /* = NULL */
)
{
- var_types destType;
GenTree* dest = nullptr;
unsigned destFlags = 0;
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)
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;
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)