I have a target that supports a "push.b x" operation that puts a byte onto
the stack but pre-decrements the stack pointer by 2 to maintain alignment.

I have a machine description that includes these two defines:

(define_insn "*pushqi_pre_mod"
[(set (mem:QI (pre_modify:HI (reg:HI 1)
                (plus:HI (reg:HI 1) (const_int -2))))
    (match_operand:QI 0 "general_operand" "rim"))]
""
"* return msp430_pushqi(insn, operands);"
[(set_attr "length" "2")])

(define_insn "*pushqi"
  [(set (match_operand:QI 1 "push_operand" "=<")
        (match_operand:QI 0 "general_operand" "rim"))]
  ""
  "* return msp430_pushqi(insn, operands);"
  [(set_attr "length" "2")])

I'd hoped to clean this up by removing the apparently redundant first
definition.

I have a test program which normally works fine, but if I comment out the
first define produces:

movqi.c: In function ‘pushqi_r’:
movqi.c:33:1: error: unable to generate reloads for:
(insn 6 3 7 2 movqi.c:33 (set (mem/i:QI (pre_modify:HI (reg/f:HI 1 r1)
                (plus:HI (reg/f:HI 1 r1)
                    (const_int -2 [0xfffffffe]))) [0 S1 A8])
        (reg:QI 15 r15 [ p ])) 13 {*pushqi} (expr_list:REG_DEAD
(reg:QI 15 r15 [ p ])
        (nil)))
movqi.c:33:1: internal compiler error: in find_reloads, at reload.c:3821

Instrumentation shows that push_operand succeeds, but the '<' constraint
fails, as the mem operand with pre_modify does not pass that test (nor does
it pass 'g' or 'm'; only 'X').

I've discovered HAVE_PRE_MODIFY_DISP which, based on its one-sentence
description, appears to be relevant as I'm changing the stack pointer by 2
though the operand size is 1.  But it seems to have no effect, nor does
HAVE_PRE_MODIFY_REG.

Is there a better alternative to make this work than either leaving the
extra instruction in, or replacing the "=<" constraint with "=X"?  Does the
latter have consequences that I should expect to regret?

Peter

Reply via email to