http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58390
Bug ID: 58390 Summary: avr-gcc produces unusable code when label address is placed in register Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: semicontinuity at yandex dot ru Trying to speed up the following code, I've placed 'address' variable to the r2:r3 (and added -ffixed-r2 -ffixed-r3): // ------------------------------------------------------------------------- //void* address; // placed in memory (OK) //register void* address asm("r30"); // placed in r30:r31 (OK) register void* address asm("r2"); // placed in r2:r3 or any other register (NOT OK) void test(void) { char flag = 1; goto *address; // address is computed properly beforehand for(;;) { asm volatile("nop\t\n"); flag = 0; L1: (void)&&L1; if (flag==0) { address = &&L1; return; } asm volatile("nop\t\n"); flag = 0; L2: (void)&&L2; if (flag==0) { address = &&L2; return; } } } int main(void) { for(;;) { test(); } return 0; } // ------------------------------------------------------------------------- If 'address' variable is placed in memory or in r30:r31, the generated code is OK: // ------------------------------------------------------------------------- 0000003c <test>: register void* address asm("r30"); void test(void) { 3c: 09 94 ijmp goto *address; // address is computed properly for(;;) { asm volatile("nop\t\n"); 3e: 00 00 nop // ------------------------------------------------------------------------- ijmp is generated for computed goto, address is already in r30:r31 for ijmp. If 'address' variable is placed in memory or in r2:r3, the generated code is NOT OK: // ------------------------------------------------------------------------- 0000003c <test>: register void* address asm("r2"); void test(void) { 3c: 2f 92 push r2 3e: 3f 92 push r3 40: 08 95 ret goto *address; // address is computed properly for(;;) { asm volatile("nop\t\n"); 42: 00 00 nop // ------------------------------------------------------------------------- No ijmp is generated. Instead, push r2, push r3 and ret. No pops are generated. The expected output should ideally be // ------------------------------------------------------------------------- 0000003c <test>: register void* address asm("r2"); void test(void) { 3c: ? ? movw r30, r2 3e: 09 94 ijmp goto *address; // address is computed properly for(;;) { asm volatile("nop\t\n"); 40: 00 00 nop // ------------------------------------------------------------------------- ========= avr-gcc -c -mmcu=atmega8535 -I. -gdwarf-2 -I../../bsp -I../../../.. -O3 -save-temps -v -ffixed-r2 -ffixed-r3 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wundef -Wa,-adhlns=.obj/main.lst -std=gnu99 -Wundef -MD -MP -MF .dep/main.o.d main.c -o .obj/main.o Using built-in specs. COLLECT_GCC=avr-gcc Target: avr Configured with: ../../gcc.gnu.org/gcc-4_7-branch/configure --target=avr --prefix=/local/gnu/install/gcc-4.7-mingw32 --host=i386-mingw32 --build=i686-linux-gnu --enable-languages=c,c++ --disable-nls --disable-shared --with-dwarf2 --with-avrlibc=yes Thread model: single gcc version 4.7.2 (GCC)