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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |gjl at gcc dot gnu.org
         Resolution|---                         |INVALID

--- Comment #1 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
(In reply to semicontinuity from comment #0)
> 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.

This PUSH/PUSH/RET sequence is in order because is acts exactly like an IJMP
for targets with 16-bit PC.  This is the case for ATmega8535 as of
-mmcu=atmega8535.

FYI, reserving r30/r31 (Z-reg) might break code because there are situations
where the compiler cannot generate code without using Z, e.g. when reading from
flash by means of LPM. Or indirect addressing when a frame pointer is needed
and Y cannot be used for addressing.

Reply via email to