On Wed, Apr 25, 2007 at 09:11:52AM -0700, Richard Henderson wrote: > On Wed, Apr 25, 2007 at 01:51:34PM +0200, Rask Ingemann Lambertsen wrote: > > (define_mode_macro GT16 [SI DI TI SF DF XF SC DC XC SD DD TD CHI CSI CDI > > CTI]) > > > > (define_insn_and_split "*push<mode>1" > > You almost certainly do not want to handle complex yourself, > and instead rely on the fallback code in expr.c.
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 needs two more instructions, an extra register and longer instructions. It becomes even worse when the complex value is on the stack: addw $-N*2, %sp movw %sp, %basereg movw wordN(%basereg),%tmpreg movw %tmpreg, N*2(%basereg) ... movw word0(%basereg),%tmpreg movw %tmpreg, (%basereg) vs. movw %sp, %basereg pushw wordN(%basereg) ... pushw word0(%basereg) which is 1+N extra instructions, possibly only 1+(N+1)/2 extra instructions after peephole optimization. I ended up with this, which seems to work as intended: ; Complex modes. (define_mode_macro COMPLEX [SC DC XC CQI CHI CSI CDI CTI]) ; Inner mode of a complex value (concat ...). (define_mode_attr INNER [(SC "SF") (DC "DF") (XC "XF") (CQI "QI") (CHI "HI") (CSI "SI") (CDI "DI") (CTI "TI")]) ; Reload can't handle a (concat ...) operand. (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")))] "TARGET_PUSH_IMM || (!CONSTANT_P (operands[0]) && !CONSTANT_P (operands[1]))" "#" "reload_completed" ... -- Rask Ingemann Lambertsen