[Bug target/56439] global and local register variables don't work in a useful way -- AVR
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439 Georg-Johann Lay changed: What|Removed |Added CC||gjl at gcc dot gnu.org --- Comment #8 from Georg-Johann Lay 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: :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
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439 --- Comment #7 from Chung-Ju Wu 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
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
[Bug target/56439] global and local register variables don't work in a useful way -- AVR
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439 Chung-Ju Wu changed: What|Removed |Added CC||jasonwucj at gmail dot com --- Comment #5 from Chung-Ju Wu 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?
[Bug target/56439] global and local register variables don't work in a useful way -- AVR
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
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439 --- Comment #3 from Andrew Pinski 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
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
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56439 Andrew Pinski changed: What|Removed |Added Component|c |target --- Comment #1 from Andrew Pinski 2013-02-25 03:10:35 UTC --- I think this is correct behavior if you read the manual.