https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84169

ktkachov at gcc dot gnu.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |segher at gcc dot gnu.org

--- Comment #2 from ktkachov at gcc dot gnu.org ---
I think combine is at fault here. The faulty assembly is:
foo:
        ldrb    w0, [sp, 16]
        neg     x0, x0, lsl 4
        csetm   x3, ne
<snip>

The csetm is supposed to set the top 64 bits of the TImode value (in x3) to
ones, based on the CC content, but the CC-setting instruction has disappeared.
The correct sequence (by hacking the assembly output and checking that it
passes) would be:
        ldrb    w0, [sp, 16]
        negs     x0, x0, lsl 4 // NEG sets the condition code as well.
        csetm   x3, ne

There's a few complex combinations going on, but before combine we have (some
RTL edited to tone down verbosity):

(insn 14 12 17 2 (set (reg:DI 87)
        (lshiftrt:DI (reg:DI 103)
            (const_int 60 [0x3c]))) "wrong.c":9 676
{*aarch64_lshr_sisd_or_int_di3}
(insn 19 17 20 2 (parallel [
            (set (reg:CC 66 cc)
                (compare:CC (reg:DI 85)
                    (reg:DI 105)))
            (set (reg:DI 90)
                (minus:DI (reg:DI 85)
                    (reg:DI 105)))
        ]) "wrong.c":9 270 {subdi3_compare1}

(insn 20 19 23 2 (set (reg:DI 91)
        (minus:DI (minus:DI (reg:DI 85)
                (reg:DI 87))
            (ltu:DI (reg:CC 66 cc)
                (const_int 0 [0])))) "wrong.c":9 327 {*subdi3_carryin}

where insn 19 sets the CC and insn 20 uses it. After combine we have:
(insn 14 12 17 2 (set (reg:DI 87)
        (lshiftrt:DI (reg:DI 103)
            (const_int 60 [0x3c]))) "wrong.c":9 676
{*aarch64_lshr_sisd_or_int_di3}
(note 19 17 20 2 NOTE_INSN_DELETED)
(insn 20 19 23 2 (set (reg:DI 91)
        (neg:DI (ne:DI (reg:CC 66 cc)
                (const_int 0 [0])))) "wrong.c":9 441 {cstoredi_neg}

with insn 20 still using the CC but the CC setting instruction being deleted.
There's a number of exciting things going on in combine so my analysis may not
be entirely accurate, but I see things like:
Trying 14 -> 20:
   14: r87:DI=r103:DI 0>>0x3c
   20: r91:DI=r85:DI-r87:DI-ltu(cc:CC,0)
      REG_DEAD r87:DI
      REG_DEAD r85:DI
      REG_DEAD cc:CC
      REG_EQUAL -r87:DI-ltu(cc:CC,0)
Successfully matched this instruction:
(set (reg:DI 91)
    (neg:DI (ltu:DI (reg:CC 66 cc)
            (const_int 0 [0]))))

and

Trying 19 -> 26:
   19: cc:CC=cmp(r103:DI,0)
      REG_DEAD r103:DI
   26:
{cc:CC_C=zero_extend(r90:DI)+zero_extend(r111:DI)!=zero_extend(r90:DI+r111:DI);r95:DI=r90:DI+r111:DI;}
      REG_DEAD r111:DI
      REG_DEAD r90:DI
Successfully matched this instruction:
(parallel [
        (set (reg:CC_C 66 cc)
            (ne:CC_C (plus:TI (zero_extend:TI (reg:DI 90))
                    (zero_extend:TI (reg:DI 111 [ b ])))
                (zero_extend:TI (plus:DI (reg:DI 90)
                        (reg:DI 111 [ b ])))))
        (set (reg:DI 95)
            (plus:DI (reg:DI 90)
                (reg:DI 111 [ b ])))
    ])
deferring deletion of insn with uid = 19.

So insn 19 ends up being combined into a subsequent instruction and ends up
being deleted even though insn 20 depends on it's CC-setting effects

Reply via email to