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

           Summary: Missed byte (subreg) extraction
           Product: gcc
           Version: 4.6.1
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: g...@gcc.gnu.org
            Target: avr


This C source:

#define SPDR (*((char volatile*) 0x2c))

void read_adc (long big)
{ 
   SPDR = big >> 24;
   SPDR = big >> 16;
   SPDR = big >> 8; 
   SPDR = big;
} 

compiles with 
   avr-gcc -S -Os -dp -mmcu=atmega8
to:

read_adc:
    movw r26,r24     ;  2    *movsi/1    [length = 2]
    movw r24,r22
    mov r20,r27     ;  28    *ashrsi3_const/3    [length = 6]
    clr r23
    sbrc r20,7
    com r23
    mov r21,r23
    mov r22,r23
    out 44-0x20,r20     ;  9    *movqi/3    [length = 1]
    movw r20,r26     ;  29    *ashrsi3_const/3    [length = 5]
    clr r23
    sbrc r21,7
    com r23
    mov r22,r23
    out 44-0x20,r20     ;  13    *movqi/3    [length = 1]
    mov r20,r25     ;  30    *ashrsi3_const/3    [length = 6]
    mov r21,r26
    mov r22,r27
    clr r23
    sbrc r22,7
    dec r23
    out 44-0x20,r20     ;  17    *movqi/3    [length = 1]
    out 44-0x20,r24     ;  20    *movqi/3    [length = 1]
    ret     ;  26    return    [length = 1]

The shifts are done explicitely where the bytes could be saved directly.

Combiner tries insns like

Failed to match this instruction:
(set (mem/v:QI (const_int 44))
     (subreg:QI (reg:SI 49) 1))

But they don't match because of MEM_VOLATILE_P so that the MEM
does not match memory_operand as obviously volatile_ok is 0 at that moment.

Must the backend split such insns by hand?

Changing the source like

#define SPDR0 (*((char*) 0x2c))
#define SPDR1 (*((char*) 0x2d))
#define SPDR2 (*((char*) 0x2e))
#define SPDR3 (*((char*) 0x2f))

void read_adc (long big)
{ 
   SPDR0 = big >> 24;
   SPDR1 = big >> 16;
   SPDR2 = big >> 8;
   SPDR3 = big;
}


and it compiles fine:

read_adc:
    out 44-0x20,r25     ;  8    *movqi/3    [length = 1]
    out 45-0x20,r24     ;  11    *movqi/3    [length = 1]
    out 46-0x20,r23     ;  14    *movqi/3    [length = 1]
    out 47-0x20,r22     ;  16    *movqi/3    [length = 1]
    ret     ;  26    return    [length = 1]


== configure ==

Target: avr
Configured with: ../../gcc.gnu.org/gcc-4_6-branch/configure --target=avr
--prefix=/local/gnu/install/gcc-4.6-mingw32 --host=i586-mingw32
--build=i686-linux-gnu --enable-languages=c,c++ --disable-nls --disable-shared
--with-dwarf2
Thread model: single
gcc version 4.6.1 20110620 (prerelease) (GCC)

Reply via email to