@@ -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