1
0
Fork 0
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:
Jakob Botsch Nielsen 2023-06-08 22:20:44 +02:00 committed by GitHub
parent 3502f0ee4d
commit 3fded0bb77
Signed by: github
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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);
}