aboutsummaryrefslogtreecommitdiff
path: root/gcc/internal-fn.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/internal-fn.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/internal-fn.c')
-rw-r--r--gcc/internal-fn.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index a7bb748..eb5493f 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3219,6 +3219,21 @@ static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
0
};
+/* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
+ tree code CODE. */
+#define FOR_EACH_CODE_MAPPING(T) \
+ T (PLUS_EXPR, IFN_COND_ADD) \
+ T (MINUS_EXPR, IFN_COND_SUB) \
+ T (MULT_EXPR, IFN_COND_MUL) \
+ T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
+ T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
+ T (RDIV_EXPR, IFN_COND_RDIV) \
+ T (MIN_EXPR, IFN_COND_MIN) \
+ T (MAX_EXPR, IFN_COND_MAX) \
+ T (BIT_AND_EXPR, IFN_COND_AND) \
+ T (BIT_IOR_EXPR, IFN_COND_IOR) \
+ T (BIT_XOR_EXPR, IFN_COND_XOR)
+
/* Return a function that only performs CODE when a certain condition is met
and that uses a given fallback value otherwise. For example, if CODE is
a binary operation associated with conditional function FN:
@@ -3238,31 +3253,30 @@ get_conditional_internal_fn (tree_code code)
{
switch (code)
{
- case PLUS_EXPR:
- return IFN_COND_ADD;
- case MINUS_EXPR:
- return IFN_COND_SUB;
- case MIN_EXPR:
- return IFN_COND_MIN;
- case MAX_EXPR:
- return IFN_COND_MAX;
- case TRUNC_DIV_EXPR:
- return IFN_COND_DIV;
- case TRUNC_MOD_EXPR:
- return IFN_COND_MOD;
- case RDIV_EXPR:
- return IFN_COND_RDIV;
- case BIT_AND_EXPR:
- return IFN_COND_AND;
- case BIT_IOR_EXPR:
- return IFN_COND_IOR;
- case BIT_XOR_EXPR:
- return IFN_COND_XOR;
+#define CASE(CODE, IFN) case CODE: return IFN;
+ FOR_EACH_CODE_MAPPING(CASE)
+#undef CASE
default:
return IFN_LAST;
}
}
+/* If IFN implements the conditional form of a tree code, return that
+ tree code, otherwise return ERROR_MARK. */
+
+tree_code
+conditional_internal_fn_code (internal_fn ifn)
+{
+ switch (ifn)
+ {
+#define CASE(CODE, IFN) case IFN: return CODE;
+ FOR_EACH_CODE_MAPPING(CASE)
+#undef CASE
+ default:
+ return ERROR_MARK;
+ }
+}
+
/* Return true if IFN is some form of load from memory. */
bool