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

2013-03-07 Thread gjl at gcc dot gnu.org


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



Georg-Johann Lay gjl at gcc dot gnu.org changed:



   What|Removed |Added



 CC||gjl at gcc dot gnu.org



--- Comment #8 from Georg-Johann Lay gjl at gcc dot gnu.org 2013-03-07 
23:26:01 UTC ---

(In reply to comment #3)

 (In reply to comment #2)

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

 justification for this behavior.

 

 Simple answer, an interrupt can happen any time after the access/assignment of

 the global register variable so it needs to be set to the value and treated as

 a volatile variable.



Is this really the case?  There is not even a means to tag a REG as volatile. 

The /v flag is set but for REGs it means user variable, see rtl.h and the

docs for volatil.



http://gcc.gnu.org/viewcvs/trunk/gcc/rtl.h?view=markup#l286



And qualifying foo as volatile diagnoses as expected:



stdin:1:1: warning: optimization may eliminate reads and/or writes to

register variables [-Wvolatile-register-var]



This issue looks rather like a fallout of reload that for some reasons spills

for the shift insn.



See also PR49491 



Or are global registers spacial for reload? I still don't see why a spilling is

needed for the shift insn...


[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 rfmerrill at berkeley dot edu 
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


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

2013-02-25 Thread jasonwucj at gmail dot com


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



--- Comment #7 from Chung-Ju Wu jasonwucj at gmail dot com 2013-02-26 
03:30:40 UTC ---

Sorry I didn't notice that it is 8-bit register on avr.

I was porting a 32-bit register target and this case is similar to mine.

That's why I have such guess in comment 5.





Now I tried to build an avr-elf target and test it with your code fragment,

using following command: $ avr-elf-gcc -S -Os test.c -fdump-rtl-all



Here are my preliminary observation:





As Andrew Pinski said in comment 3, global register variable is treated

as a volatile variable. So have:



$ vi a.c.150r.expand



 25 (insn 5 4 6 3 (set (reg:QI 42 [ foo.0 ])

 26 (reg/v:QI 4 r4 [ foo ])) a.c:11 -1

 27  (nil))

 28

 29 (insn 6 5 7 3 (set (reg:QI 43 [ foo.1 ])

 30 (ashift:QI (reg:QI 42 [ foo.0 ])

 31 (const_int 1 [0x1]))) a.c:11 -1

 32  (nil))

 33

 34 (insn 7 6 8 3 (set (reg/v:QI 4 r4 [ foo ])

 35 (reg:QI 43 [ foo.1 ])) a.c:11 -1

 36  (nil))

 37





Then, in the combine phase,

I notice that it does try to combine insn-5 and insn-6.

But it does not further combine insn-6 and insn-7.



 $ vi a.c.185r.combine



 29 (insn 6 5 7 2 (set (reg:QI 43 [ foo.1 ])

 30 (ashift:QI (reg/v:QI 4 r4 [ foo ])

 31 (const_int 1 [0x1]))) a.c:11 199 {*ashlqi3}

 32  (expr_list:REG_DEAD (reg/v:QI 4 r4 [ foo ])

 33 (nil)))

 34

 35 (insn 7 6 8 2 (set (reg/v:QI 4 r4 [ foo ])

 36 (reg:QI 43 [ foo.1 ])) a.c:11 28 {movqi_insn}

 37  (nil))

 38





Finally, at ira/reload phase, the (reg:QI 43) is assigned r24,

which does not satisfy the 'lsl' instruction constraint.

So a new insn-24 is created.



 $ vi a.c.198r.reload



 44 (insn 24 5 6 2 (set (reg:QI 24 r24 [orig:43 foo.1 ] [43])

 45 (reg/v:QI 4 r4 [ foo ])) a.c:11 28 {movqi_insn}

 46  (nil))

 47

 48 (insn 6 24 7 2 (set (reg:QI 24 r24 [orig:43 foo.1 ] [43])

 49 (ashift:QI (reg:QI 24 r24 [orig:43 foo.1 ] [43])

 50 (const_int 1 [0x1]))) a.c:11 199 {*ashlqi3}

 51  (nil))

 52

 53 (insn 7 6 8 2 (set (reg/v:QI 4 r4 [ foo ])

 54 (reg:QI 24 r24 [orig:43 foo.1 ] [43])) a.c:11 28 {movqi_insn}

 55  (nil))

 56





I am not sure if there is a solution to this issue on avr target.

Maybe someone else who work on avr porting can improve it

in combine phase or machine description design.


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

2013-02-24 Thread pinskia at gcc dot gnu.org


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



Andrew Pinski pinskia at gcc dot gnu.org changed:



   What|Removed |Added



  Component|c   |target



--- Comment #1 from Andrew Pinski pinskia at gcc dot gnu.org 2013-02-25 
03:10:35 UTC ---

I think this is correct behavior if you read the manual.


[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 rfmerrill at berkeley dot edu 
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 pinskia at gcc dot gnu.org


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



--- Comment #3 from Andrew Pinski pinskia at gcc dot gnu.org 2013-02-25 
03:53:25 UTC ---

(In reply to comment #2)

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

 justification for this behavior.



Simple answer, an interrupt can happen any time after the access/assignment of

the global register variable so it needs to be set to the value and treated as

a volatile variable.


[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 rfmerrill at berkeley dot edu 
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-24 Thread jasonwucj at gmail dot com


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



Chung-Ju Wu jasonwucj at gmail dot com changed:



   What|Removed |Added



 CC||jasonwucj at gmail dot com



--- Comment #5 from Chung-Ju Wu jasonwucj at gmail dot com 2013-02-25 
06:32:05 UTC ---

(In reply to comment #4)

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

 

 mov r24,r4

 lsl r24

 mov r4,r24

 

 instead of just lsl r4?



Just guess...



Is that possibly related to zero_extend RTL transformation?

Either in gcc optimization, or the design of machine description?



Try to use this declaration (use 'int' instead of 'char'):

  register unsigned int foo asm (r4);



Is there any difference on code generation?