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