[Bug c/56439] New: global and local register variables don't work in a useful way -- AVR

2013-02-24 Thread rfmerrill at berkeley dot edu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439



 Bug #: 56439

   Summary: global and local register variables don't work in a

useful way -- AVR

Classification: Unclassified

   Product: gcc

   Version: 4.7.2

Status: UNCONFIRMED

  Severity: normal

  Priority: P3

 Component: c

AssignedTo: unassig...@gcc.gnu.org

ReportedBy: rfmerr...@berkeley.edu





I am writing some interrupt code for an Atmel AVR microcontroller and I'm

trying to shave cycles off, specifically at the beginning of the interrupt. I

want to achieve this by minimizing the registers that need to be saved, so I

decided to declare a few variables as global register variables.



What I found is that GCC will "optimize away" the register assignment and

instead produce code that is almost what I want, except it copies the value in

and out of another register (allocated the usual way) instead of operating on

the assigned one.



For example the following C:



register unsigned char foo asm ("r4");



void baz();

void quux();



void bar() {

  foo = foo * 2;

  if (foo > 10)

baz();

  else

quux();

}



generates the following assembly:



mov r24,r4

lsl r24

mov r4,r24

cpi r24,lo8(11)

brsh .L4

rjmp quux

.L4:

rjmp baz





It does the same thing (copy to r24, manipulate, copy back) on every

optimization level.



Surely this can't be desired behavior? If you use local register variables it's

often even worse, as gcc won't touch the assigned register at all but instead

produce identical code that uses a different register.



I'm fairly certain this shouldn't work this way...


[Bug target/56439] global and local register variables don't work in a useful way -- AVR

2013-02-24 Thread rfmerrill at berkeley dot edu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439



--- Comment #2 from Robert "Finny" Merrill  
2013-02-25 03:30:47 UTC ---

Any specific sections you can point me to? I'd be interested to hear a

justification for this behavior.


[Bug target/56439] global and local register variables don't work in a useful way -- AVR

2013-02-24 Thread rfmerrill at berkeley dot edu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439



--- Comment #4 from Robert "Finny" Merrill  
2013-02-25 05:46:29 UTC ---

Wouldn't that be a reason /against/ doing this:



mov r24,r4

lsl r24

mov r4,r24



instead of just lsl r4?


[Bug target/56439] global and local register variables don't work in a useful way -- AVR

2013-02-25 Thread rfmerrill at berkeley dot edu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439



--- Comment #6 from Robert "Finny" Merrill  
2013-02-25 16:39:39 UTC ---

Well other than the fact that it now uses two registers (the registers are

8-bit and ints are 16-bit), no, it does the same thing



register int foo asm ("r30");



void baz();

void quux();



void bar() {

  foo = foo * 2;

  if (foo > 10)

baz();

  else

quux();

}





yields:



bar:

/* prologue: function */

/* frame size = 0 */

/* stack size = 0 */

.L__stack_usage = 0

mov r24,r30

mov r25,r31

lsl r24

rol r25

mov r30,r24

mov r31,r25

sbiw r24,11

brge .L4

rjmp quux

.L4:

rjmp baz