https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84780
--- Comment #4 from ktkachov at gcc dot gnu.org ---
A carry-setting instruction gets deleted. Among the disassembly the non-failing
assembly has this:
cmp x13, 0
asr w0, w0, w4
cset w4, ne
sxtw x0, w0
adrp x12, d
sub w4, w7, w4
sxtw x9, w7
add w4, w4, w6
asr x6, x0, 63
cmn x4, x2 // sets the carry flag
asr x1, x9, 63
cinc x3, x3, cs // Uses the carry flag
The bad disassembly has this:
cmp x4, 0
adrp x13, d
cset w4, ne
asr x7, x0, 63
sxtw x6, w8
cinc x1, x3, cs // use of carry flag, but the setter was eliminated
Combine ends up eliminating the carry-setting instruction:
(insn 55 52 56 2 (set (reg:CC_C 66 cc)
(ne:CC_C (plus:TI (zero_extend:TI (reg:DI 165))
(zero_extend:TI (reg:DI 2 x2 [ h ])))
(zero_extend:TI (plus:DI (reg:DI 165)
(reg:DI 2 x2 [ h ]))))) "bad.c":23 104
{*adddi3_compareC_cconly}
(nil))
From what I can see in the combine logs:
Trying 55 -> 70:
55:
{cc:CC_C=zero_extend(r165:DI)+zero_extend(x2:DI)!=zero_extend(r165:DI+x2:DI);r167:DI=r165:DI+x2:DI;}
REG_DEAD x2:DI
REG_DEAD r165:DI
70: r178:DI=r167:DI
REG_DEAD r167:DI
After a few failed PARALLEL formation it succeeds twice with:
Successfully matched this instruction:
(set (reg:CC_C 66 cc)
(ne:CC_C (plus:TI (zero_extend:TI (reg:DI 165))
(zero_extend:TI (reg:DI 2 x2 [ h ])))
(zero_extend:TI (plus:DI (reg:DI 165)
(reg:DI 2 x2 [ h ])))))
Successfully matched this instruction:
(set (reg:DI 178)
(plus:DI (reg:DI 165)
(reg:DI 2 x2 [ h ])))
allowing combination of insns 55 and 70
original costs 0 + 0 = 0
replacement costs 24 + 4 = 28
deferring deletion of insn with uid = 55.
modifying insn i2 55:
cc:CC_C=zero_extend(r165:DI)+zero_extend(x2:DI)!=zero_extend(r165:DI+x2:DI)
deferring rescan insn with uid = 55.
modifying insn i3 70: r178:DI=r165:DI+x2:DI
REG_DEAD r165:DI
REG_DEAD x2:DI
deferring rescan insn with uid = 70.
so it seems like it deletes insn 55 but then also modifies it?