Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 53 additions & 12 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11085,11 +11085,15 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
#endif // TARGET_ARM

// Can't use field by field assignment if the src is a call.
// Don't use field by field assignment if the src is a call
//
// TODO: Document why do we have this restriction?
// Maybe it isn't needed, or maybe it is only needed
// for calls that return multiple registers
//
if (src->OperGet() == GT_CALL)
{
JITDUMP(" src is a call");
// C++ style CopyBlock with holes
requiresCopyBlock = true;
}

Expand Down Expand Up @@ -11330,8 +11334,10 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
// address value once...)
if (destLclVar->lvFieldCnt > 1)
{
addrSpill = gtCloneExpr(srcAddr); // addrSpill represents the 'srcAddr'
noway_assert(addrSpill != nullptr);
// We will spill srcAddr (i.e. assign to a temp "BlockOp address local")
// no need to clone a new copy as it is only used once
//
addrSpill = srcAddr; // addrSpill represents the 'srcAddr'
}
}
}
Expand Down Expand Up @@ -11363,8 +11369,10 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
// use the address value once...)
if (srcLclVar->lvFieldCnt > 1)
{
addrSpill = gtCloneExpr(destAddr); // addrSpill represents the 'destAddr'
noway_assert(addrSpill != nullptr);
// We will spill destAddr (i.e. assign to a temp "BlockOp address local")
// no need to clone a new copy as it is only used once
//
addrSpill = destAddr; // addrSpill represents the 'destAddr'
}
}
}
Expand All @@ -11388,8 +11396,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)

if (addrSpill != nullptr)
{
// Simplify the address if possible, and mark as DONT_CSE as needed..
addrSpill = fgMorphTree(addrSpill);
// 'addrSpill' is already morphed

// Spill the (complex) address to a BYREF temp.
// Note, at most one address may need to be spilled.
Expand Down Expand Up @@ -11470,8 +11477,25 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
else
{
dstFld = gtCloneExpr(destAddr);
noway_assert(dstFld != nullptr);
if (i == 0)
{
// Use the orginal destAddr tree when i == 0
dstFld = destAddr;
}
else
{
// We can't clone multiple copies of a tree with persistent side effects
noway_assert((destAddr->gtFlags & GTF_PERSISTENT_SIDE_EFFECTS) == 0);

dstFld = gtCloneExpr(destAddr);
noway_assert(dstFld != nullptr);

JITDUMP("dstFld - Multiple Fields Clone created:\n");
DISPTREE(dstFld);

// Morph the newly created tree
dstFld = fgMorphTree(dstFld);
}

// Is the address of a local?
GenTreeLclVarCommon* lclVarTree = nullptr;
Expand Down Expand Up @@ -11550,8 +11574,25 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
else
{
srcFld = gtCloneExpr(srcAddr);
noway_assert(srcFld != nullptr);
if (i == 0)
{
// Use the orginal srcAddr tree when i == 0
srcFld = srcAddr;
}
else
{
// We can't clone multiple copies of a tree with persistent side effects
noway_assert((srcAddr->gtFlags & GTF_PERSISTENT_SIDE_EFFECTS) == 0);

srcFld = gtCloneExpr(srcAddr);
noway_assert(srcFld != nullptr);

JITDUMP("srcFld - Multiple Fields Clone created:\n");
DISPTREE(srcFld);

// Morph the newly created tree
srcFld = fgMorphTree(srcFld);
}
}

CORINFO_CLASS_HANDLE classHnd = lvaTable[destLclNum].GetStructHnd();
Expand Down