https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69305
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Looks like aarch64 backend bug to me. unsigned __int128 f1 (unsigned __int128 x, unsigned __int128 y) { return x + y; } unsigned __int128 f2 (unsigned __int128 x, unsigned __int128 y) { return x - y; } unsigned __int128 f3 (unsigned __int128 x, unsigned long long y) { return x + y; } unsigned __int128 f4 (unsigned __int128 x, unsigned long long y) { return x - y; } unsigned __int128 f5 (unsigned __int128 x, unsigned long long y) { return x + (unsigned long long) -y; } This case is f5 from the above, where the value should be negated first in DImode and then added to the TImode value. But combiner sees (insn 7 4 10 2 (set (reg:DI 79) (neg:DI (reg/v:DI 77 [ y ]))) pr69305-1.c:5 331 {negdi2} (expr_list:REG_DEAD (reg/v:DI 77 [ y ]) (nil))) (insn 10 7 11 2 (parallel [ (set (reg:CC_NZ 66 cc) (compare:CC_NZ (plus:DI (reg:DI 79) (reg:DI 85 [ x ])) (const_int 0 [0]))) (set (reg:DI 81) (plus:DI (reg:DI 79) (reg:DI 85 [ x ]))) ]) pr69305-1.c:5 100 {adddi3_compare0} (expr_list:REG_DEAD (reg:DI 85 [ x ]) (expr_list:REG_DEAD (reg:DI 79) (nil)))) (insn 11 10 25 2 (set (reg:DI 82) (plus:DI (geu:DI (reg:CC 66 cc) (const_int 0 [0])) (reg:DI 86 [ x+8 ]))) pr69305-1.c:5 452 {*csinc2di_insn} (expr_list:REG_DEAD (reg:DI 86 [ x+8 ]) (expr_list:REG_DEAD (reg:CC 66 cc) (nil)))) and attempts to merge insn 7 into insn 10 by having a minus in there instead, and that pattern is then recognized as subdi3_compare0. But probably csinc2di_insn actually relies on the preceeding insn being result of adddi3_compare instead of subdi3_compare. Seems on arm32 or x86_64 we have a DImode (arm32) or TImode pattern for the addition that is only lowered later on, so this is something that really can't happen on those targets.