Bug 28894 - Optimizaition on AVR target breaks code.
Summary: Optimizaition on AVR target breaks code.
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.4.6
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-08-29 22:29 UTC by Ralf Engels
Modified: 2006-08-30 20:43 UTC (History)
2 users (show)

See Also:
Host:
Target: avr
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
source code which is compiled strangely. (1.53 KB, text/x-csrc)
2006-08-29 22:30 UTC, Ralf Engels
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ralf Engels 2006-08-29 22:29:11 UTC
Attached code file is compiled.
Here is the critical passage:

inline void taskSignal(void) 
{
  unsigned char i;

  PORTB |= _BV(PB4);
  PORTB |= _BV(PB5);
  PORTB |= _BV(PB6);
  

  i=0;
  do 
    {
      i+=2;
    } 
  while( i<245 );

  i=0;
  do 
    {
      i+=3;
    } 
  while( i<245 );

  PORTB &= ~_BV(PB4);

  i=pos1;
  do 
    {
      i+=1;
    } 
  while( i<245 );


  PORTB &= ~_BV(PB5);
  PORTB &= ~_BV(PB6);
}  

When compiling without optimization I get:

  do 
    {
      i+=2;
 41e:   89 81           ldd     r24, Y+1        ; 0x01
 420:   8e 5f           subi    r24, 0xFE       ; 254
 422:   89 83           std     Y+1, r24        ; 0x01
    } 
 424:   89 81           ldd     r24, Y+1        ; 0x01
 426:   85 3f           cpi     r24, 0xF5       ; 245
 428:   08 f4           brcc    .+2             ; 0x42c <taskSignal+0x42>
 42a:   f9 cf           rjmp    .-14            ; 0x41e <taskSignal+0x34>
  while( i<245 );


But using -Os results in the following code:

 262:   80 e0           ldi     r24, 0x00       ; 0
  do 
    {
      i+=2;
 264:   8a 5f           subi    r24, 0xFA       ; 250
    } 
 266:   85 3f           cpi     r24, 0xF5       ; 245
 268:   e8 f3           brcs    .-6             ; 0x264 <taskSignal+0x8>
  while( i<245 );

Please note how the  substraction of -2 is optimized in something other.
The compiler said:
avr-gcc (GCC) 3.4.6 (Gentoo 3.4.6, ssp-3.4.5-1.0, pie-8.7.9)
Copyright (C) 2006 Free Software Foundation, Inc.

The line calling it was: 
avr-gcc -c -mmcu=attiny26 -I. -g -DF_CPU=8000000UL   -Os -Wall -Wstrict-prototypes -Wa,-adhlns=tester.lst   -MD -MP -MF .dep/tester.o.d tester.c -o tester.o
Comment 1 Ralf Engels 2006-08-29 22:30:10 UTC
Created attachment 12150 [details]
source code which is compiled strangely.
Comment 2 Andrew Pinski 2006-08-29 22:34:25 UTC
 264:   8a 5f           subi    r24, 0xFA       ; 250

That looks fine for me since it is r24 = r24 - -2.
Comment 3 Eric Weddington 2006-08-30 15:06:49 UTC
The AVR does not have an Add Immediate instruction (addi), so this is normally done using sbi with a negative number as Andrew correctly points out.

In Ralf's unoptimized output, it correctly shows a -2 (0xFE):

41e:   89 81           ldd     r24, Y+1        ; 0x01
420:   8e 5f           subi    r24, 0xFE       ; 254

The optimized output shows a -6 (0xFA)

264:   8a 5f           subi    r24, 0xFA       ; 250

Why is this? Well, the optimizer aggressively optimizes loops that do nothing, like the code is here:

i=0;
do 
  {
    i+=2;
  } 
while( i<245 );

Note that you only have 'i' declared as unsigned char.

The first FAQ entry in the avr-libc user manual talks about using the keyword 'volatile':
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_volatile

If you define 'i' as volatile unsigned char, then the optimizer will not agressively optimize your "do-nothing" loop. In fact, if you are trying to achieve a delay using a "do-nothing" loop, then you are strongly suggested to use the <util/delay.h> header that comes with avr-libc, which are "busy-wait delay loops":
<http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html>

GCC Bugmasters:
Please close this bug as invalid.

Eric Weddington
Comment 4 Andrew Pinski 2006-08-30 15:09:35 UTC
This is just unrolling/removing empty loops so invalid.
Comment 5 Ralf Engels 2006-08-30 20:43:34 UTC
Wow, 
you mean that unrolling the loop three times but not removing it is the right behaviour?

Anyway, 4.1.1 seems to do it right. It's removing the whole loop as expected.

delay.h is working.