Skip to content

Commit be7030f

Browse files
Transform STRUCT-typed uses of primitives in local morph (#78131)
* Add fwd-sub workaround * Fold STRUCT-based access to primitives in local morph * Solve a tiny regression * Adapt args morhing * Adapt block morphing * Adapt return morphing * Delete dead code
1 parent 62bb4f2 commit be7030f

File tree

6 files changed

+173
-429
lines changed

6 files changed

+173
-429
lines changed

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5712,7 +5712,7 @@ class Compiler
57125712
GenTree* fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode);
57135713
#endif // TARGET_X86
57145714
GenTree* fgMorphExpandImplicitByRefArg(GenTreeLclVarCommon* lclNode);
5715-
GenTree* fgMorphLocalVar(GenTree* tree, bool forceRemorph);
5715+
GenTree* fgMorphLocalVar(GenTree* tree);
57165716

57175717
public:
57185718
bool fgAddrCouldBeNull(GenTree* addr);

src/coreclr/jit/flowgraph.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ bool Compiler::fgAddrCouldBeNull(GenTree* addr)
944944
case GT_CNS_STR:
945945
case GT_ADDR:
946946
case GT_FIELD_ADDR:
947+
case GT_LCL_VAR_ADDR:
948+
case GT_LCL_FLD_ADDR:
947949
case GT_CLS_VAR_ADDR:
948950
// A GT_ADDR node, by itself, never requires null checking. The expression whose address is being
949951
// taken is either a local or static variable, whose address is necessarily non-null, or else it is

src/coreclr/jit/forwardsub.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,15 @@ bool Compiler::fgForwardSubStatement(Statement* stmt)
641641
return false;
642642
}
643643

644+
// A "CanBeReplacedWithItsField" SDSU can serve as a sort of "BITCAST<primitive>(struct)"
645+
// device, forwarding it risks forcing things to memory.
646+
//
647+
if (fwdSubNode->IsCall() && varDsc->CanBeReplacedWithItsField(this))
648+
{
649+
JITDUMP(" fwd sub local is 'CanBeReplacedWithItsField'\n");
650+
return false;
651+
}
652+
644653
// There are implicit assumptions downstream on where/how multi-reg ops
645654
// can appear.
646655
//

src/coreclr/jit/lclmorph.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -992,7 +992,13 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
992992
indir->AsLclFld()->SetLayout(indirLayout);
993993
lclNode = indir->AsLclVarCommon();
994994

995-
m_compiler->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::LocalField));
995+
if (!indir->TypeIs(TYP_STRUCT))
996+
{
997+
// The general invariant in the compiler is that whoever creates a LCL_FLD node after local morph
998+
// must mark the associated local DNER. We break this invariant here, for STRUCT fields, to allow
999+
// global morph to transform these into enregisterable LCL_VARs, applying DNER otherwise.
1000+
m_compiler->lvaSetVarDoNotEnregister(val.LclNum() DEBUGARG(DoNotEnregisterReason::LocalField));
1001+
}
9961002
break;
9971003

9981004
default:
@@ -1097,14 +1103,6 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
10971103
return IndirTransform::LclFld;
10981104
}
10991105

1100-
if (varDsc->TypeGet() != TYP_STRUCT)
1101-
{
1102-
// TODO-ADDR: STRUCT uses of primitives require more work: "fgMorphOneAsgBlockOp"
1103-
// and init block morphing need to be updated to recognize them. Alternatively,
1104-
// we could consider moving some of their functionality here.
1105-
return IndirTransform::None;
1106-
}
1107-
11081106
ClassLayout* indirLayout = nullptr;
11091107

11101108
if (indir->OperIs(GT_FIELD))
@@ -1122,8 +1120,10 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
11221120

11231121
*pStructLayout = indirLayout;
11241122

1125-
// We're only processing TYP_STRUCT uses and variables now.
1126-
assert(indir->TypeIs(TYP_STRUCT) && (varDsc->GetLayout() != nullptr));
1123+
if (varDsc->TypeGet() != TYP_STRUCT)
1124+
{
1125+
return IndirTransform::LclFld;
1126+
}
11271127

11281128
if ((val.Offset() == 0) && ClassLayout::AreCompatible(indirLayout, varDsc->GetLayout()))
11291129
{

0 commit comments

Comments
 (0)