This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: general_operand() not accepting CONCAT?
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