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

Reply via email to