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