Re: Extend tree code folds to IFN_COND_*

2018-07-09 Thread Richard Biener
On Wed, Jul 4, 2018 at 8:46 PM Richard Sandiford
 wrote:
>
> Finally getting back to this...
>
> Richard Biener  writes:
> > On Wed, Jun 6, 2018 at 10:16 PM Richard Sandiford
> >  wrote:
> >>
> >> > On Thu, May 24, 2018 at 11:36 AM Richard Sandiford
> >> >  wrote:
> >> >>
> >> >> This patch adds match.pd support for applying normal folds to their
> >> >> IFN_COND_* forms.  E.g. the rule:
> >> >>
> >> >>   (plus @0 (negate @1)) -> (minus @0 @1)
> >> >>
> >> >> also allows the fold:
> >> >>
> >> >>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
> >> >>
> >> >> Actually doing this by direct matches in gimple-match.c would
> >> >> probably lead to combinatorial explosion, so instead, the patch
> >> >> makes gimple_match_op carry a condition under which the operation
> >> >> happens ("cond"), and the value to use when the condition is false
> >> >> ("else_value").  Thus in the example above we'd do the following
> >> >>
> >> >> (a) convert:
> >> >>
> >> >>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
> >> >>
> >> >> to:
> >> >>
> >> >>   cond:@0 (plus @1 @4) else_value:@3
> >> >>
> >> >> (b) apply gimple_resimplify to (plus @1 @4)
> >> >>
> >> >> (c) reintroduce cond and else_value when constructing the result.
> >> >>
> >> >> Nested operations inherit the condition of the outer operation
> >> >> (so that we don't introduce extra faults) but have a null else_value.
> >> >> If we try to build such an operation, the target gets to choose what
> >> >> else_value it can handle efficiently: obvious choices include one of
> >> >> the operands or a zero constant.  (The alternative would be to have some
> >> >> representation for an undefined value, but that seems a bit invasive,
> >> >> and isn't likely to be useful here.)
> >> >>
> >> >> I've made the condition a mandatory part of the gimple_match_op
> >> >> constructor so that it doesn't accidentally get dropped.
> >> >>
> >> >> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> >> >> and x86_64-linux-gnu.  OK to install?
> >> >
> >> > It looks somewhat clever but after looking for a while it doesn't handle
> >> > simplifying
> >> >
> >> >  (IFN_COND_ADD @0 @1 (IFN_COND_SUB @0 @2 @1 @3) @3)
> >> >
> >> > to
> >> >
> >> >  (cond @0 @2 @3)
> >> >
> >> > right?  Because while the conditional gimple_match_op is built
> >> > by try_conditional_simplification it isn't built when doing
> >> > SSA use->def following in the generated matching code?
> >>
> >> Right.  This would be easy to add, but there's no motivating case yet.
> >
> > ...
> >
> >> > So it looks like a bit much noise for this very special case?
> >> >
> >> > I suppose you ran into the need of these foldings from looking
> >> > at real code - which foldings specifically were appearing here?
> >> > Usually code is well optimized before if-conversion/vectorization
> >> > so we shouldn't need full-blown handling?
> >>
> >> It's needed to get the FMA, FMS, FNMA and FNMS folds for IFN_COND_* too.
> >> I thought it'd be better to do it "automatically" rather than add specific
> >> folds, since if we don't do it automatically now, it's going to end up
> >> being a precedent for not doing it automatically in future either.
> >
> > ... not like above isn't a similar precedent ;)  But OK, given...
>
> But we're not doing the above case manually either yet :-)  Whereas the
> series does need to do what the patch does one way or another.
>
> Also, it might be hard to do the above case manually anyway (i.e. match
> nested IFN_COND_* ops with an implicitly-conditional top-level op),
> since the match.pd rule wouldn't have easy access to the overall condition.
> And that's by design, or so I'd like to claim.
>
> >> > That said, I'm not sure how much work it is to massage
> >> >
> >> >   if (gimple *def_stmt = get_def (valueize, op2))
> >> > {
> >> >   if (gassign *def = dyn_cast  (def_stmt))
> >> > switch (gimple_assign_rhs_code (def))
> >> >   {
> >> >   case PLUS_EXPR:
> >> >
> >> > to look like
> >> >
> >> >   if (gimple *def_stmt = get_def (valueize, op2))
> >> > {
> >> >code = ERROR_MARK;
> >> >if (!is_cond_ifn_with_cond (curr_gimple_match_op, &code))
> >> >  if (gassign *def dyn_cast  (def_stmt))
> >> >code = gimple_assign_rhs_code (def);
> >> >switch (code)
> >> >  {
> >> >  case PLUS_EXPR:
> >> >
> >> > thus transparently treat the IFN_COND_* as their "code" if the condition
> >> > matches that of the context (I'm not sure if we can do anything for
> >> > mismatching contexts).
> >>
> >> Yeah, this was one approach I had in mind for the subnodes, if we do
> >> end up needing it.  But at least for the top-level node, we want to try
> >> both as a native IFN_COND_FOO and as a conditional FOO, which is why the
> >> top-level case is handled directly in gimple-match-head.c.
> >>
> >> Of course, tr

Re: Extend tree code folds to IFN_COND_*

2018-07-04 Thread Richard Sandiford
Finally getting back to this...

Richard Biener  writes:
> On Wed, Jun 6, 2018 at 10:16 PM Richard Sandiford
>  wrote:
>>
>> > On Thu, May 24, 2018 at 11:36 AM Richard Sandiford
>> >  wrote:
>> >>
>> >> This patch adds match.pd support for applying normal folds to their
>> >> IFN_COND_* forms.  E.g. the rule:
>> >>
>> >>   (plus @0 (negate @1)) -> (minus @0 @1)
>> >>
>> >> also allows the fold:
>> >>
>> >>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
>> >>
>> >> Actually doing this by direct matches in gimple-match.c would
>> >> probably lead to combinatorial explosion, so instead, the patch
>> >> makes gimple_match_op carry a condition under which the operation
>> >> happens ("cond"), and the value to use when the condition is false
>> >> ("else_value").  Thus in the example above we'd do the following
>> >>
>> >> (a) convert:
>> >>
>> >>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
>> >>
>> >> to:
>> >>
>> >>   cond:@0 (plus @1 @4) else_value:@3
>> >>
>> >> (b) apply gimple_resimplify to (plus @1 @4)
>> >>
>> >> (c) reintroduce cond and else_value when constructing the result.
>> >>
>> >> Nested operations inherit the condition of the outer operation
>> >> (so that we don't introduce extra faults) but have a null else_value.
>> >> If we try to build such an operation, the target gets to choose what
>> >> else_value it can handle efficiently: obvious choices include one of
>> >> the operands or a zero constant.  (The alternative would be to have some
>> >> representation for an undefined value, but that seems a bit invasive,
>> >> and isn't likely to be useful here.)
>> >>
>> >> I've made the condition a mandatory part of the gimple_match_op
>> >> constructor so that it doesn't accidentally get dropped.
>> >>
>> >> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
>> >> and x86_64-linux-gnu.  OK to install?
>> >
>> > It looks somewhat clever but after looking for a while it doesn't handle
>> > simplifying
>> >
>> >  (IFN_COND_ADD @0 @1 (IFN_COND_SUB @0 @2 @1 @3) @3)
>> >
>> > to
>> >
>> >  (cond @0 @2 @3)
>> >
>> > right?  Because while the conditional gimple_match_op is built
>> > by try_conditional_simplification it isn't built when doing
>> > SSA use->def following in the generated matching code?
>>
>> Right.  This would be easy to add, but there's no motivating case yet.
>
> ...
>
>> > So it looks like a bit much noise for this very special case?
>> >
>> > I suppose you ran into the need of these foldings from looking
>> > at real code - which foldings specifically were appearing here?
>> > Usually code is well optimized before if-conversion/vectorization
>> > so we shouldn't need full-blown handling?
>>
>> It's needed to get the FMA, FMS, FNMA and FNMS folds for IFN_COND_* too.
>> I thought it'd be better to do it "automatically" rather than add specific
>> folds, since if we don't do it automatically now, it's going to end up
>> being a precedent for not doing it automatically in future either.
>
> ... not like above isn't a similar precedent ;)  But OK, given...

But we're not doing the above case manually either yet :-)  Whereas the
series does need to do what the patch does one way or another.

Also, it might be hard to do the above case manually anyway (i.e. match
nested IFN_COND_* ops with an implicitly-conditional top-level op),
since the match.pd rule wouldn't have easy access to the overall condition.
And that's by design, or so I'd like to claim.

>> > That said, I'm not sure how much work it is to massage
>> >
>> >   if (gimple *def_stmt = get_def (valueize, op2))
>> > {
>> >   if (gassign *def = dyn_cast  (def_stmt))
>> > switch (gimple_assign_rhs_code (def))
>> >   {
>> >   case PLUS_EXPR:
>> >
>> > to look like
>> >
>> >   if (gimple *def_stmt = get_def (valueize, op2))
>> > {
>> >code = ERROR_MARK;
>> >if (!is_cond_ifn_with_cond (curr_gimple_match_op, &code))
>> >  if (gassign *def dyn_cast  (def_stmt))
>> >code = gimple_assign_rhs_code (def);
>> >switch (code)
>> >  {
>> >  case PLUS_EXPR:
>> >
>> > thus transparently treat the IFN_COND_* as their "code" if the condition
>> > matches that of the context (I'm not sure if we can do anything for
>> > mismatching contexts).
>>
>> Yeah, this was one approach I had in mind for the subnodes, if we do
>> end up needing it.  But at least for the top-level node, we want to try
>> both as a native IFN_COND_FOO and as a conditional FOO, which is why the
>> top-level case is handled directly in gimple-match-head.c.
>>
>> Of course, trying both for subnodes would lead to exponential behaviour
>> in general.  And like you say, in practice most double-IFN_COND cases
>> should have been folded before we created the IFN_CONDs, so it's hard
>> to tell which recursive behaviour would be best.
>
> ... this it probably makes sense t

Re: Extend tree code folds to IFN_COND_*

2018-06-07 Thread Richard Biener
On Wed, Jun 6, 2018 at 10:16 PM Richard Sandiford
 wrote:
>
> > On Thu, May 24, 2018 at 11:36 AM Richard Sandiford
> >  wrote:
> >>
> >> This patch adds match.pd support for applying normal folds to their
> >> IFN_COND_* forms.  E.g. the rule:
> >>
> >>   (plus @0 (negate @1)) -> (minus @0 @1)
> >>
> >> also allows the fold:
> >>
> >>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
> >>
> >> Actually doing this by direct matches in gimple-match.c would
> >> probably lead to combinatorial explosion, so instead, the patch
> >> makes gimple_match_op carry a condition under which the operation
> >> happens ("cond"), and the value to use when the condition is false
> >> ("else_value").  Thus in the example above we'd do the following
> >>
> >> (a) convert:
> >>
> >>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
> >>
> >> to:
> >>
> >>   cond:@0 (plus @1 @4) else_value:@3
> >>
> >> (b) apply gimple_resimplify to (plus @1 @4)
> >>
> >> (c) reintroduce cond and else_value when constructing the result.
> >>
> >> Nested operations inherit the condition of the outer operation
> >> (so that we don't introduce extra faults) but have a null else_value.
> >> If we try to build such an operation, the target gets to choose what
> >> else_value it can handle efficiently: obvious choices include one of
> >> the operands or a zero constant.  (The alternative would be to have some
> >> representation for an undefined value, but that seems a bit invasive,
> >> and isn't likely to be useful here.)
> >>
> >> I've made the condition a mandatory part of the gimple_match_op
> >> constructor so that it doesn't accidentally get dropped.
> >>
> >> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> >> and x86_64-linux-gnu.  OK to install?
> >
> > It looks somewhat clever but after looking for a while it doesn't handle
> > simplifying
> >
> >  (IFN_COND_ADD @0 @1 (IFN_COND_SUB @0 @2 @1 @3) @3)
> >
> > to
> >
> >  (cond @0 @2 @3)
> >
> > right?  Because while the conditional gimple_match_op is built
> > by try_conditional_simplification it isn't built when doing
> > SSA use->def following in the generated matching code?
>
> Right.  This would be easy to add, but there's no motivating case yet.

...

> > So it looks like a bit much noise for this very special case?
> >
> > I suppose you ran into the need of these foldings from looking
> > at real code - which foldings specifically were appearing here?
> > Usually code is well optimized before if-conversion/vectorization
> > so we shouldn't need full-blown handling?
>
> It's needed to get the FMA, FMS, FNMA and FNMS folds for IFN_COND_* too.
> I thought it'd be better to do it "automatically" rather than add specific
> folds, since if we don't do it automatically now, it's going to end up
> being a precedent for not doing it automatically in future either.

... not like above isn't a similar precedent ;)  But OK, given...

> > That said, I'm not sure how much work it is to massage
> >
> >   if (gimple *def_stmt = get_def (valueize, op2))
> > {
> >   if (gassign *def = dyn_cast  (def_stmt))
> > switch (gimple_assign_rhs_code (def))
> >   {
> >   case PLUS_EXPR:
> >
> > to look like
> >
> >   if (gimple *def_stmt = get_def (valueize, op2))
> > {
> >code = ERROR_MARK;
> >if (!is_cond_ifn_with_cond (curr_gimple_match_op, &code))
> >  if (gassign *def dyn_cast  (def_stmt))
> >code = gimple_assign_rhs_code (def);
> >switch (code)
> >  {
> >  case PLUS_EXPR:
> >
> > thus transparently treat the IFN_COND_* as their "code" if the condition
> > matches that of the context (I'm not sure if we can do anything for
> > mismatching contexts).
>
> Yeah, this was one approach I had in mind for the subnodes, if we do
> end up needing it.  But at least for the top-level node, we want to try
> both as a native IFN_COND_FOO and as a conditional FOO, which is why the
> top-level case is handled directly in gimple-match-head.c.
>
> Of course, trying both for subnodes would lead to exponential behaviour
> in general.  And like you say, in practice most double-IFN_COND cases
> should have been folded before we created the IFN_CONDs, so it's hard
> to tell which recursive behaviour would be best.

... this it probably makes sense to do it "simple" first.

Btw, I'd simply _only_ consider the IFN_ stripped path when looking for
defs if it has matching condition (which is a prerequesite anyway).  So
the get_at_the_def () would first check for IFN_ with matching condition
and then expand to the unconditional operation.  And get_at_the_def ()
for UNCOND context would never look into IFN_s.

Even the toplevel handling probably never will need the outermost
conditional IFN_ handling - at least I can't think of a pattern that
you would be forced to write the outermost conditional IFN_
explicitely?

So m

Re: Extend tree code folds to IFN_COND_*

2018-06-06 Thread Richard Sandiford
> On Thu, May 24, 2018 at 11:36 AM Richard Sandiford
>  wrote:
>>
>> This patch adds match.pd support for applying normal folds to their
>> IFN_COND_* forms.  E.g. the rule:
>>
>>   (plus @0 (negate @1)) -> (minus @0 @1)
>>
>> also allows the fold:
>>
>>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
>>
>> Actually doing this by direct matches in gimple-match.c would
>> probably lead to combinatorial explosion, so instead, the patch
>> makes gimple_match_op carry a condition under which the operation
>> happens ("cond"), and the value to use when the condition is false
>> ("else_value").  Thus in the example above we'd do the following
>>
>> (a) convert:
>>
>>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
>>
>> to:
>>
>>   cond:@0 (plus @1 @4) else_value:@3
>>
>> (b) apply gimple_resimplify to (plus @1 @4)
>>
>> (c) reintroduce cond and else_value when constructing the result.
>>
>> Nested operations inherit the condition of the outer operation
>> (so that we don't introduce extra faults) but have a null else_value.
>> If we try to build such an operation, the target gets to choose what
>> else_value it can handle efficiently: obvious choices include one of
>> the operands or a zero constant.  (The alternative would be to have some
>> representation for an undefined value, but that seems a bit invasive,
>> and isn't likely to be useful here.)
>>
>> I've made the condition a mandatory part of the gimple_match_op
>> constructor so that it doesn't accidentally get dropped.
>>
>> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
>> and x86_64-linux-gnu.  OK to install?
>
> It looks somewhat clever but after looking for a while it doesn't handle
> simplifying
>
>  (IFN_COND_ADD @0 @1 (IFN_COND_SUB @0 @2 @1 @3) @3)
>
> to
>
>  (cond @0 @2 @3)
>
> right?  Because while the conditional gimple_match_op is built
> by try_conditional_simplification it isn't built when doing
> SSA use->def following in the generated matching code?

Right.  This would be easy to add, but there's no motivating case yet.

> So it looks like a bit much noise for this very special case?
>
> I suppose you ran into the need of these foldings from looking
> at real code - which foldings specifically were appearing here?
> Usually code is well optimized before if-conversion/vectorization
> so we shouldn't need full-blown handling?

It's needed to get the FMA, FMS, FNMA and FNMS folds for IFN_COND_* too.
I thought it'd be better to do it "automatically" rather than add specific
folds, since if we don't do it automatically now, it's going to end up
being a precedent for not doing it automatically in future either.

> That said, I'm not sure how much work it is to massage
>
>   if (gimple *def_stmt = get_def (valueize, op2))
> {
>   if (gassign *def = dyn_cast  (def_stmt))
> switch (gimple_assign_rhs_code (def))
>   {
>   case PLUS_EXPR:
>
> to look like
>
>   if (gimple *def_stmt = get_def (valueize, op2))
> {
>code = ERROR_MARK;
>if (!is_cond_ifn_with_cond (curr_gimple_match_op, &code))
>  if (gassign *def dyn_cast  (def_stmt))
>code = gimple_assign_rhs_code (def);
>switch (code)
>  {
>  case PLUS_EXPR:
>
> thus transparently treat the IFN_COND_* as their "code" if the condition
> matches that of the context (I'm not sure if we can do anything for
> mismatching contexts).

Yeah, this was one approach I had in mind for the subnodes, if we do
end up needing it.  But at least for the top-level node, we want to try
both as a native IFN_COND_FOO and as a conditional FOO, which is why the
top-level case is handled directly in gimple-match-head.c.

Of course, trying both for subnodes would lead to exponential behaviour
in general.  And like you say, in practice most double-IFN_COND cases
should have been folded before we created the IFN_CONDs, so it's hard
to tell which recursive behaviour would be best.

Thanks,
Richard


Re: Extend tree code folds to IFN_COND_*

2018-06-06 Thread Richard Biener
On Thu, May 24, 2018 at 11:36 AM Richard Sandiford
 wrote:
>
> This patch adds match.pd support for applying normal folds to their
> IFN_COND_* forms.  E.g. the rule:
>
>   (plus @0 (negate @1)) -> (minus @0 @1)
>
> also allows the fold:
>
>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
>
> Actually doing this by direct matches in gimple-match.c would
> probably lead to combinatorial explosion, so instead, the patch
> makes gimple_match_op carry a condition under which the operation
> happens ("cond"), and the value to use when the condition is false
> ("else_value").  Thus in the example above we'd do the following
>
> (a) convert:
>
>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
>
> to:
>
>   cond:@0 (plus @1 @4) else_value:@3
>
> (b) apply gimple_resimplify to (plus @1 @4)
>
> (c) reintroduce cond and else_value when constructing the result.
>
> Nested operations inherit the condition of the outer operation
> (so that we don't introduce extra faults) but have a null else_value.
> If we try to build such an operation, the target gets to choose what
> else_value it can handle efficiently: obvious choices include one of
> the operands or a zero constant.  (The alternative would be to have some
> representation for an undefined value, but that seems a bit invasive,
> and isn't likely to be useful here.)
>
> I've made the condition a mandatory part of the gimple_match_op
> constructor so that it doesn't accidentally get dropped.
>
> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> and x86_64-linux-gnu.  OK to install?

It looks somewhat clever but after looking for a while it doesn't handle
simplifying

 (IFN_COND_ADD @0 @1 (IFN_COND_SUB @0 @2 @1 @3) @3)

to

 (cond @0 @2 @3)

right?  Because while the conditional gimple_match_op is built
by try_conditional_simplification it isn't built when doing
SSA use->def following in the generated matching code?

So it looks like a bit much noise for this very special case?

I suppose you ran into the need of these foldings from looking
at real code - which foldings specifically were appearing here?
Usually code is well optimized before if-conversion/vectorization
so we shouldn't need full-blown handling?

That said, I'm not sure how much work it is to massage

  if (gimple *def_stmt = get_def (valueize, op2))
{
  if (gassign *def = dyn_cast  (def_stmt))
switch (gimple_assign_rhs_code (def))
  {
  case PLUS_EXPR:

to look like

  if (gimple *def_stmt = get_def (valueize, op2))
{
   code = ERROR_MARK;
   if (!is_cond_ifn_with_cond (curr_gimple_match_op, &code))
 if (gassign *def dyn_cast  (def_stmt))
   code = gimple_assign_rhs_code (def);
   switch (code)
 {
 case PLUS_EXPR:

thus transparently treat the IFN_COND_* as their "code" if the condition
matches that of the context (I'm not sure if we can do anything for
mismatching contexts).

Richard.

> Richard
>
>
> 2018-05-24  Richard Sandiford  
>
> gcc/
> * target.def (preferred_else_value): New target hook.
> * doc/tm.texi.in (TARGET_PREFERRED_ELSE_VALUE): New hook.
> * doc/tm.texi: Regenerate.
> * targhooks.h (default_preferred_else_value): Declare.
> * targhooks.c (default_preferred_else_value): New function.
> * internal-fn.h (conditional_internal_fn_code): Declare.
> * internal-fn.c (FOR_EACH_CODE_MAPPING): New macro.
> (get_conditional_internal_fn): Use it.
> (conditional_internal_fn_code): New function.
> * gimple-match.h (gimple_match_cond): New struct.
> (gimple_match_op): Add a cond member function.
> (gimple_match_op::gimple_match_op): Update all forms to take a
> gimple_match_cond.
> * genmatch.c (expr::gen_transform): Use the same condition as res_op
> for the suboperation, but don't specify a particular else_value.
> * tree-ssa-sccvn.c (vn_nary_simplify, vn_reference_lookup_3)
> (visit_nary_op, visit_reference_op_load): Pass
> gimple_match_cond::UNCOND to the gimple_match_op constructor.
> * gimple-match-head.c: Include tree-eh.h
> (convert_conditional_op): New function.
> (maybe_resimplify_conditional_op): Likewise.
> (gimple_resimplify1): Call maybe_resimplify_conditional_op.
> (gimple_resimplify2): Likewise.
> (gimple_resimplify3): Likewise.
> (gimple_resimplify4): Likewise.
> (maybe_push_res_to_seq): Return null for conditional operations.
> (try_conditional_simplification): New function.
> (gimple_simplify): Call it.  Pass conditions to the gimple_match_op
> constructor.
> * match.pd: Fold VEC_COND_EXPRs of an IFN_COND_* call to a new
> IFN_COND_* call.
> * config/aarch64/aarch64.c (aarch64_preferred_else_value): New
> function.
> 

Ping: Extend tree code folds to IFN_COND_*

2018-06-01 Thread Richard Sandiford
Ping for the below, which is the only unreviewed IFN_COND_* patch.
Thanks for the reviews of the others.

Richard Sandiford  writes:
> This patch adds match.pd support for applying normal folds to their
> IFN_COND_* forms.  E.g. the rule:
>
>   (plus @0 (negate @1)) -> (minus @0 @1)
>
> also allows the fold:
>
>   (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)
>
> Actually doing this by direct matches in gimple-match.c would
> probably lead to combinatorial explosion, so instead, the patch
> makes gimple_match_op carry a condition under which the operation
> happens ("cond"), and the value to use when the condition is false
> ("else_value").  Thus in the example above we'd do the following
>
> (a) convert:
>
>   cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE
>
> to:
>
>   cond:@0 (plus @1 @4) else_value:@3
>
> (b) apply gimple_resimplify to (plus @1 @4)
>
> (c) reintroduce cond and else_value when constructing the result.
>
> Nested operations inherit the condition of the outer operation
> (so that we don't introduce extra faults) but have a null else_value.
> If we try to build such an operation, the target gets to choose what
> else_value it can handle efficiently: obvious choices include one of
> the operands or a zero constant.  (The alternative would be to have some
> representation for an undefined value, but that seems a bit invasive,
> and isn't likely to be useful here.)
>
> I've made the condition a mandatory part of the gimple_match_op
> constructor so that it doesn't accidentally get dropped.
>
> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> and x86_64-linux-gnu.  OK to install?
>
> Richard
>
>
> 2018-05-24  Richard Sandiford  
>
> gcc/
>   * target.def (preferred_else_value): New target hook.
>   * doc/tm.texi.in (TARGET_PREFERRED_ELSE_VALUE): New hook.
>   * doc/tm.texi: Regenerate.
>   * targhooks.h (default_preferred_else_value): Declare.
>   * targhooks.c (default_preferred_else_value): New function.
>   * internal-fn.h (conditional_internal_fn_code): Declare.
>   * internal-fn.c (FOR_EACH_CODE_MAPPING): New macro.
>   (get_conditional_internal_fn): Use it.
>   (conditional_internal_fn_code): New function.
>   * gimple-match.h (gimple_match_cond): New struct.
>   (gimple_match_op): Add a cond member function.
>   (gimple_match_op::gimple_match_op): Update all forms to take a
>   gimple_match_cond.
>   * genmatch.c (expr::gen_transform): Use the same condition as res_op
>   for the suboperation, but don't specify a particular else_value.
>   * tree-ssa-sccvn.c (vn_nary_simplify, vn_reference_lookup_3)
>   (visit_nary_op, visit_reference_op_load): Pass
>   gimple_match_cond::UNCOND to the gimple_match_op constructor.
>   * gimple-match-head.c: Include tree-eh.h
>   (convert_conditional_op): New function.
>   (maybe_resimplify_conditional_op): Likewise.
>   (gimple_resimplify1): Call maybe_resimplify_conditional_op.
>   (gimple_resimplify2): Likewise.
>   (gimple_resimplify3): Likewise.
>   (gimple_resimplify4): Likewise.
>   (maybe_push_res_to_seq): Return null for conditional operations.
>   (try_conditional_simplification): New function.
>   (gimple_simplify): Call it.  Pass conditions to the gimple_match_op
>   constructor.
>   * match.pd: Fold VEC_COND_EXPRs of an IFN_COND_* call to a new
>   IFN_COND_* call.
>   * config/aarch64/aarch64.c (aarch64_preferred_else_value): New
>   function.
>   (TARGET_PREFERRED_ELSE_VALUE): Redefine.
>
> gcc/testsuite/
>   * gcc.dg/vect/vect-cond-arith-2.c: New test.
>   * gcc.target/aarch64/sve/loop_add_6.c: Likewise.
>
> Index: gcc/target.def
> ===
> --- gcc/target.def2018-05-01 19:30:30.159632586 +0100
> +++ gcc/target.def2018-05-24 10:33:30.871095132 +0100
> @@ -2040,6 +2040,25 @@ HOOK_VECTOR_END (vectorize)
>  #define HOOK_PREFIX "TARGET_"
>  
>  DEFHOOK
> +(preferred_else_value,
> + "This hook returns the target's preferred final argument for a call\n\
> +to conditional internal function @var{ifn} (really of type\n\
> +@code{internal_fn}).  @var{type} specifies the return type of the\n\
> +function and @var{ops} are the operands to the conditional operation,\n\
> +of which there are @var{nops}.\n\
> +\n\
> +For example, if @var{ifn} is @code{IFN_COND_ADD}, the hook returns\n\
> +a value of type @var{type} that should be used when @samp{@var{ops}[0]}\n\
> +and @samp{@var{ops}[1]} are conditionally added together.\n\
> +\n\
> +This hook is only relevant if the target supports conditional patterns\n\
> +like @code{cond_add@var{m}}.  The default implementation returns a zero\n\
> +constant of type @var{type}.",
> + tree,
> + (unsigned ifn, tree type, unsigned nops, tree *ops),
> + default_preferred_else_value)
> +
> +DEFHOOK
>  (record_offload_symbol,
>   "Used when offloa

Extend tree code folds to IFN_COND_*

2018-05-24 Thread Richard Sandiford
This patch adds match.pd support for applying normal folds to their
IFN_COND_* forms.  E.g. the rule:

  (plus @0 (negate @1)) -> (minus @0 @1)

also allows the fold:

  (IFN_COND_ADD @0 @1 (negate @2) @3) -> (IFN_COND_SUB @0 @1 @2 @3)

Actually doing this by direct matches in gimple-match.c would
probably lead to combinatorial explosion, so instead, the patch
makes gimple_match_op carry a condition under which the operation
happens ("cond"), and the value to use when the condition is false
("else_value").  Thus in the example above we'd do the following

(a) convert:

  cond:NULL_TREE (IFN_COND_ADD @0 @1 @4 @3) else_value:NULL_TREE

to:

  cond:@0 (plus @1 @4) else_value:@3

(b) apply gimple_resimplify to (plus @1 @4)

(c) reintroduce cond and else_value when constructing the result.

Nested operations inherit the condition of the outer operation
(so that we don't introduce extra faults) but have a null else_value.
If we try to build such an operation, the target gets to choose what
else_value it can handle efficiently: obvious choices include one of
the operands or a zero constant.  (The alternative would be to have some
representation for an undefined value, but that seems a bit invasive,
and isn't likely to be useful here.)

I've made the condition a mandatory part of the gimple_match_op
constructor so that it doesn't accidentally get dropped.

Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
and x86_64-linux-gnu.  OK to install?

Richard


2018-05-24  Richard Sandiford  

gcc/
* target.def (preferred_else_value): New target hook.
* doc/tm.texi.in (TARGET_PREFERRED_ELSE_VALUE): New hook.
* doc/tm.texi: Regenerate.
* targhooks.h (default_preferred_else_value): Declare.
* targhooks.c (default_preferred_else_value): New function.
* internal-fn.h (conditional_internal_fn_code): Declare.
* internal-fn.c (FOR_EACH_CODE_MAPPING): New macro.
(get_conditional_internal_fn): Use it.
(conditional_internal_fn_code): New function.
* gimple-match.h (gimple_match_cond): New struct.
(gimple_match_op): Add a cond member function.
(gimple_match_op::gimple_match_op): Update all forms to take a
gimple_match_cond.
* genmatch.c (expr::gen_transform): Use the same condition as res_op
for the suboperation, but don't specify a particular else_value.
* tree-ssa-sccvn.c (vn_nary_simplify, vn_reference_lookup_3)
(visit_nary_op, visit_reference_op_load): Pass
gimple_match_cond::UNCOND to the gimple_match_op constructor.
* gimple-match-head.c: Include tree-eh.h
(convert_conditional_op): New function.
(maybe_resimplify_conditional_op): Likewise.
(gimple_resimplify1): Call maybe_resimplify_conditional_op.
(gimple_resimplify2): Likewise.
(gimple_resimplify3): Likewise.
(gimple_resimplify4): Likewise.
(maybe_push_res_to_seq): Return null for conditional operations.
(try_conditional_simplification): New function.
(gimple_simplify): Call it.  Pass conditions to the gimple_match_op
constructor.
* match.pd: Fold VEC_COND_EXPRs of an IFN_COND_* call to a new
IFN_COND_* call.
* config/aarch64/aarch64.c (aarch64_preferred_else_value): New
function.
(TARGET_PREFERRED_ELSE_VALUE): Redefine.

gcc/testsuite/
* gcc.dg/vect/vect-cond-arith-2.c: New test.
* gcc.target/aarch64/sve/loop_add_6.c: Likewise.

Index: gcc/target.def
===
--- gcc/target.def  2018-05-01 19:30:30.159632586 +0100
+++ gcc/target.def  2018-05-24 10:33:30.871095132 +0100
@@ -2040,6 +2040,25 @@ HOOK_VECTOR_END (vectorize)
 #define HOOK_PREFIX "TARGET_"
 
 DEFHOOK
+(preferred_else_value,
+ "This hook returns the target's preferred final argument for a call\n\
+to conditional internal function @var{ifn} (really of type\n\
+@code{internal_fn}).  @var{type} specifies the return type of the\n\
+function and @var{ops} are the operands to the conditional operation,\n\
+of which there are @var{nops}.\n\
+\n\
+For example, if @var{ifn} is @code{IFN_COND_ADD}, the hook returns\n\
+a value of type @var{type} that should be used when @samp{@var{ops}[0]}\n\
+and @samp{@var{ops}[1]} are conditionally added together.\n\
+\n\
+This hook is only relevant if the target supports conditional patterns\n\
+like @code{cond_add@var{m}}.  The default implementation returns a zero\n\
+constant of type @var{type}.",
+ tree,
+ (unsigned ifn, tree type, unsigned nops, tree *ops),
+ default_preferred_else_value)
+
+DEFHOOK
 (record_offload_symbol,
  "Used when offloaded functions are seen in the compilation unit and no 
named\n\
 sections are available.  It is called once for each symbol that must be\n\
Index: gcc/doc/tm.texi.in
===
--- gcc/doc/tm.texi.in  2018-05-01