diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2018-07-12 13:01:17 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-07-12 13:01:17 +0000 |
commit | 6a86928d9882c17b7526d657a38cb314fa0aaba6 (patch) | |
tree | 57cdf4000ddf7bace5fd55b3cfdb32a5457aa332 /gcc/tree-ssa-sccvn.c | |
parent | d5cbbf873956db1c4eed15a88f935700e7d6012a (diff) | |
download | gcc-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.c | 19 |
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); } |