On Thu, Oct 28, 2010 at 09:11:44AM +0200, roy rosen wrote: > Hi all, > > I am trying to use define_split, but it seems to me that I don't > understand how it is used. > It says in the gccint.pdf (which I use as my tutorial (is there > anything better or more up to date?)) that the combiner only uses the > define_split if it doesn't find any define_insn to match. This is not > clear to me: If there is no define_insn to match a pattern in the > combine stage, then how is this pattern there in the first place? The > only way I can think for it to happen is that such a pattern was > created by the combiner itself (but it seems unreasonable to me that > we now want to split what the combiner just combined). Can someone > please explain this to me?
Basically combine.c works by trying to build a combined insn, and then it sees if it matches an insn. The canonical example is fused multiply/add (avoiding all of the issues with FMA's for the moment): (define_insn "addsf3" [(set (match_operand:SF 0 "f_operand" "=f") (plus:SF (match_operand:SF 1 "f_operand" "f") (match_operand:SF 2 "f_operand" "f")))] "" "fadd %0,%1,%2") (define_insn "mulsf3" [(set (match_operand:SF 0 "f_operand" "=f") (mult:SF (match_operand:SF 1 "f_operand" "f") (match_operand:SF 2 "f_operand" "f")))] "" "fadd %0,%1,%2") (define_insn "fmasf3" [(set (match_operand:SF 0 "f_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "f_operand" "f") (match_operand:SF 2 "f_operand" "f")) (match_operand:SF 3 "f_operand" "f")))] "" "fma %0,%1,%2,%3") What the documentation is trying to say is that instead of the fmasf3 define_insn, you could have a define_split. I personally would do a define_insn_and_split for the combined insn. Consider a weird machine that you need to do FMA in a special fixed register, but you need to do the multiply and add as separate instructions: (define_split [(set (match_operand:SF 0 "f_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "f_operand" "f") (match_operand:SF 2 "f_operand" "f")) (match_operand:SF 3 "f_operand" "f")))] "" [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2))) (set (match_dup 4) (plus:SF (match_dup 4) (match_dup 3))) (set (match_dup 0) (match_dup 4))] "operands[4] = gen_rtx_REG (SFmode, ACC_REGISTER);") I would probably write it as: (define_insn_and_split "fmasf3" [(set (match_operand:SF 0 "f_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "f_operand" "f") (match_operand:SF 2 "f_operand" "f")) (match_operand:SF 3 "f_operand" "f"))) (clobber (reg:SF ACC_REGISTER))] "" "#" "" [(set (match_dup 4) (mult:SF (match_dup 1) (match_dup 2))) (set (match_dup 4) (plus:SF (match_dup 4) (match_dup 3))) (set (match_dup 0) (match_dup 4))] "operands[4] = gen_rtx_REG (SFmode, ACC_REGISTER);") In the old days, define_split was only processed before each of the two scheduling passes if they were run and at the very end if final finds an insn string "#". Now, it is always run several times. Looking at passes.c, we see it is run: Before the 2nd lower subreg pass (which is before the 1st scheduling pass) After gcse2 and reload Just before the 2nd scheduling pass Before regstack elimination on x86 Before the execption handling/short branch passes I talked about this in part of my tutorial on using modern features in your MD file that I gave at this year's GCC summit: http://gcc.gnu.org/wiki/summit2010 -- Michael Meissner, IBM 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA meiss...@linux.vnet.ibm.com