This issue was a GC hole that was caused by bad IR produced by
recursivelty promoting a struct with the following form:
```
struct S
{
struct T
{
object o;
};
T t;
}
```
In this case, the recursive promotion logic created a single lclVar to
represent `S.t` and retyped it using the type of `T.o`, but did not
rewrite IR that treated the single lclVar as a struct (e.g. instances of
`lclFld/st.lclFld Vx` where `Vx` referred to the lclVar that represented
`S.t` were not rewritten an `lclVar/st.lclVar Vx`). This IR in
turn confused the incremental liveness used during code generation,
which caused the stack slot holding `o`'s value to die too early.
This change fixes codegen's incremental liveness to handle this case.
genConsumeAddress(tree->AsIndir()->Addr());
}
#ifdef _TARGET_XARCH_
- else if (tree->OperGet() == GT_LCL_VAR)
+ else if (tree->OperIsLocalRead())
{
// A contained lcl var must be living on stack and marked as reg optional, or not be a
// register candidate.
GenTreePtr op1 = treeNode->gtGetOp1();
genConsumeRegs(op1);
emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1);
+
+ genUpdateLife(treeNode);
}
break;