On Thu, Apr 26, 2007 at 01:52:37PM -0700, Richard Henderson wrote:
> On Thu, Apr 26, 2007 at 09:49:16PM +0200, Rask Ingemann Lambertsen wrote:
> >    Unfortunately, the fallback code isn't exactly optimum, as it produces
> > something like
> > 
> >     addw    $-N*2,  %sp
> >     movw    %sp,    %basereg
> >     movw    %wordN, N*2(%basereg)
> >     ...
> >     movw    %word0, (%basereg)
> > 
> > which compared with
> > 
> >     pushw   %wordN
> >     ...
> >     pushw   %word0
> 
> It's not supposed to.  Please debug emit_move_complex_push
> and find out why.  I suspect PUSH_ROUNDING is larger than
> it's supposed to be.

#define PUSH_ROUNDING(BYTES)    (((BYTES) + 1) & ~1)

   I don't see how emit_move_complex_push() can ever generate a push
instruction. Here's a backtrace:

(gdb) fin
Run till exit from #0  push_operand (op=0xb7f7b118, mode=SFmode) at 
../../../cvssrc/gcc/gcc/recog.c:1299
0x0828f941 in emit_move_multi_word (mode=SFmode, x=0xb7f78bc4, y=0xb7f793d0) at 
../../../cvssrc/gcc/gcc/expr.c:3182
Value returned is $44 = 1
(gdb) bt
#0  0x0828f941 in emit_move_multi_word (mode=SFmode, x=0xb7f78bc4, 
y=0xb7f793d0) at ../../../cvssrc/gcc/gcc/expr.c:3182
#1  0x0829016e in emit_move_insn_1 (x=0xb7f78bc4, y=0xb7f793d0) at 
../../../cvssrc/gcc/gcc/expr.c:3291
#2  0x0829074d in emit_move_insn (x=0xb7f78bc4, y=0xb7f793d0) at 
../../../cvssrc/gcc/gcc/expr.c:3351
#3  0x0828f236 in emit_move_complex_push (mode=SCmode, x=0xb7f78bb8, 
y=0xb7f78078) at ../../../cvssrc/gcc/gcc/expr.c:3025
#4  0x0828f45d in emit_move_complex (mode=SCmode, x=0xb7f78bb8, y=0xb7f78078) 
at ../../../cvssrc/gcc/gcc/expr.c:3061
#5  0x0829003f in emit_move_insn_1 (x=0xb7f78bb8, y=0xb7f78078) at 
../../../cvssrc/gcc/gcc/expr.c:3264
#6  0x0829074d in emit_move_insn (x=0xb7f78bb8, y=0xb7f78078) at 
../../../cvssrc/gcc/gcc/expr.c:3351
#7  0x0829120e in emit_single_push_insn (mode=SCmode, x=0xb7f78078, 
type=0xb7edcbd0) at ../../../cvssrc/gcc/gcc/expr.c:3582
#8  0x08291d43 in emit_push_insn (x=0xb7f78078, mode=SCmode, type=0xb7edcbd0, 
size=0x0, align=16, partial=0, reg=0x0, extra=0, args_addr=0x0,
    args_so_far=0xb7ecb210, reg_parm_stack_space=0, alignment_pad=0xb7ecb210) 
at ../../../cvssrc/gcc/gcc/expr.c:3852

(gdb) call debug_rtx(x)
(mem:SF (pre_dec:HI (reg/f:HI 12 sp)) [0 S4 A8])
(gdb) call debug_rtx(y)
(reg/v:SF 27 [ i+4 ])

   The only place where push_optab is consulted is at the beginning of
emit_single_push_insn(), which is only called from move_by_pieces() and
emit_push_insn(). emit_push_insn() isn't called from anywhere in expr.c.
I don't see how move_by_pieces() can be called by emit_move_insn(). There
seems to be no way that it could ever work.

> > (define_insn_and_split "*push<mode>1_concat"
> >   [(set (mem:COMPLEX (pre_dec:HI (reg:HI SP_REG)))
> >         (concat:COMPLEX (match_operand:<INNER> 0 "general_operand" "RmIpu")
> >                         (match_operand:<INNER> 1 "general_operand" 
> > "RmIpu")))]
> 
> This is horrible.  At minimum you should expand this to
> two separate pushed immediately.

   Usually, doing so will fool reload's frame pointer elimination if the
operand is a pseudo which ends up on the stack. Diffing the output between
the two implementations confirms it:

--- /tmp/complex-3.s_expand     2007-04-27 15:50:49.000000000 +0200
+++ /tmp/complex-3.s_postsplit  2007-04-27 15:50:26.000000000 +0200
@@ -53,8 +53,8 @@
        movw    16(%di),        %ax     
        pushw   %cx     
        pushw   %ax     
-       pushw   14(%di) 
-       pushw   12(%di) 
+       pushw   10(%di) 
+       pushw   8(%di)  
        call    g       
        movw    24(%di),        %dx     
        movw    %dx,    32(%di) 

-- 
Rask Ingemann Lambertsen

Reply via email to