Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Handle retbuf definitions precisely in physical promotion's liveness #104551

Merged
Merged
Show file tree
Hide file tree
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
17 changes: 9 additions & 8 deletions src/coreclr/jit/promotion.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,15 @@ class PromotionLiveness
StructDeaths GetDeathsForStructLocal(GenTreeLclVarCommon* use);

private:
void MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, BitVec& defSet);
void MarkIndex(unsigned index, bool isUse, bool isDef, BitVec& useSet, BitVec& defSet);
void ComputeUseDefSets();
void InterBlockLiveness();
bool PerBlockLiveness(BasicBlock* block);
void AddHandlerLiveVars(BasicBlock* block, BitVec& ehLiveVars);
void FillInLiveness();
void FillInLiveness(BitVec& life, BitVec volatileVars, GenTreeLclVarCommon* lcl);
void MarkUseDef(Statement* stmt, GenTreeLclVarCommon* lcl, BitVec& useSet, BitVec& defSet);
unsigned GetSizeOfStructLocal(Statement* stmt, GenTreeLclVarCommon* lcl);
void MarkIndex(unsigned index, bool isUse, bool isDef, BitVec& useSet, BitVec& defSet);
void ComputeUseDefSets();
void InterBlockLiveness();
bool PerBlockLiveness(BasicBlock* block);
void AddHandlerLiveVars(BasicBlock* block, BitVec& ehLiveVars);
void FillInLiveness();
void FillInLiveness(BitVec& life, BitVec volatileVars, Statement* stmt, GenTreeLclVarCommon* lcl);
#ifdef DEBUG
void DumpVarSet(BitVec set, BitVec allVars);
#endif
Expand Down
76 changes: 37 additions & 39 deletions src/coreclr/jit/promotionliveness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void PromotionLiveness::ComputeUseDefSets()
{
for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList())
{
MarkUseDef(lcl, bb.VarUse, bb.VarDef);
MarkUseDef(stmt, lcl, bb.VarUse, bb.VarDef);
}
}
else
Expand All @@ -143,7 +143,7 @@ void PromotionLiveness::ComputeUseDefSets()
// Skip liveness updates/marking for defs; they may be conditionally executed.
if ((lcl->gtFlags & GTF_VAR_DEF) == 0)
{
MarkUseDef(lcl, bb.VarUse, bb.VarDef);
MarkUseDef(stmt, lcl, bb.VarUse, bb.VarDef);
}
}
}
Expand All @@ -155,7 +155,7 @@ void PromotionLiveness::ComputeUseDefSets()
{
for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList())
{
MarkUseDef(lcl, bb.VarUse, bb.VarDef);
MarkUseDef(stmt, lcl, bb.VarUse, bb.VarDef);
}
}
}
Expand All @@ -179,11 +179,12 @@ void PromotionLiveness::ComputeUseDefSets()
// Mark use/def information for a single appearence of a local.
//
// Parameters:
// stmt - Statement containing the local
// lcl - The local node
// useSet - The use set to mark in.
// defSet - The def set to mark in.
//
void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, BitVec& defSet)
void PromotionLiveness::MarkUseDef(Statement* stmt, GenTreeLclVarCommon* lcl, BitVec& useSet, BitVec& defSet)
{
AggregateInfo* agg = m_aggregates.Lookup(lcl->GetLclNum());
if (agg == nullptr)
Expand All @@ -198,17 +199,8 @@ void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, Bit
unsigned baseIndex = m_structLclToTrackedIndex[lcl->GetLclNum()];
var_types accessType = lcl->TypeGet();

if (accessType == TYP_STRUCT)
if ((accessType == TYP_STRUCT) || lcl->OperIs(GT_LCL_ADDR))
{
if (lcl->OperIs(GT_LCL_ADDR))
{
// For LCL_ADDR this is a retbuf and we expect it to be a def. We
// don't know the exact size here so we cannot mark anything as
// being fully defined, thus we can just return.
assert(isDef);
return;
}

if (lcl->OperIsScalarLocal())
{
// Mark remainder and all fields.
Expand All @@ -220,7 +212,7 @@ void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, Bit
else
{
unsigned offs = lcl->GetLclOffs();
unsigned size = lcl->GetLayout(m_compiler)->GetSize();
unsigned size = GetSizeOfStructLocal(stmt, lcl);
size_t index = Promotion::BinarySearch<Replacement, &Replacement::Offset>(reps, offs);

if ((ssize_t)index < 0)
Expand Down Expand Up @@ -264,6 +256,30 @@ void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, Bit
}
}

//------------------------------------------------------------------------
// GetSizeOfStructLocal:
// Get the size of a struct local (either a TYP_STRUCT typed local, or a
// GT_LCL_ADDR retbuf definition).
//
// Parameters:
// stmt - Statement containing the local
// lcl - The local node
//
unsigned PromotionLiveness::GetSizeOfStructLocal(Statement* stmt, GenTreeLclVarCommon* lcl)
{
if (lcl->OperIs(GT_LCL_ADDR))
{
// Retbuf definition. Find the definition size from the
// containing call.
Compiler::FindLinkData data = m_compiler->gtFindLink(stmt, lcl);
assert((data.parent != nullptr) && data.parent->IsCall() &&
(m_compiler->gtCallGetDefinedRetBufLclAddr(data.parent->AsCall()) == lcl));
return m_compiler->typGetObjLayout(data.parent->AsCall()->gtRetClsHnd)->GetSize();
}

return lcl->GetLayout(m_compiler)->GetSize();
}

//------------------------------------------------------------------------
// MarkIndex:
// Mark specific bits in use/def bit vectors depending on whether this is a use def.
Expand Down Expand Up @@ -435,7 +451,7 @@ void PromotionLiveness::FillInLiveness()
{
for (GenTree* cur = stmt->GetTreeListEnd(); cur != nullptr; cur = cur->gtPrev)
{
FillInLiveness(life, volatileVars, cur->AsLclVarCommon());
FillInLiveness(life, volatileVars, stmt, cur->AsLclVarCommon());
}
}
else
Expand All @@ -445,7 +461,7 @@ void PromotionLiveness::FillInLiveness()
// Skip liveness updates/marking for defs; they may be conditionally executed.
if ((cur->gtFlags & GTF_VAR_DEF) == 0)
{
FillInLiveness(life, volatileVars, cur->AsLclVarCommon());
FillInLiveness(life, volatileVars, stmt, cur->AsLclVarCommon());
}
}
}
Expand All @@ -467,9 +483,10 @@ void PromotionLiveness::FillInLiveness()
// Parameters:
// life - The current life set. Will be read and updated depending on 'lcl'.
// volatileVars - Bit vector of variables that are live always.
// stmt - Statement containing the local
// lcl - The IR node to process liveness for and to mark with liveness information.
//
void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTreeLclVarCommon* lcl)
void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, Statement* stmt, GenTreeLclVarCommon* lcl)
{
AggregateInfo* agg = m_aggregates.Lookup(lcl->GetLclNum());
if (agg == nullptr)
Expand All @@ -483,7 +500,7 @@ void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTre
unsigned baseIndex = m_structLclToTrackedIndex[lcl->GetLclNum()];
var_types accessType = lcl->TypeGet();

if (accessType == TYP_STRUCT)
if ((accessType == TYP_STRUCT) || lcl->OperIs(GT_LCL_ADDR))
{
// We need an external bit set to represent dying fields/remainder on a struct use.
BitVecTraits aggTraits(1 + (unsigned)agg->Replacements.size(), m_compiler);
Expand Down Expand Up @@ -515,7 +532,7 @@ void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTre
else
{
unsigned offs = lcl->GetLclOffs();
unsigned size = lcl->GetLayout(m_compiler)->GetSize();
unsigned size = GetSizeOfStructLocal(stmt, lcl);
size_t index = Promotion::BinarySearch<Replacement, &Replacement::Offset>(agg->Replacements, offs);

if ((ssize_t)index < 0)
Expand Down Expand Up @@ -579,25 +596,6 @@ void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTre
}
else
{
if (lcl->OperIs(GT_LCL_ADDR))
{
// Retbuf -- these are definitions but we do not know of how much.
// We never treat them as killing anything, but we do store liveness information for them.
BitVecTraits aggTraits(1 + (unsigned)agg->Replacements.size(), m_compiler);
BitVec aggDeaths(BitVecOps::MakeEmpty(&aggTraits));
// Copy preexisting liveness information.
for (size_t i = 0; i <= agg->Replacements.size(); i++)
{
unsigned varIndex = baseIndex + (unsigned)i;
if (!BitVecOps::IsMember(m_bvTraits, life, varIndex))
{
BitVecOps::AddElemD(&aggTraits, aggDeaths, (unsigned)i);
}
}
m_aggDeaths.Set(lcl, aggDeaths);
return;
}

unsigned offs = lcl->GetLclOffs();
size_t index = Promotion::BinarySearch<Replacement, &Replacement::Offset>(agg->Replacements, offs);
if ((ssize_t)index < 0)
Expand Down
Loading