Update GC info when emitting IF_RRW_SHF.
authorPat Gavlin <pagavlin@microsoft.com>
Mon, 17 Oct 2016 22:26:53 +0000 (15:26 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Mon, 17 Oct 2016 22:26:53 +0000 (15:26 -0700)
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

src/coreclr/src/jit/emitxarch.cpp

index 727246d..b7c2ae9 100644 (file)
@@ -10791,6 +10791,10 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
             dst += emitOutputWord(dst, code);
             dst += emitOutputByte(dst, emitGetInsSC(id));
             sz = emitSizeOfInsDsc(id);
+
+            // Update GC info.
+            assert(!id->idGCref());
+            emitGCregDeadUpd(id->idReg1(), dst);
             break;
 
         case IF_RRD_RRD: