https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54236
--- Comment #9 from Oleg Endo <olegendo at gcc dot gnu.org> --- The following function compiled with -O2 unsigned int check (unsigned int x) { return x == 0 ? 1 : x; } results in: tst r4,r4 bt/s .L7 mov #1,r0 mov r4,r0 .L7: rts nop Writing it as: unsigned int check (unsigned int x) { return x + (x == 0); } results in: tst r4,r4 mov #0,r0 rts addc r4,r0 It seems that ifcvt is trying to utilize the 'add<mode>cc' standard name pattern. If the 2nd operand of the conditional addition is a constant 1 or -1 the addcc insn can be implemented via addc or subc without a branch. If the comparison can't be done in one insn (e.g. x != 0) and requires T bit negation/inversion: unsigned int check (unsigned int x) { return x + (x != 0); } results in (non-SH2A): tst r4,r4 mov #-1,r0 negc r0,r0 rts add r4,r0 slightly better (one arith insn less): tst r4,r4 mov #-1,r0 subc r0,r4 // r4 = r4 - (-1) - T = r4 + 1 - T rts mov r4,r0 and on SH2A (already minimal): tst r4,r4 movrt r0 rts add r4,r0 subc case: unsigned int check (unsigned int x) { return x - (x != 0); } non-SH2A: tst r4,r4 mov #-1,r1 mov r4,r0 negc r1,r1 rts sub r1,r0 // r0 = r4 - (1 - T) = r4 - 1 + T SH2A: tst r4,r4 movrt r1 mov r4,r0 rts sub r1,r0 better (non-SH2A and SH2A): tst r4,r4 mov #-1,r0 rts addc r4,r0 // r0 = -1 + r4 + T = r4 - 1 + T The equivalent conditional version should result in the same (currently it isn't): unsigned int check (unsigned int x) { return x != 0 ? (x - 1) : x; } Since ifcvt is also ran after combine, combine won't get the chance to combine patterns such as: (set (reg:SI 165 [ D.1635 ]) (plus:SI (xor:SI (reg:SI 147 t) (const_int 1 [0x1])) (reg/v:SI 164 [ x ]))) which would occur after emitting a comparison, negating the result (T bit) and then adding/subtracting the T bit via addc/subc. If that happens, the combine must be done manually in the split pass as it's done with some of the other insns.