This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]