Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
response review.
  • Loading branch information
Sergey committed Aug 24, 2021
commit e438e3d86d35a845d44691062045113eac9668ef
2 changes: 2 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5208,6 +5208,8 @@ class Compiler
// Does value-numbering for a block assignment.
void fgValueNumberBlockAssignment(GenTree* tree);

bool fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree, GenTreeLclVarCommon* rhsLclVarTree);

// Does value-numbering for a cast tree.
void fgValueNumberCastTree(GenTree* tree);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lclmorph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>

haveCorrectFieldForVN =
compiler->info.compCompHnd->doesFieldBelongToClass(field->gtFldHnd, clsHnd);
assert(haveCorrectFieldForVN);
noway_assert(haveCorrectFieldForVN);
}
}
}
Expand Down
113 changes: 66 additions & 47 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7116,7 +7116,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
unsigned lhsLclNum = lclVarTree->GetLclNum();
FieldSeqNode* lhsFldSeq = nullptr;
unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclNum);
LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclNum);
// If it's excluded from SSA, don't need to do anything.
if (lvaInSsa(lhsLclNum) && lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
{
Expand Down Expand Up @@ -7269,52 +7269,9 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
isNewUniq = true;
}

if (!isNewUniq && (rhsVarDsc != nullptr) && (lhsVarDsc != nullptr))
if (!isNewUniq && (lclVarTree != nullptr) && (rhsLclVarTree != nullptr))
{
if (rhsLclVarTree->TypeGet() == TYP_STRUCT)
{
if (rhsLclVarTree->TypeGet() == lclVarTree->TypeGet())
{
assert(rhsVarDsc->TypeGet() == TYP_STRUCT);
assert(lhsVarDsc->TypeGet() == TYP_STRUCT);

CORINFO_CLASS_HANDLE rhsStructHnd = NO_CLASS_HANDLE;
CORINFO_CLASS_HANDLE lhsStructHnd = NO_CLASS_HANDLE;

if (rhsFldSeq == nullptr)
{
rhsStructHnd = rhsVarDsc->GetStructHnd();
}
else
{
CORINFO_FIELD_HANDLE fldHnd = rhsFldSeq->GetTail()->GetFieldHandle();
rhsStructHnd = info.compCompHnd->getFieldClass(fldHnd);
}

if (lhsFldSeq == nullptr)
{
lhsStructHnd = lhsVarDsc->GetStructHnd();
}
else
{
CORINFO_FIELD_HANDLE fldHnd = lhsFldSeq->GetTail()->GetFieldHandle();
lhsStructHnd = info.compCompHnd->getFieldClass(fldHnd);
}

if (rhsStructHnd != lhsStructHnd)
{
// This can occur for nested structs or for unsafe casts, when we have IR like
// struct1 = struct2.
// Use an unique value number for the old map, as we don't have information about
// the dst field values using dst FIELD_HANDLE.
// Note that other asignments, like struct1 = IND struct(ADDR(LCL_VAR long))
// will be handled in `VNPairApplySelectorsAssign`, here we care only about
// `LCL_VAR structX = (*)LCL_VAR structY` cases.
JITDUMP(" *** Different struct handles for Dst/Src of COPYBLK\n");
isNewUniq = true;
}
}
}
isNewUniq = fgValueNumberIsStructReinterpretation(lclVarTree, rhsLclVarTree);
}

if (isNewUniq)
Expand Down Expand Up @@ -7381,6 +7338,67 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
}
}

//------------------------------------------------------------------------
// fgValueNumberIsStructReinterpretation: Checks if there is a struct reinterpretation that prevent VN propagation.
//
// Arguments:
// lhsLclVarTree - a lcl var tree on the lhs of the asg;
// rhsLclVarTree - a lcl var tree on the rhs of the asg;
//
// Return Value:
// True if the locals have different struct types and VN can't use rhs VN for lhs VN.
// False if locals have the same struct type or if this ASG is not a struct ASG.
//
bool Compiler::fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree,
GenTreeLclVarCommon* rhsLclVarTree)
{
assert(lhsLclVarTree != nullptr);
assert(rhsLclVarTree != nullptr);

if (rhsLclVarTree->TypeGet() == TYP_STRUCT)
{
if (rhsLclVarTree->TypeGet() == lhsLclVarTree->TypeGet())
{
if (lhsLclVarTree->isLclField() || rhsLclVarTree->isLclField())
{
// Jit does not have a real support for `LCL_FLD struct [FldSeq]` because it can't determinate their
// size
// when the fieldSeq is `NotAField`, but by mistake we could have
// `BLK(ADDR byref(LCL_FLD struct Fseq[]))` nowadays in out IR.
// Generate a unique VN for now, it currently won't match the other side,
// otherwise we would not have 'OBJ struct2 (ADDR(LCL_FLD struct1))` cast.
return true;
}

assert(lhsLclVarTree->OperIs(GT_LCL_VAR));
assert(rhsLclVarTree->OperIs(GT_LCL_VAR));

const LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclVarTree);
const LclVarDsc* rhsVarDsc = lvaGetDesc(rhsLclVarTree);
assert(rhsVarDsc->TypeGet() == TYP_STRUCT);
assert(lhsVarDsc->TypeGet() == TYP_STRUCT);

CORINFO_CLASS_HANDLE rhsStructHnd = rhsVarDsc->GetStructHnd();
CORINFO_CLASS_HANDLE lhsStructHnd = lhsVarDsc->GetStructHnd();

if (rhsStructHnd != lhsStructHnd)
{
// This can occur for nested structs or for unsafe casts, when we have IR like
// struct1 = struct2.
// Use an unique value number for the old map, as we don't have information about
// the dst field values using dst FIELD_HANDLE.
// Note that other asignments, like struct1 = IND struct(ADDR(LCL_VAR long))
// will be handled in `VNPairApplySelectorsAssign`, here we care only about
// `LCL_VAR structX = (*)LCL_VAR structY` cases.
JITDUMP(" *** Different struct handles for Dst/Src of COPYBLK\n");
return true;
}
}
}

return false;
}

void Compiler::fgValueNumberTree(GenTree* tree)
{
genTreeOps oper = tree->OperGet();
Expand Down Expand Up @@ -8032,7 +8050,6 @@ void Compiler::fgValueNumberTree(GenTree* tree)
rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
}

unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
ValueNumPair newLhsVNPair;
if (isEntire)
{
Expand All @@ -8050,6 +8067,8 @@ void Compiler::fgValueNumberTree(GenTree* tree)
lhs->TypeGet(), compCurBB);
}

unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);

if (lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
{
lvaTable[lclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair;
Expand Down