http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58517
Oleg Endo <olegendo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2013-10-05 Component|target |rtl-optimization Summary|[SH] wrong code with subc |icvt (after combine) puts |and movsicc |ccreg clobbering insn |(-mpretend-cmove) after ce2 |between ccset insn and cc | |use Ever confirmed|0 |1 --- Comment #1 from Oleg Endo <olegendo at gcc dot gnu.org> --- This seems to be a bug in ifcvt.c Reduced test cases: int test_subc (int q, int read, int end) { return q < read ? (read - q - 1) : (end - q); } int test_addc (int q, int read, int end) { return q < read ? (read + q + 1) : (end + q); } compiled with -O2 -m4 -mpretend-cmove: _test_subc: sett mov r5,r0 sub r4,r6 subc r4,r0 ! 36 *subc bf 0f ! 34 *movsicc_t_true/1 mov r6,r0 0: rts nop _test_addc: sett mov r4,r0 add r4,r6 addc r5,r0 ! 34 *addc bf 0f ! 32 *movsicc_t_true/1 mov r6,r0 0: rts nop In both above cases the comparison 'q < read' is eliminated, because ifcvt moves the T_REG clobbering subc/addc insn between the 'q < read' comparison (sets T_REG) and the conditional branch (uses T_REG).