https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82940
--- Comment #3 from Segher Boessenkool <segher at gcc dot gnu.org> --- In combine, we start with insn_cost 4 for 10: r137:SI=r136:QI#0&0x7f REG_DEAD r136:QI insn_cost 4 for 13: r140:SI=r132:SI&0xffffffffffffff80 REG_DEAD r132:SI insn_cost 4 for 16: r143:SI=r137:SI|r140:SI REG_DEAD r140:SI REG_DEAD r137:SI insn_cost 4 for 17: r144:SI=zero_extend(r143:SI#3) REG_DEAD r143:SI It then tries: Trying 13, 10 -> 16: 13: r140:SI=r132:SI&0xffffffffffffff80 REG_DEAD r132:SI 10: r137:SI=r136:QI#0&0x7f REG_DEAD r136:QI 16: r143:SI=r137:SI|r140:SI REG_DEAD r140:SI REG_DEAD r137:SI Failed to match this instruction: (set (reg:SI 143) (ior:SI (and:SI (reg/v:SI 132 [ v+-3 ]) (const_int 128 [0x80])) (and:SI (subreg:SI (reg:QI 136 [ *_2 ]) 0) (const_int 127 [0x7f])))) which fails because that isn't an existing instruction (the -0x80 was optimised to 0x80). Then 16->17 is done (throwing away the useless extend), and of course 10,13->17 won't work after that. So it's a case of the general problem that combine using known values of registers often hurts instead of helps.