Inefficient code

Paul Koning paulkoning@comcast.net
Thu Jul 5 16:29:00 GMT 2018



> On Jul 5, 2018, at 12:01 PM, Segher Boessenkool <segher@kernel.crashing.org> wrote:
> 
> On Thu, Jul 05, 2018 at 08:45:30AM -0400, Paul Koning wrote:
>> I have a struct that looks like this:
>> 
>> struct Xrb
>> {
>>    uint16_t xrlen;		/* Length of I/O buffer in bytes */
>>    uint16_t xrbc;		/* Byte count for transfer */
>>    void * xrloc;		/* Pointer to I/O buffer */
>>    uint8_t xrci;		/* Channel number times 2 for transfer */
>>    uint32_t xrblk:24;	/* Random access block number */
>>    uint16_t xrtime;	/* Wait time for terminal input */
>>    uint16_t xrmod;		/* Modifiers */
>> };
>> 
>> When I write to xrblk (that 24 bit field) on my 16 bit target, I get unexpectly inefficient output:
>> 
>>    XRB->xrblk = 5;
>> 
>> 	movb	#5,10(r0)
>> 	clrb	11(r0)
>> 	clrb	7(r0)
> 
> (7? not 12?)

Octal offsets.  It's writing the 3 bytes in LSB to MSB order.  (PDP11 -- which has funny-endian ordering.)

> rather than the expected word write to the word-aligned lower half of that field.
>> 
>> Looking at the dumps, I see it coming into the RTL expand phase as a single write, which expand then turns into the three insns corresponding to the above.  But (of course) there is a word (HImode) move also, which has the same cost as the byte one.
>> 
>> Is there something I have to do in my target definition to get this to come out right?  This is a strict_alignment target, but alignment is satisfied in this example.  Also, SLOW_BYTE_ACCESS is 1.
> 
> What is your MOVE_MAX?  It should be 2 probably.

It is. 

I just constructed another test case that shows the same issue more blatantly:

struct s
{
    char a;
    char b;
    char c;
    char d;
    int e;
    int f;
    char h;
    char i;
};

struct s ts;

void setts(void)
{
    ts.a=2;
    ts.b=4;
    ts.c=1;
    ts.d=24;
    ts.e=5;
    ts.f=42;
    ts.h=9;
    ts.i=3;
}

Each of the fields are written separately, even though clearly the adjacent byte writes can and should be combined into a single HImode move.  This happens both with -O2 and -Os.

	paul



More information about the Gcc mailing list