@@ -1970,42 +1970,19 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
1970
1970
{
1971
1971
GenTreeIndir* const store = addrUse.User ()->AsIndir ();
1972
1972
1973
- // If this is a zero init of an explicit zero init gc local
1974
- // that has at least one other reference, we will keep the zero init.
1975
- //
1976
- const LclVarDsc& varDsc = lvaTable[node->AsLclVarCommon ()->GetLclNum ()];
1977
- const bool isExplicitInitLocal = varDsc.lvHasExplicitInit ;
1978
- const bool isReferencedLocal = varDsc.lvRefCnt () > 1 ;
1979
- const bool isZeroInit = store->OperIsInitBlkOp ();
1980
- const bool isGCInit = varDsc.HasGCPtr ();
1981
-
1982
- if (isExplicitInitLocal && isReferencedLocal && isZeroInit && isGCInit)
1973
+ if (fgTryRemoveDeadStoreLIR (store, node->AsLclVarCommon (), block))
1983
1974
{
1984
- // Yes, we'd better keep it around.
1985
- //
1986
- JITDUMP (" Keeping dead indirect store -- explicit zero init of gc type\n " );
1987
- DISPNODE (store);
1988
- }
1989
- else
1990
- {
1991
- // Remove the store. DCE will iteratively clean up any ununsed operands.
1992
- //
1993
- JITDUMP (" Removing dead indirect store:\n " );
1994
- DISPNODE (store);
1995
-
1996
- assert (store->Addr () == node);
1997
- blockRange.Delete (this , block, node);
1975
+ JITDUMP (" Removing dead LclVar address:\n " );
1976
+ DISPNODE (node);
1977
+ blockRange.Remove (node);
1998
1978
1999
- GenTree* data =
2000
- store->OperIs (GT_STOREIND) ? store->AsStoreInd ()->Data () : store->AsBlk ()->Data ();
1979
+ GenTree* data = store->AsIndir ()->Data ();
2001
1980
data->SetUnusedValue ();
2002
1981
2003
1982
if (data->isIndir ())
2004
1983
{
2005
1984
Lowering::TransformUnusedIndirection (data->AsIndir (), this , block);
2006
1985
}
2007
-
2008
- fgRemoveDeadStoreLIR (store, block);
2009
1986
}
2010
1987
}
2011
1988
}
@@ -2027,17 +2004,10 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
2027
2004
isDeadStore = fgComputeLifeUntrackedLocal (life, keepAliveVars, varDsc, lclVarNode);
2028
2005
}
2029
2006
2030
- if (isDeadStore)
2007
+ if (isDeadStore && fgTryRemoveDeadStoreLIR (node, lclVarNode, block) )
2031
2008
{
2032
- JITDUMP (" Removing dead store:\n " );
2033
- DISPNODE (lclVarNode);
2034
-
2035
- // Remove the store. DCE will iteratively clean up any ununsed operands.
2036
- lclVarNode->gtOp1 ->SetUnusedValue ();
2037
-
2038
- fgRemoveDeadStoreLIR (node, block);
2009
+ lclVarNode->Data ()->SetUnusedValue ();
2039
2010
}
2040
-
2041
2011
break ;
2042
2012
}
2043
2013
@@ -2185,17 +2155,41 @@ bool Compiler::fgTryRemoveNonLocal(GenTree* node, LIR::Range* blockRange)
2185
2155
}
2186
2156
2187
2157
// ---------------------------------------------------------------------
2188
- // fgRemoveDeadStoreLIR - remove a dead store from LIR
2158
+ // fgTryRemoveDeadStoreLIR - try to remove a dead store from LIR
2189
2159
//
2190
- // store - A store tree
2191
- // block - Block that the store is part of
2160
+ // Arguments:
2161
+ // store - A store tree
2162
+ // lclNode - The node representing the local being stored to
2163
+ // block - Block that the store is part of
2164
+ //
2165
+ // Return Value:
2166
+ // Whether the store was successfully removed from "block"'s range.
2192
2167
//
2193
- void Compiler::fgRemoveDeadStoreLIR (GenTree* store, BasicBlock* block)
2168
+ bool Compiler::fgTryRemoveDeadStoreLIR (GenTree* store, GenTreeLclVarCommon* lclNode , BasicBlock* block)
2194
2169
{
2195
- LIR::Range& blockRange = LIR::AsRange (block);
2196
- blockRange.Remove (store);
2197
2170
assert (!opts.MinOpts ());
2171
+
2172
+ // We cannot remove stores to (tracked) TYP_STRUCT locals with GC pointers marked as "explicit init",
2173
+ // as said locals will be reported to the GC untracked, and deleting the explicit initializer risks
2174
+ // exposing uninitialized references.
2175
+ if ((lclNode->gtFlags & GTF_VAR_USEASG) == 0 )
2176
+ {
2177
+ LclVarDsc* varDsc = lvaGetDesc (lclNode);
2178
+ if (varDsc->lvHasExplicitInit && (varDsc->TypeGet () == TYP_STRUCT) && varDsc->HasGCPtr () &&
2179
+ (varDsc->lvRefCnt () > 1 ))
2180
+ {
2181
+ JITDUMP (" Not removing a potential explicit init [%06u] of V%02u\n " , dspTreeID (store), lclNode->GetLclNum ());
2182
+ return false ;
2183
+ }
2184
+ }
2185
+
2186
+ JITDUMP (" Removing dead %s:\n " , store->OperIsIndir () ? " indirect store" : " local store" );
2187
+ DISPNODE (store);
2188
+
2189
+ LIR::AsRange (block).Remove (store);
2198
2190
fgStmtRemoved = true ;
2191
+
2192
+ return true ;
2199
2193
}
2200
2194
2201
2195
// ---------------------------------------------------------------------
0 commit comments