mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 10:00:57 +09:00
JIT: Handle primitive remainder stores to regularly promoted fields in physical promotion (#87217)
If the remainder of a block copy is handled as a primitive, then it is possible that the destination or source is a regularly promoted field. In this case we do not have to DNER it. Example. Before: ``` Processing block operation [000009] that involves replacements V08 (field V02.hasValue (fldOffset=0x0)) <- V16 (V00.[000..001)) (last use) Remainder: [004..008) => Remainder strategy: int at +004 Local V00 should not be enregistered because: was accessed as a local field Local V02 should not be enregistered because: was accessed as a local field New statement: STMT00003 ( 0x00D[E-] ... 0x00E ) [000090] -A--------- ▌ COMMA void [000087] DA--------- ├──▌ STORE_LCL_VAR bool V08 tmp4 [000086] ----------- │ └──▌ LCL_VAR bool V16 tmp12 (last use) [000089] UA--------- └──▌ STORE_LCL_FLD int (P) V02 loc1 [+4] ▌ bool V02.<unknown class>:hasValue (offs=0x00) -> V08 tmp4 ▌ int V02.<unknown class>:value (offs=0x04) -> V09 tmp5 [000088] ----------- └──▌ LCL_FLD int V00 arg0 [+4] ``` After: ``` Processing block operation [000009] that involves replacements V08 (field V02.hasValue (fldOffset=0x0)) <- V16 (V00.[000..001)) (last use) Remainder: [004..008) => Remainder strategy: int at +004 Local V00 should not be enregistered because: was accessed as a local field New statement: STMT00003 ( 0x00D[E-] ... 0x00E ) [000090] -A--------- ▌ COMMA void [000087] DA--------- ├──▌ STORE_LCL_VAR bool V08 tmp4 [000086] ----------- │ └──▌ LCL_VAR bool V16 tmp12 (last use) [000089] DA--------- └──▌ STORE_LCL_VAR int V09 tmp5 [000088] ----------- └──▌ LCL_FLD int V00 arg0 [+4] ```
This commit is contained in:
parent
3502f0ee4d
commit
3fded0bb77
1 changed files with 55 additions and 10 deletions
|
@ -768,13 +768,32 @@ private:
|
|||
|
||||
if (remainderStrategy.Type == RemainderStrategy::Primitive)
|
||||
{
|
||||
GenTree* src;
|
||||
GenTree* src = nullptr;
|
||||
if (m_src->OperIs(GT_LCL_VAR, GT_LCL_FLD))
|
||||
{
|
||||
GenTreeLclVarCommon* srcLcl = m_src->AsLclVarCommon();
|
||||
src = m_compiler->gtNewLclFldNode(srcLcl->GetLclNum(), remainderStrategy.PrimitiveType,
|
||||
srcLcl->GetLclOffs() + remainderStrategy.PrimitiveOffset);
|
||||
m_compiler->lvaSetVarDoNotEnregister(srcLcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField));
|
||||
|
||||
// Check if the source has a regularly promoted field at this offset.
|
||||
LclVarDsc* srcLclDsc = m_compiler->lvaGetDesc(srcLcl);
|
||||
unsigned srcLclOffs = srcLcl->GetLclOffs() + remainderStrategy.PrimitiveOffset;
|
||||
|
||||
unsigned int fieldLcl =
|
||||
srcLclDsc->lvPromoted ? m_compiler->lvaGetFieldLocal(srcLclDsc, srcLclOffs) : BAD_VAR_NUM;
|
||||
if (fieldLcl != BAD_VAR_NUM)
|
||||
{
|
||||
LclVarDsc* dsc = m_compiler->lvaGetDesc(fieldLcl);
|
||||
if (genTypeSize(dsc->lvType) == genTypeSize(remainderStrategy.PrimitiveType))
|
||||
{
|
||||
src = m_compiler->gtNewLclvNode(fieldLcl, dsc->lvType);
|
||||
}
|
||||
}
|
||||
|
||||
if (src == nullptr)
|
||||
{
|
||||
src = m_compiler->gtNewLclFldNode(srcLcl->GetLclNum(), remainderStrategy.PrimitiveType, srcLclOffs);
|
||||
m_compiler->lvaSetVarDoNotEnregister(srcLcl->GetLclNum()
|
||||
DEBUGARG(DoNotEnregisterReason::LocalField));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -783,18 +802,44 @@ private:
|
|||
PropagateIndirFlags(src, indirFlags);
|
||||
}
|
||||
|
||||
GenTree* store;
|
||||
GenTree* store = nullptr;
|
||||
if (m_store->OperIsLocalStore())
|
||||
{
|
||||
GenTreeLclVarCommon* dstLcl = m_store->AsLclVarCommon();
|
||||
store = m_compiler->gtNewStoreLclFldNode(dstLcl->GetLclNum(), remainderStrategy.PrimitiveType,
|
||||
dstLcl->GetLclOffs() + remainderStrategy.PrimitiveOffset, src);
|
||||
m_compiler->lvaSetVarDoNotEnregister(dstLcl->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField));
|
||||
|
||||
// Check if the destination has a regularly promoted field at this offset.
|
||||
LclVarDsc* dstLclDsc = m_compiler->lvaGetDesc(dstLcl);
|
||||
unsigned dstLclOffs = dstLcl->GetLclOffs() + remainderStrategy.PrimitiveOffset;
|
||||
|
||||
unsigned int fieldLcl =
|
||||
dstLclDsc->lvPromoted ? m_compiler->lvaGetFieldLocal(dstLclDsc, dstLclOffs) : BAD_VAR_NUM;
|
||||
if (fieldLcl != BAD_VAR_NUM)
|
||||
{
|
||||
LclVarDsc* dsc = m_compiler->lvaGetDesc(fieldLcl);
|
||||
if (genTypeSize(dsc->lvType) == genTypeSize(remainderStrategy.PrimitiveType))
|
||||
{
|
||||
// Since the destination is regularly promoted the
|
||||
// source must be physically promoted to get here. That
|
||||
// means we always expect to see a LCL_FLD for the
|
||||
// source here that we can retype to what matches the
|
||||
// promoted field.
|
||||
assert(src->OperIs(GT_LCL_FLD));
|
||||
src->gtType = dsc->lvType;
|
||||
|
||||
store = m_compiler->gtNewStoreLclVarNode(fieldLcl, src);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == nullptr)
|
||||
{
|
||||
store = m_compiler->gtNewStoreLclFldNode(dstLcl->GetLclNum(), src->TypeGet(), dstLclOffs, src);
|
||||
m_compiler->lvaSetVarDoNotEnregister(dstLcl->GetLclNum()
|
||||
DEBUGARG(DoNotEnregisterReason::LocalField));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
store = m_compiler->gtNewStoreIndNode(remainderStrategy.PrimitiveType,
|
||||
grabAddr(remainderStrategy.PrimitiveOffset), src);
|
||||
store = m_compiler->gtNewStoreIndNode(src->TypeGet(), grabAddr(remainderStrategy.PrimitiveOffset), src);
|
||||
PropagateIndirFlags(store, indirFlags);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue