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)