*pLclVarTree = addrArgLcl;
if (pIsEntire != NULL)
{
- unsigned lclNum = addrArgLcl->GetLclNum();
- unsigned varWidth = comp->lvaLclExactSize(lclNum);
- if (comp->lvaTable[lclNum].lvNormalizeOnStore())
+ unsigned lclOffset = 0;
+ if (addrArg->OperIsLocalField())
{
- // It's normalize on store, so use the full storage width -- writing to low bytes won't
- // necessarily yield a normalized value.
- varWidth = genTypeStSz(var_types(comp->lvaTable[lclNum].lvType)) * sizeof(int);
+ lclOffset = addrArg->gtLclFld.gtLclOffs;
+ }
+
+ if (lclOffset != 0)
+ {
+ // We aren't updating the bytes at [0..lclOffset-1] so *pIsEntire should be set to false
+ *pIsEntire = false;
+ }
+ else
+ {
+ unsigned lclNum = addrArgLcl->GetLclNum();
+ unsigned varWidth = comp->lvaLclExactSize(lclNum);
+ if (comp->lvaTable[lclNum].lvNormalizeOnStore())
+ {
+ // It's normalize on store, so use the full storage width -- writing to low bytes won't
+ // necessarily yield a normalized value.
+ varWidth = genTypeStSz(var_types(comp->lvaTable[lclNum].lvType)) * sizeof(int);
+ }
+ *pIsEntire = (varWidth == width);
}
- *pIsEntire = (varWidth == width);
}
return true;
}
GenTreeLclVarCommon* rhsLclVarTree = nullptr;
FieldSeqNode* rhsFldSeq = nullptr;
ValueNumPair rhsVNPair;
-#ifdef DEBUG
bool isNewUniq = false;
-#endif
+
if (srcAddr->IsLocalAddrExpr(this, &rhsLclVarTree, &rhsFldSeq))
{
unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
LclVarDsc* rhsVarDsc = &lvaTable[rhsLclNum];
if (fgExcludeFromSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
{
- rhsVNPair.SetBoth(vnStore->VNForExpr(lclVarTree->TypeGet()));
-#ifdef DEBUG
isNewUniq = true;
-#endif
}
else
{
}
else
{
- JITDUMP(" *** Missing field sequence info for COPYBLK\n");
+ JITDUMP(" *** Missing field sequence info for Src/RHS of COPYBLK\n");
rhsVNPair.SetBoth(vnStore->VNForExpr(indType)); // a new unique value number
}
}
}
else
{
- rhsVNPair.SetBoth(vnStore->VNForExpr(lclVarTree->TypeGet()));
-#ifdef DEBUG
isNewUniq = true;
-#endif
}
}
else
{
- rhsVNPair.SetBoth(vnStore->VNForExpr(lclVarTree->TypeGet()));
-#ifdef DEBUG
- isNewUniq = true;
-#endif
+ isNewUniq = true;
}
- ValueNumPair newRhsVNPair;
- if (lhsFldSeq != nullptr && isEntire)
+ if (lhsFldSeq == FieldSeqStore::NotAField())
+ {
+ // We don't have proper field sequence information for the lhs
+ //
+ JITDUMP(" *** Missing field sequence info for Dst/LHS of COPYBLK\n");
+ isNewUniq = true;
+ }
+ else if (lhsFldSeq != nullptr && isEntire)
{
// This can occur in for structs with one field, itself of a struct type.
// We won't promote these.
// TODO-Cleanup: decide what exactly to do about this.
// Always treat them as maps, making them use/def, or reconstitute the
// map view here?
- newRhsVNPair.SetBoth(vnStore->VNForExpr(TYP_STRUCT));
+ isNewUniq = true;
}
- else
+ else if (!isNewUniq)
{
ValueNumPair oldLhsVNPair = lvaTable[lhsLclNum].GetPerSsaData(lclVarTree->GetSsaNum())->m_vnPair;
- newRhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lhsFldSeq, rhsVNPair, lclVarTree->TypeGet());
+ rhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lhsFldSeq, rhsVNPair, lclVarTree->TypeGet());
}
- lvaTable[lhsLclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = vnStore->VNPNormVal(newRhsVNPair);
+
+ if (isNewUniq)
+ {
+ rhsVNPair.SetBoth(vnStore->VNForExpr(lclVarTree->TypeGet()));
+ }
+
+ lvaTable[lhsLclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = vnStore->VNPNormVal(rhsVNPair);
+
#ifdef DEBUG
if (verbose)
{
printf("Tree ");
Compiler::printTreeID(tree);
- printf(" assigned VN to local var V%02u/%d: ",
- lhsLclNum, lclDefSsaNum);
+ printf(" assigned VN to local var V%02u/%d: ", lhsLclNum, lclDefSsaNum);
if (isNewUniq)
printf("new uniq ");
- vnpPrint(newRhsVNPair, 1);
+ vnpPrint(rhsVNPair, 1);
printf("\n");
}
#endif // DEBUG
- }
- }
+
+ }
+ }
else
{
// For now, arbitrary side effect on Heap.