2010/11/8 Michael Meissner <meiss...@linux.vnet.ibm.com>:
> 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
>

I still don't understand the difference between your two examples:
If you write a define_split then whenever during combine it gets into
a pattern which matches the define_split then it splits.

What is the difference when writing define_insn_and_split?
From what I understood from the docs then if there is such an insn
then the split does not occur so it would simply match it as an insn
without splitting and at the end would print the #?
Can you please elaborate?

Thanks, Roy.

Reply via email to