This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Help with constraint for single register
On Sat, 25 Dec 2004 20:01:37 -0500, Daniel Jacobowitz <drow@false.org> wrote:
> > Next, I have a define_insn for *movqi, which can only be passed moves
> > through W. If there's a move that does not involve W, we better debug
> > that situation.
> >
> > QUESTION #2: Uh oh, somehow the compiler got a hold of W anyway, and
> > generated RTL for const -1 -> W, and passed that move to my expander.
> > How did the compiler grab W? I didn't include it in GENERAL_REGS.
> > Here's an excerpt of the register masks:
>
> As Ulrich wrote, reload will do this; a fundamental assumption is that
> all register moves are valid. Do you have secondary reload classes
> yet?
Well, I'm afraid I'm very confused about the whole reload thing. I defined:
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
((REG_P(X) && REGNO(X)==W_REGNO) ? (CLASS) : W_REG)
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) W_REG
So if I understand the documentation correctly, this says that:
1) W may be moved into any register
2) Any register except W must be moved into W
3) All moves must involve the W register as an intermediate register
Then I have this expander for reload_in (I'm just writing some
debuggint code here to see if the expander even gets called):
(define_expand "reload_inqi"
[(parallel [(match_operand:QI 0 "nonimmediate_operand" "=r")
(match_operand:QI 1 "general_operand" "g")
(match_operand:QI 2 "register_operand" "=&W")])]
""
"
{
/* op1 -> op2, op2 -> op0, where op2 is the scratch (W) register.
op1 is the reload register */
fprintf(stderr, \"***** reload_in:\n\");
fprintf(stderr, \" op0: \");
debug_rtx(operands[0]);
fprintf(stderr, \" op1: \");
debug_rtx(operands[1]);
fprintf(stderr, \" op2: \");
debug_rtx(operands[2]);
}
"
)
Unfortunately, it looks like the build bombs out, and never even calls
this expander. The error is:
../../Desktop/gcc-3.4.3/gcc/libgcc2.c:468: error: unable to find a
register to spill in class `W_REG'
../../Desktop/gcc-3.4.3/gcc/libgcc2.c:468: error: this is the insn:
(insn 3 755 12 0 ../../Desktop/gcc-3.4.3/gcc/libgcc2.c:459 (set (reg/f:QI 59)
(reg:QI 1 R50)) 0 {*movqi} (nil)
(expr_list:REG_DEAD (reg:QI 1 R50)
(nil)))
So the compiler is attempting a move pseudo-59 -> R50, which fails,
presumably because my movqi expander allows everything and does not
alter the set:
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"
{
/* pic_emit_move(operands);
DONE; */
}
"
)
...and my *movqi insn restricts the operands so that pseudo-59 -> R50
is invalid:
(define_insn "*movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,m,w,W,W")
(match_operand:QI 1 "general_operand" "W,W,w,i,r"))]
""
"\tmovf %1,%0"
[(set_attr "cc" "z")]
)
So in that case, it looks like I may have to do both:
1) Generate only moves through W in the expander for movqi.
2) Define the reload classes appropriately so that reloads always go through W.
Does that sound about right?
Thanks!
--Rob