"Amker.Cheng" <amker.ch...@gmail.com> writes:
> Hi:
>   as to page http://gcc.gnu.org/ml/gcc/2010-05/msg00091.html,
> If the fpu register can not copied to/from memory directly, I have
> to use intermediate GPR registers.
>
> In fact, I return GP_REGS if copying x to a register in class FP_REGS
> in any mode(including CCmode), this results in infinite recursive calling
> of memory_move_secondary_cost.
>
> After tracing cc1, I found the calling sequence is like:
>
> memory_move_secondary_cost (CCmode, ST_REGS, 1)  -->
> memory_move_secondary_cost (CCmode, FP_REGS, 1)  -->
> memory_move_secondary_cost (CCmode, ST_REGS, 1)  -->
> memory_move_secondary_cost (CCmode, FP_REGS, 1)  -->
> ....... infinite recursive....
>
> It seems function default_secondary_reload always use ST_REGS as intermediate
> register for FP_REGS:CCmode according to reload_incc pattern.
> This is all what i found, and I have totally no idea about how reload
> pass works .

Hmm.  I think that's a flaw in memory_move_secondary_cost.  This call:

  memory_move_secondary_cost (CCmode, ST_REGS, 1)

asks for the cost of using reload_incc on a stack memory rtx:

(define_expand "reload_incc"
  [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
        (match_operand:CC 1 "general_operand" ""))
   (clobber (match_operand:TF 2 "register_operand" "=&f"))]

And secondary_reload_class rightly returns FP_REGS for this, since we
need an FP_REGS scratch register.  But memory_move_reload_cost then
thinks that the cost of loading a memory into ST_REGS is:

    cost of loading a mem into FP_REGS
  + cost of moving FP_REGS into ST_REGS

That's fine for moves via temporary registers (i.e. when the secondary
reload does not use reload_{in,out}cc) but a bit dubious for scratch
operand registers (when reload_{in,out}cc are used).  There's no telling
in general what the target is doing with the scratch register it has asked
for, and if the reload* pattern really was a simple move via a temporary,
the target probably wouldn't be defining it in the first place.

In this particular case, it might make more sense to replace:

  altclass = secondary_reload_class (in ? 1 : 0, rclass, mode, mem);

with:

  altclass = targetm.secondary_reload (in ? 1 : 0, mem, rclass, mode, &sri);

for some new temporary sri.  But that might adversely affect other targets
(as reload changes often do!).  I also might be talking gibberish; it's
thankfully a while since I had to work on reload stuff....

Anyway, I suppose the reason that this works on mainline is that:

  memory_move_secondary_cost (CCmode, FP_REGS, 1)

calls:

  default_secondary_reload (1, mem, FP_REGS, CCmode, &sri)

which in turn calls:

  SECONDARY_INPUT_RELOAD_CLASS (FP_REGS, CC_MODE, mem)

This returns NO_REGS in FSF sources but GR_REGS with your changes.
"mem" matches the predicate for operand 1 of reload_incc (namely
general_operand), so when default_secondary_reload processes the
reload_incc pattern, I suppose we have:

  reload_class == FP_REGS
  rclass == GR_REGS
  insn_class == ST_REGS
  scratch_class == FP_REGS

And because reload_class (FP_REGS) is not a subset of insn_class
(ST_REGS), default_secondary_reload thinks that you need:

  FP_REGS <- ST_REGS <- mem

with FP_REGS <- ST_REGS being done by a move and the ST_REGS <- mem
being done by reload_incc.

This is a genuine problem with the modified MIPS backend, regardless of
whether the current memory_move_secondary_cost is right.  You'll need
to override TARGET_SECONDARY_RELOAD with a MIPS-specific version that
does _not_ use reload_incc for CCmode loads into FP_REGS.  You want
a normal move via a temporary instead.

I had plans for a different approach to handling CCmode reloads,
but I don't know when/if I'll get round to them...

Richard

Reply via email to