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