aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-sccvn.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-07-12 13:01:17 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-07-12 13:01:17 +0000
commit6a86928d9882c17b7526d657a38cb314fa0aaba6 (patch)
tree57cdf4000ddf7bace5fd55b3cfdb32a5457aa332 /gcc/tree-ssa-sccvn.c
parentd5cbbf873956db1c4eed15a88f935700e7d6012a (diff)
downloadgcc-6a86928d9882c17b7526d657a38cb314fa0aaba6.zip
gcc-6a86928d9882c17b7526d657a38cb314fa0aaba6.tar.gz
gcc-6a86928d9882c17b7526d657a38cb314fa0aaba6.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa-sccvn.c')
-rw-r--r--gcc/tree-ssa-sccvn.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index d779c66..4a2f702 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1786,7 +1786,8 @@ vn_nary_simplify (vn_nary_op_t nary)
{
if (nary->length > gimple_match_op::MAX_NUM_OPS)
return NULL_TREE;
- gimple_match_op op (nary->opcode, nary->type, nary->length);
+ gimple_match_op op (gimple_match_cond::UNCOND, nary->opcode,
+ nary->type, nary->length);
memcpy (op.ops, nary->op, sizeof (tree) * nary->length);
return vn_nary_build_or_lookup_1 (&op, false);
}
@@ -2014,8 +2015,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
else if (INTEGRAL_TYPE_P (vr->type)
&& known_eq (ref->size, 8))
{
- gimple_match_op res_op (NOP_EXPR, vr->type,
- gimple_call_arg (def_stmt, 1));
+ gimple_match_op res_op (gimple_match_cond::UNCOND, NOP_EXPR,
+ vr->type, gimple_call_arg (def_stmt, 1));
val = vn_nary_build_or_lookup (&res_op);
if (!val
|| (TREE_CODE (val) == SSA_NAME
@@ -2155,7 +2156,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
|| known_eq (ref->size, TYPE_PRECISION (vr->type)))
&& multiple_p (ref->size, BITS_PER_UNIT))
{
- gimple_match_op op (BIT_FIELD_REF, vr->type,
+ gimple_match_op op (gimple_match_cond::UNCOND,
+ BIT_FIELD_REF, vr->type,
SSA_VAL (gimple_assign_rhs1 (def_stmt)),
bitsize_int (ref->size),
bitsize_int (offset - offset2));
@@ -3686,7 +3688,8 @@ visit_nary_op (tree lhs, gassign *stmt)
unsigned rhs_prec = TYPE_PRECISION (TREE_TYPE (rhs1));
if (lhs_prec == rhs_prec)
{
- gimple_match_op match_op (NOP_EXPR, type, ops[0]);
+ gimple_match_op match_op (gimple_match_cond::UNCOND,
+ NOP_EXPR, type, ops[0]);
result = vn_nary_build_or_lookup (&match_op);
if (result)
{
@@ -3699,7 +3702,8 @@ visit_nary_op (tree lhs, gassign *stmt)
{
tree mask = wide_int_to_tree
(type, wi::mask (rhs_prec, false, lhs_prec));
- gimple_match_op match_op (BIT_AND_EXPR,
+ gimple_match_op match_op (gimple_match_cond::UNCOND,
+ BIT_AND_EXPR,
TREE_TYPE (lhs),
ops[0], mask);
result = vn_nary_build_or_lookup (&match_op);
@@ -3823,7 +3827,8 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
So first simplify and lookup this expression to see if it
is already available. */
- gimple_match_op res_op (VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
+ gimple_match_op res_op (gimple_match_cond::UNCOND,
+ VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
result = vn_nary_build_or_lookup (&res_op);
}