This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]