I found that compiling for mips with -mabi=n32 produces such inefficient code. 
When -mabi=n32, mips_return_in_memory returns 0 if size is small regardless 
BLKmode or not. 

        .type   foo, @function
foo:
        .frame  $sp,16,$31              # vars= 16, regs= 0/0, args= 0, gp= 0

        addiu   $sp,$sp,-16
        li      $2,-7                   # 0xfffffffffffffff9
        sh      $2,0($sp)
        sh      $2,2($sp)
        ld      $3,0($sp)
        addiu   $sp,$sp,16
        dsrl    $4,$3,32
        andi    $4,$4,0xffff
        dsrl    $3,$3,48
        dsll    $4,$4,32
        dsll    $2,$3,48
        j       $31
        or      $2,$2,$4

        .ent    main
        .type   main, @function
main:
        
        addiu   $sp,$sp,-48
        sd      $31,40($sp)
        jal     foo
        nop

        dsra    $3,$2,32
        dsrl    $2,$2,48
        sh      $3,18($sp)
        sh      $2,16($sp)
        lw      $2,16($sp)
        sll     $3,$2,16
        sw      $2,0($sp)
        sra     $3,$3,16
        li      $2,-7                   # 0xfffffffffffffff9
        bne     $3,$2,$L8
        ld      $31,40($sp)

        j       $31
        addiu   $sp,$sp,48

$L8:
        jal     abort
        nop


With old ABI, produced code is much simpler but the structure is returned 
through memory. mips_retrun_in_memory returns 1 because the structure type is 
BLKmode.

foo:
        li      $3,-7                   # 0xfffffffffffffff9
        move    $2,$4
        sh      $3,0($4)
        j       $31
        sh      $3,2($4)

        .ent    main
        .type   main, @function
main:
        .frame  $sp,32,$31              # vars= 8, regs= 1/0, args= 16, gp= 0
        
        addiu   $sp,$sp,-32
        sw      $31,28($sp)
        jal     foo
        addiu   $4,$sp,16

        lh      $3,18($sp)
        li      $2,-7                   # 0xfffffffffffffff9
        bne     $3,$2,$L8
        nop

        lw      $31,28($sp)
        nop
        j       $31
        addiu   $sp,$sp,32

$L8:
        jal     abort
        nop

> -----Original Message-----
> From: gcc-ow...@gcc.gnu.org [mailto:gcc-ow...@gcc.gnu.org] On 
> Behalf Of Bingfeng Mei
> Sent: 13 March 2009 16:35
> To: gcc@gcc.gnu.org
> Cc: Adrian Ashley
> Subject: Understand BLKmode and returning structure in register.
> 
> Hello,
> I came across an issue regarding BLKmode and returning 
> structure in register.  For following code,  I try to return 
> the structure in register instead of memory. 
>  
> extern void abort();
> typedef struct {
>   short x;
>   short y;
> } COMPLEX;
>  
> COMPLEX foo (void) __attribute__ ((noinline));
> COMPLEX foo (void)
> {
>   COMPLEX  x;  
>  
>   x.x = -7;
>   x.y = -7;
>  
>   return x;
> }
>  
> 
> int main(){
>   COMPLEX x = foo();
>   if(x.y != -7)
>     abort();
> }
> 
>  
> In foo function, compute_record_mode function will set the 
> mode for struct COMPLEX as BLKmode partly because 
> STRICT_ALIGNMENT is 1 on my target. In 
> TARGET_RETURN_IN_MEMORY hook, I return 1 for BLKmode type and 
> 0 otherwise for small size (<8) (like MIPS). Thus, this 
> structure is still returned through memory, which is not very 
> efficient. More importantly, ABI is NOT FIXED under such 
> situation. If an assembly code programmer writes a function 
> returning a structure. How does he know the structure will be 
> treated as BLKmode or otherwise? So he doesn't know whether 
> to pass result through memory or register. Do I understand correctly?
> 
> On the other hand, if I return 0 only according to struct 
> type's size regardless BLKmode or not, GCC will produces very 
> inefficient code. For example, stack setup code in foo is 
> still generated even it is totally unnecessary.
> 
> Only when I set STRICT_ALIGNMENT to 0, the structure can be 
> passed through register in an efficient way. Unfortunately, 
> our machine is strictly aligned and I cannot really do that. 
> 
> Any suggestion? 
> 
> Thanks,
> Bingfeng Mei
> Broadcom UK 
> 
> 
> 

Reply via email to