Instructions with this format should never produce a GC reference, and
should kill any GC reference that was in the destination register.
This situation can arise with IR such as the following:
t1347 = &lclFld byref V00 loc0 [+8] Fseq[m_b] REG ecx
/--* t1347 byref
* st.lclVar int V271 tmp270 d:3 ecx REG ecx RV
t8942 = lclVar int V271 tmp270 ecx REG ecx RV
t8937 = const int 0 reuse reg val REG eax RV
/--* t8942 int
+--* t8937 int
t8943 = * gt_long long REG NA
t8939 = const int 4 REG NA
/--* t8943 long
+--* t8939 int
t8944 = * <<Hi int REG eax
t6676 = lclVar int V271 tmp270 u:3 ecx (last use) REG ecx RV $6b6
t8940 = const int 4 REG NA
/--* t6676 int
+--* t8940 int
t8941 = * << int REG ecx
For this IR, we generate the following x86 assembly:
IN04b3: 001218 8D4DE8 lea ecx, bword ptr [ebp-18H]
IN04b4: 00121B
0FA4C804 shld eax, ecx, 4
IN04b5: 00121F C1E104 shl ecx, 4
Where the `lea` corresponds to the `&lclFld` node, the `shld`
corresponds to the `<<Hi` node, and the `shl` corresponds to the `<<`
node. Because the `&lclFld` node is typed as a byref, the `lea`
instruction marks `ecx` as a byref register. Normally, the `st.lclVar`
would update the gc-ness of its destination, but in this case it is
elided because its source register matches its destination register. As
a result, `ecx` is still considered to contain a byref value at the
point of the `shl`.
It is very likely that it is also a bug that the elided `st.lclVar` does
not udpate the gc-ness of its destination, though it remains to be seen
whether or not this can cause SBCG in other cases.
The typing of the `&lclFld` node as a byref is also questionable, as
these nodes are guaranteed to point to the stack (and are therefore
never heap references). This typing is conservatively correct, however,
and AFAICT only causes us to over-report registers or stack slots in the
generated GC info.
Commit migrated from https://github.com/dotnet/coreclr/commit/
2d82e2740d666ef9c4e661ad5798b387ced75b13