On Tue, Nov 09, 2010 at 09:38:28AM +0200, roy rosen wrote:
> 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?

In the case where you have a define and split, such 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);")

At the end of the combine pass will be an insn with the plus and mult.  This
insn will exist for at least the  if_after_combine, partition_blocks, regmove,
and outof_cfg_layout_mode passes before it is potentially split in the
split_all_insns pass, unless you have a "&& reload_completed" in the test for
the split (second "" in the example above).

The define_insn_and_split is just syntactic sugar.  You could have written this
as:

        (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")))
          (clobber (reg:SF ACC_REGISTER))]
         ""
         "#")

        (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")))
          (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);")

Thus, if you had the following insns before combine:

        (insn ... (set (reg:SF 123)
                       (mult:SF (reg:SF 124)
                                (reg:SF 125))))

        (insn ... (set (reg:SF 126)
                       (plus:SF (reg:SF 123)
                                (reg:SF 127))))

After combine, the combined insn would be (note register 123 disappears after
combine):

        (insn ... (set (reg:SF 126)
                       (plus:SF (mult:SF (reg:SF 124)
                                         (reg:SF 125))
                                (reg:SF 127))))

The split pass would then break this back into three insns:

        (insn ... (set (reg:SF ACC_REGISTER)
                       (mult:SF (reg:SF 124)
                                (reg:SF 125))))

        (insn ... (set (reg:SF ACC_REGISTER)
                       (plus:SF (reg:SF ACC_REGISTER)
                                (reg:SF 127))))

        (insn ... (set (reg:SF 126)
                       (reg:SF ACC_REGISTER)))

Now, if you just had the split and no define_insn, combine would try and form
the (plus (mult ...)) and not find an insn to match, so while it had the
temporary insn created, it would try to immediately split the insn, so at the
end of the combine pass, you would have:

        (insn ... (set (reg:SF ACC_REGISTER)
                       (mult:SF (reg:SF 124)
                                (reg:SF 125))))

        (insn ... (set (reg:SF ACC_REGISTER)
                       (plus:SF (reg:SF ACC_REGISTER)
                                (reg:SF 127))))

        (insn ... (set (reg:SF 126)
                       (reg:SF ACC_REGISTER)))

So whether the passes in between combine and the split pass care, is a
different question.  I didn't recall that combine had this split feature.  As I
said, my preference is to create the insn, and then split it later.

Note, you can only allocate new registers (either hard registers or pseudo
registers) in the split passes before register allocation.  You will get an
error if you create a new register after reload.

-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meiss...@linux.vnet.ibm.com

Reply via email to