"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