Skip to content

Commit

Permalink
JIT: Handle retbuf definitions precise in physical promotion's liveness
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobbotsch committed Jul 8, 2024
1 parent e336326 commit 7546409
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
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
81 changes: 40 additions & 41 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 @@ -219,9 +211,10 @@ void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, Bit
}
else
{
unsigned offs = lcl->GetLclOffs();
unsigned size = lcl->GetLayout(m_compiler)->GetSize();
size_t index = Promotion::BinarySearch<Replacement, &Replacement::Offset>(reps, offs);
unsigned offs = lcl->GetLclOffs();
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 +257,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 +452,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 +462,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 +484,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 +501,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 +533,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 +597,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

0 comments on commit 7546409

Please sign in to comment.