Oleg Endo schrieb:
Hello,

On Thu, 2012-08-23 at 19:52 +0200, Georg-Johann Lay wrote:
Uros Bizjak wrote:
Hello!

This patch introduces TARGET_REJECT_COMBINED_INSN target hook, so
targets are able to reject combinations of two or more insns. The hook
is called from recog_for_combine, so it is the target that has the
final say on the combined insn.
Hi,

great place for a hook, it was missing, IMO.

Just a note:  Wouldn't it be good to have a hook that may transform
a pattern to a new one and return that to combine?

As far as I understand that's what the splits during combine are for.

These patters are very specific.  They only can map one set to two sets.
It's not possible to implement a canonicalization for anything
combine might come up with and that is just ready to be stuffed
into recog.

However, I always get surprised when combine would actually take the
split and continue trying combinations with the insns that came out from
the split, and when it won't.  Sometimes it works, sometimes it doesn't.
Very often I have to resort to insn_and_split, which is similar, but not
the same ...

The advantage is that you can da any transform in split1, even with new
pseudos.  The disadvantage is that the result does not get back into
combine and that in split1 the meta-information om involved data is
lost (zeroed bits etc.).  At least that information is not available
in insn condition or predicate.

However, there may be a pattern that does exactly the same thing
but is written down differently.  The backend then could try to
canonicalize the pattern before it goes into recog.

Do you mean something like already existing CANONICALIZE_COMPARISON
macro?  If so, then probably one would have to match/transform the
patterns in C, which is not 'very nice', IMHO.  Maybe relaxing the

Yes, it's a hook and in C.  Sometime C can be more convenient.

For the hook in question, it would be the same effort as far as
the hook is concerned:  Ir really makes no difference if you

- Pass X to the hook and return true or false

- Pass X to the hook and return X or NULL_RTX.

However, the latter interface is much more general and powerful and
allows to change X -- or simply leave it alone like in
legitimize_address (target_legitimize_combine or so).

Some years ago there were plans for a define_combine thing for the
backend (similar to define_insn/split/expand/peephole etc.)
But that idea was dropped for some reason or in favor of a better or
easier approach.

combine-splitting (not insn_and_split, just define_split) would be
better for this?

RTL is great.  I think it makes reading and writing back ends much
more robust, easy and powerful.  And I always wondered why there is
no tree/SSA equivalent of RTL.

However, sometimes you are better off with C.

In any case, if combine doesn't try out all the combinations, then
something would have to do that in the backend and everything is back to
square one, except that every backend (sooner or later) will have some
kind of half-combine-half-recog implementation in it, won't it?

Yes, you are right.  There is already too much recog-like code in the
backends, for example in rtx_costs.  In a private port I call recog
from rtx_costs to get the costs from insn attributes.  Works very nice
and is much better to maintain than XEXP for many, many insns and
patterns...

An other question is:

I always wondered if it is possible to transform code like

(set (reg:SI 0)
     (ior:SI (reg SI:1)
             (reg SI:2)))

or more complicated, combined patterns to a different pattern
if there is some additional knowledge.

For example, a backend may have an insn that can do the
combined operation efficiently, but only if reg2 is a
boolean value (0 or 1).

Currently you will have to write a combine pattern like

(set (reg:SI 0)
     (ior:SI (reg SI:1)
             (and:SI (reg SI:2)
                     (const_int 0))))

and/or

(set (reg:SI 0)
     (ior:SI (reg SI:1)
             (zero_extract:SI (reg:SI 2)
                              (const_int 1)
                              (const_int x)))))

and/or

(set (reg:SI 0)
     (ior:SI (reg SI:1)
             (and:SI (lshiftrt:SI (reg SI:2)
                                  (const_int x))
                     (const_int 1))))

You can imagine that it is really tedious to write
down all these patterns and describe their rtx_costs.

I think in this case one could define a predicate for those and then
re-use it in multiple patterns.

Been there, done it: http://gcc.gnu.org/ml/gcc/2010-11/msg00222.html
This needed yet another hook in find_reloads because you don't want
to reload the whole predicate; you want to reload the individual
operands.  Therefore this needs a mapping from the predicate to its
operands.  Currently, reload has only magic for unary rtxes like
zero_extract.

As for the costs, it would really be nice if it was possible to just
say: "If this pattern is matched, the total cost is X", instead of
partially re-implementing/describing the patterns in C in the rtx_costs
function.  I was already thinking of using recog functions in the
rtx_costs function, but I'm not sure whether it is the right thing to
do.

Yes.  Just call recog in combine :-)  It needs some preparation, but
"proof of concept" work is already done and works smooth in 45 and 4.6,
and I don't see a reason why it should not work in newer versions.
If you are interested I can explain the caveats and details.

Johann

I think one of the prime examples that would benefit from those things
are patterns to implement instructions such as bit-tests with constants
(on SH: tst #imm8,R0), where the basic pattern is simply:

(define_insn "tstsi_t"
  [(set (reg:SI T_REG)
        (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
                       (match_operand:SI 1 "logical_operand" "K08,r"))
               (const_int 0)))]

.. but then 9 variations are required to make it really work under
various circumstances.

Cheers,
Oleg


Reply via email to