8/16bit oddities on avr-gcc

Andrew Haley aph@redhat.com
Fri Mar 2 12:56:00 GMT 2007


Michael Kukat writes:
 > 
 > i'm programming a lot of AVR firmware since a while, first in pure
 > assembler, as gcc 3.x didn't produce code i liked very much. But the
 > 4.1.1 i'm currently using produces quite good code if you sometimes
 > try around to get the best results (as in "i would write nearly the
 > same in assembler").
 > 
 > But now, i found one strange thing where i currently can't find a
 > workaround i really like. It's about a quite simple loop here:
 > 
 > This is my perftest.c file:
 > #include <avr/io.h>
 > #include < inttypes.h>
 > 
 > volatile uint8_t xx;
 > 
 > void test() {
 >         uint8_t ctr;
 > 
 >         ctr = 0;
 >         do {
 >                 xx = ctr;
 >         } while(++ctr < 64);
 > }
 > 
 > quite simple. If i compile this like the following:
 > 
 > avr-gcc -mmcu=atmega644 -O3 -S -o - perftest.c
 > 
 > i see that ctr is used in 16bit:
 > 
 >         ldi r24,lo8(0)
 >         ldi r25,hi8(0)
 > .L2:
 >         sts xx,r24
 >         adiw r24,1
 >         cpi r24,64
 >         cpc r25,__zero_reg__
 >         brne .L2
 > /* epilogue: frame size=0 */
 >         ret
 > 
 > Now i tried around a bit and see the following situation:
 > 
 > if i replace the "xx = ctr" by an __asm__("nop"), the counter is 8
 > bit, as it should be. If i use ctr = 64 before the loop and do
 > while(--ctr);, the counter also is 8 bit (with xx = ctr in the loop).
 > All experiments trying < (uint8_t) 64 and so didn't work, also !=
 > instead of < doesn't work, i can't find a "nice" way to force the
 > counter being 8 bit when using the value within the loop. I need that
 > loop in this way, that's why i don't use --ctr.
 > 
 > But i found one operation, which does the same like (++ctr < 64) in my
 > case, but doesn't create the counter in 16bit but in 8bit, as desired:
 > (++ctr % 64). With this, the result is exactly what i want:
 > 
 >          ldi r24,lo8(0)
 > .L2:
 >         sts xx,r24
 >         subi r24,lo8(-(1))
 >         cpi r24,lo8(64)
 >         brne .L2
 > /* epilogue: frame size=0 */
 >         ret
 > 
 > Is there any reason for this strange 16bit behaviour? To me, it looks
 > like the assignemt xx = ctr seems to trigger some signed flags for the
 > comparison, because ((++ctr & 0x7f) < 64) also produces the desired
 > 8bit version. Might be okay in this loop, but isn't so fine if i need,
 > say, 200 as the counter top value.
 > 
 > What do you think about this?

This is strange, and might be a missed optimization bug.  I can't see
any explanation for the behaviour you see here.

What does the output of -fdump-tree-optimized look like?

Andrew.



More information about the Gcc-help mailing list