[Bug target/60486] [4.8/4.9 Regression] [avr] superfluous or missing comparision after addition or subtraction

2014-03-13 Thread gjl at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60486

--- Comment #6 from Georg-Johann Lay gjl at gcc dot gnu.org ---
Author: gjl
Date: Thu Mar 13 09:16:53 2014
New Revision: 208532

URL: http://gcc.gnu.org/viewcvs?rev=208532root=gccview=rev
Log:
PR target/60486
* config/avr/avr.c (avr_out_plus): Swap cc_plus and cc_minus in
calls of avr_out_plus_1.


Modified:
trunk/gcc/ChangeLog
trunk/gcc/config/avr/avr.c


[Bug target/60486] [4.8/4.9 Regression] [avr] superfluous or missing comparision after addition or subtraction

2014-03-13 Thread gjl at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60486

--- Comment #7 from Georg-Johann Lay gjl at gcc dot gnu.org ---
Author: gjl
Date: Thu Mar 13 09:35:42 2014
New Revision: 208534

URL: http://gcc.gnu.org/viewcvs?rev=208534root=gccview=rev
Log:
Backport from 2014-03-13 trunk r208532.

PR target/60486
* config/avr/avr.c (avr_out_plus): Swap cc_plus and cc_minus in
calls of avr_out_plus_1.


Modified:
branches/gcc-4_8-branch/gcc/ChangeLog
branches/gcc-4_8-branch/gcc/config/avr/avr.c


[Bug target/60486] [4.8/4.9 Regression] [avr] superfluous or missing comparision after addition or subtraction

2014-03-11 Thread gjl at gcc dot gnu.org
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]