|
From: | Bruce D. Lightner |
Subject: | Re: [avr-gcc-list] Avr-gcc versions comparison. |
Date: | Wed, 21 Feb 2007 10:46:32 -0800 |
User-agent: | Thunderbird 1.5.0.9 (Windows/20061207) |
Dmitry K. wrote:
Hi. I have compile CVS version avr-libc (2007-02-20) with for different compilers. Dmitry, While you are "testing", have you checked the code quality for the I/O "bit test" logic in avr-gcc v4.1.2? I reported the following "bad I/O code" awhile back with avr-gcc v3.4.6: An example of why more people should be "watching" the "avr-gcc" code generator are these three simple C routines which test a bit in one of the AVR microcontroller I/O ports. Because of the AVR instruction set's clever "sbic" and "sbis" instructions, the machine code for tests like these should be short...and very fast. However, only "test3()" produces the expected (i.e., correct) AVR instructions: #include <avr/io.h> #define J1708_IN_PORT PORTD #define J1708_IN_DDR DDRD #define J1708_IN_PIN PIND #define J1708_IN_BIT 3 int test1(void) { unsigned char bit = (J1708_IN_PIN & (1 << J1708_IN_BIT)) ? 1 : 0; return bit; } int test2(void) { if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 0; return 1; } int test3(void) { if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 1; return 0; } ...compiled with avr-gcc 3.4.6: C:/WinAVR_20060421/bin/avr-gcc -mmcu=atmega16 -Os \ -mcall-prologues -Wall -c \ -gstabs -Wa,-ahlmsd=x.lst -o test.o test.c ...gives us horrible code for all except "test3()": **** int test1(void) **** { **** unsigned char bit = (J1708_IN_PIN & (1 << J1708_IN_BIT)) ? 1 : 0; test1: in r24,48-0x20 clr r25 ldi r18,3 1: lsr r25 ror r24 dec r18 brne 1b andi r24,lo8(1) **** return bit; **** } clr r25 ret **** **** int test2(void) { **** if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 0; test2: in r24,48-0x20 clr r25 movw r18,r24 andi r18,lo8(8) andi r19,hi8(8) sbrc r24,3 rjmp .L3 movw r24,r18 ret .L3: **** return 1; ldi r24,lo8(1) ldi r25,hi8(1) **** } ret **** int test3(void) { **** if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 1; test3: sbic 48-0x20,3 rjmp .L5 ldi r24,lo8(1) ldi r25,hi8(1) ret .L5: **** return 0; ldi r24,lo8(0) ldi r25,hi8(0) **** } ret The bit-shift "loop" code generated for "test1()" is really "special". :-) (Yes, that's 5 clocks per bit shift!) I was lucky that my application only referenced bit 3 in the I/O port. If the hardware had used bit 6, the routine would take twice as long to execute...over 33 clocks for an I/O bit test that should have taken just a couple of clocks! Note that the only difference between "test2()" and "test3()" is the return value (i.e., 0 vs. 1). Experiments show that returning "0" is what triggers the "bad behavior". This bad example takes 6 AVR instructions to do the work of one "sbic" instruction. Best regards, Bruce -- Bruce D. Lightner Lightner Engineering La Jolla, California Voice: +1-858-551-4011 FAX: +1-858-551-0777 Email: address@hidden URL: http://www.lightner.net/lightner/bruce/ |
[Prev in Thread] | Current Thread | [Next in Thread] |