http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60486
Georg-Johann Lay <gjl at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |wrong-code Component|other |target Summary|[avr] missed optimization |[4.8/4.9 Regression] [avr] |on detecting zero flag set |superfluous or missing | |comparision after addition | |or subtraction Known to fail| |4.9.0 --- Comment #5 from Georg-Johann Lay <gjl at gcc dot gnu.org> --- Target issue. (In reply to Darryl Piper from comment #4) > details also posted on avrfreaks.net I am well aware of this post. But GCC reports are supposed to be self contained. So here we go: Root cause is swapped cc_plus and cc_minus in avr.c:avr_out_plus : /* Work out the shortest sequence. */ avr_out_plus_1 (op, &len_minus, MINUS, &cc_plus, code_sat, sign, out_label); avr_out_plus_1 (op, &len_plus, PLUS, &cc_minus, code_sat, sign, out_label); Thus there are also cases where wrong code is generated like the following one: extern void foo (unsigned); char v; void bar (unsigned long z) { if (++z == 0) v = 0; foo (z); } Output is missing the comparison because addsi3 does not set cc0 in a usable way when is uses the PLUS alternative: bar: movw r26,r24 ; 20 *movsi/1 [length = 2] movw r24,r22 adiw r24,1 ; 6 addsi3/2 [length = 3] adc r26,__zero_reg__ adc r27,__zero_reg__ brne .L5 ; 8 branch [length = 1] sts v,__zero_reg__ ; 10 movqi_insn/3 [length = 2] .L5: rjmp foo ; 14 call_insn/4 [length = 1]