Extend tree code folds to IFN_COND_*
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 12 Jul 2018 13:01:17 +0000 (13:01 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 12 Jul 2018 13:01:17 +0000 (13:01 +0000)
commit6a86928d9882c17b7526d657a38cb314fa0aaba6
tree57cdf4000ddf7bace5fd55b3cfdb32a5457aa332
parentd5cbbf873956db1c4eed15a88f935700e7d6012a
Extend tree code folds to IFN_COND_*

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.

2018-07-12  Richard Sandiford  <richard.sandiford@linaro.org>

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.

From-SVN: r262586
17 files changed:
gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/genmatch.c
gcc/gimple-match-head.c
gcc/gimple-match.h
gcc/internal-fn.c
gcc/internal-fn.h
gcc/match.pd
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/loop_add_6.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c