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 ; 6addsi3/2[length = 3]
adc r26,__zero_reg__
adc r27,__zero_reg__
brne .L5 ; 8branch[length = 1]
sts v,__zero_reg__ ; 10movqi_insn/3[length = 2]
.L5:
rjmp foo ; 14call_insn/4[length = 1]