Re: Optimizing 32 bits integer manipulation on 8 bit AVR target

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sylvain Leroux schrieb:
Hi,

It seems to me that avr-gcc/avr-g++ is producing sub-optimal code for the 'f' function in the following source code:

---------8<-----------------------------------
#include <avr/io.h>

void f(uint32_t i) {
    i |= ((uint32_t)(0xFF) << 16);

    /* DDRA is an 8 bit register */
    DDRA = (uint32_t)(i);
    DDRA = (uint32_t)(i>>8);
    DDRA = (uint32_t)(i>>16);
    DDRA = (uint32_t)(i>>24);
}

int main() {
    volatile uint32_t n = 0x01020304;

    f(n);
}
---------8<-----------------------------------
Having compiled with the following options:
avr-gcc c.c -mmcu=attiny2313
            -Os -ffunction-sections -fdata-sections
            -g -Wl,--gc-sections -Wl,--print-gc-sections
            -fipa-cp -fcprop-registers -fweb

... here is the relevant fragment as displayed by avr-objdump. I marked with a star (*) all the instruction that appears to be useless:
---------8<-----------------------------------
void f(uint32_t i) {
    i |= ((uint32_t)(0xFF) << 16);
  34:   8f 6f           ori     r24, 0xFF       ; 255

    DDRA = (uint32_t)(i);
  36:   6a bb           out     0x1a, r22       ; 26
    DDRA = (uint32_t)(i>>8);
  38:   27 2f           mov     r18, r23
* 3a:   38 2f           mov     r19, r24
* 3c:   49 2f           mov     r20, r25
* 3e:   55 27           eor     r21, r21
  40:   2a bb           out     0x1a, r18       ; 26
    DDRA = (uint32_t)(i>>16);
  42:   9c 01           movw    r18, r24
* 44:   44 27           eor     r20, r20
* 46:   55 27           eor     r21, r21
  48:   2a bb           out     0x1a, r18       ; 26
    DDRA = (uint32_t)(i>>24);
  4a:   69 2f           mov     r22, r25
* 4c:   77 27           eor     r23, r23
* 4e:   88 27           eor     r24, r24
* 50:   99 27           eor     r25, r25
  52:   6a bb           out     0x1a, r22       ; 26
}
  54:   08 95           ret
---------8<-----------------------------------

Both gcc and g++ produce the same code. And I get the same results both with 4.3.5 and 4.7.1

Here is my question:
Is there any option(s) that will help gcc to not produce those extra instructions in such case?

This is PR49807 which is not avr specific.

PR49807 is missed RTL optimization, but other targets like 32-bit
targets typically don't see it because their SFRs are 32 bits wide.

Just compile the following test case and the issue is gone.
If you remove the #define a, b, c, d you see PR49807 again.

Johann

--

typedef unsigned long uint32_t;

#define DDRA (*(volatile unsigned char*) 0x3A)

extern unsigned char a, b, c, d;

#define a DDRA
#define b DDRA
#define c DDRA
#define d DDRA

void f (uint32_t i)
{
    i |= 0xFFul << 16;

    /* DDRA is an 8 bit register */
    a = i;
    b = i >> 8;
    c = i >> 16;
    d = i >> 24;
}




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux