For the following small test case there is unbelievable code bloat from
lower-subreg.c

The code reads a 4-byte value from AVR's address spaces:


long readx (const __memx long *p)
{
    return *p;
}

long read1 (const __flash1 long *p)
{
    return *p;
}


Compiled with 4.8.0


$ avr-gcc flash.c -S -dp -Os -mmcu=avr51 -fno-split-wide-types

This yields

readx:
/* prologue: function */
        movw r30,r22
        mov r21,r24
        call __xload_4
        ret

read1:
/* prologue: function */
        movw r30,r24
        ldi r18,1
        out __RAMPZ__,r18
        elpm r22,Z+
        elpm r23,Z+
        elpm r24,Z+
        elpm r25,Z+
        ret


Which is reasonable. Loads from space __memx are expensive and are outsourced
to libgcc function __xload_4.

But without the -fno-split-wide-types the code is

readx:
        push r12
        push r13
        push r14
/* prologue: function */
        mov r26,r24
        movw r24,r22
        movw r18,r24
        mov r20,r26
        subi r18,-1
        sbci r19,-1
        sbci r20,-1
        movw r30,r18
        mov r21,r20
        call __xload_1
        mov r23,r22
        ldi r18,lo8(2)
        mov r12,r18
        mov r13,__zero_reg__
        mov r14,__zero_reg__
        add r12,r24
        adc r13,r25
        adc r14,r26
        movw r18,r24
        mov r20,r26
        subi r18,-3
        sbci r19,-1
        sbci r20,-1
        movw r30,r12
        mov r21,r14
        call __xload_1
        mov r24,r22
        movw r30,r18
        mov r21,r20
        call __xload_1
        mov r25,r22
/* epilogue start */
        pop r14
        pop r13
        pop r12
        ret

read1:
/* prologue: function */
        movw r30,r24
        ldi r18,1
        out __RAMPZ__,r18
        elpm r22,Z+
        ldi r18,1
        out __RAMPZ__,r18
        elpm r23,Z
        movw r18,r24
        subi r18,-2
        sbci r19,-1
        movw r20,r24
        subi r20,-3
        sbci r21,-1
        movw r30,r18
        ldi r24,1
        out __RAMPZ__,r24
        elpm r24,Z
        movw r30,r20
        ldi r25,1
        out __RAMPZ__,r25
        elpm r25,Z
        ret

You don't need to know anything about AVR to see that the code is *really* bad
and bloat to the maximum.

Besides that the code is wrong, there are just 3 __xload_1 calls instead of 4.
But that appears to be a different issue, PR52484.

The reason is that lower-subreg.c does not care about costs at all and greedily
splits everything it gets hold of.

And a second reason is that GCC is completely afraid of pre/post
increment/modify/decrement addressing modes.

Any idea how to fix this in the backend?

There is TARGET_MODE_DEPENDENT_ADDRESS_P and it can fix the first case which
uses PSImode as pointer mode.

The second case, however, uses Pmode and in that hook there is no way to tell
if an address is to generic address space or to a special address space because
that hook hides this information from the backend and there is no address-space
flavour of the hook.

Any ideas what to do about that?

Is it reasonable hack to make
   TARGET_MODE_DEPENDENT_ADDRESS_P (PSImode) = false

Why does lower-subreg not care for costs at all?
...even if; MEMORY_MOVE_COST is not sensitive to address spaces, either.

Johann

Reply via email to