aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-match-head.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-05-25 08:09:39 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-05-25 08:09:39 +0000
commit0d2b3bca81acf226e6c10defbc6072de4cf7e75c (patch)
tree2a0e429a6a0d5569f6a5df85a05bb542308c387e /gcc/gimple-match-head.c
parent2c53b149b7476fabd329429b2a6dce090f580ff4 (diff)
Fold VEC_COND_EXPRs to IFN_COND_* where possible
This patch adds the folds: (vec_cond COND (foo A B) C) -> (IFN_COND_FOO COND A B C) (vec_cond COND C (foo A B)) -> (IFN_COND_FOO (!COND) A B C) with the usual implicit restriction that the target must support the produced IFN_COND_FOO. The results of these folds don't have identical semantics, since the reverse transform would be invalid if (FOO A[i] B[i]) faults when COND[i] is false. But this direction is OK since we're simply dropping faults for operations whose results aren't needed. The new gimple_resimplify4 doesn't try to do any constant folding on the IFN_COND_*s. This is because a later patch will handle it by folding the associated unconditional operation. Doing this in gimple is better than doing it in .md patterns, since the second form (with the inverted condition) is much more common than the first, and it's better to fold away the inversion in gimple and optimise the result before entering expand. 2018-05-24 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * doc/sourcebuild.texi (vect_double_cond_arith: Document. * gimple-match.h (gimple_match_op::MAX_NUM_OPS): Bump to 4. (gimple_match_op::gimple_match_op): Add an overload for 4 operands. (gimple_match_op::set_op): Likewise. (gimple_resimplify4): Declare. * genmatch.c (get_operand_type): Handle CFN_COND_* functions. (expr::gen_transform): Likewise. (decision_tree::gen): Generate a simplification routine for 4 operands. * gimple-match-head.c (gimple_simplify): Add an overload for 4 operands. In the top-level function, handle up to 4 call arguments and call gimple_resimplify4. (gimple_resimplify4): New function. (build_call_internal): Pass a fourth operand. (maybe_push_to_seq): Likewise. * match.pd (UNCOND_BINARY, COND_BINARY): New operator lists. Fold VEC_COND_EXPRs of an operation and a default value into an IFN_COND_* function if possible. * config/aarch64/iterators.md (UNSPEC_COND_MAX, UNSPEC_COND_MIN): New unspecs. (SVE_COND_FP_BINARY): Include them. (optab, sve_fp_op): Handle them. (SVE_INT_BINARY_REV): New code iterator. (SVE_COND_FP_BINARY_REV): New int iterator. (commutative): New int attribute. * config/aarch64/aarch64-protos.h (aarch64_sve_prepare_conditional_op): Declare. * config/aarch64/aarch64.c (aarch64_sve_prepare_conditional_op): New function. * config/aarch64/aarch64-sve.md (cond_<optab><mode>): Use it. (*cond_<optab><mode>): New patterns for reversed operands. gcc/testsuite/ * lib/target-supports.exp (check_effective_target_vect_double_cond_arith): New proc. * gcc.dg/vect/vect-cond-arith-1.c: New test. * gcc.target/aarch64/sve/vcond_8.c: Likewise. * gcc.target/aarch64/sve/vcond_8_run.c: Likewise. * gcc.target/aarch64/sve/vcond_9.c: Likewise. * gcc.target/aarch64/sve/vcond_9_run.c: Likewise. * gcc.target/aarch64/sve/vcond_12.c: Likewise. * gcc.target/aarch64/sve/vcond_12_run.c: Likewise. From-SVN: r260710
Diffstat (limited to 'gcc/gimple-match-head.c')
-rw-r--r--gcc/gimple-match-head.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index 4598781e61c..1a12bb35e01 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -51,6 +51,8 @@ static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
code_helper, tree, tree, tree);
static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
code_helper, tree, tree, tree, tree);
+static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
+ code_helper, tree, tree, tree, tree, tree);
const unsigned int gimple_match_op::MAX_NUM_OPS;
@@ -215,6 +217,30 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
return canonicalized;
}
+/* Helper that matches and simplifies the toplevel result from
+ a gimple_simplify run (where we don't want to build
+ a stmt in case it's used in in-place folding). Replaces
+ RES_OP with a simplified and/or canonicalized result and
+ returns whether any change was made. */
+
+bool
+gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
+ tree (*valueize)(tree))
+{
+ /* No constant folding is defined for four-operand functions. */
+
+ gimple_match_op res_op2 (*res_op);
+ if (gimple_simplify (&res_op2, seq, valueize,
+ res_op->code, res_op->type,
+ res_op->ops[0], res_op->ops[1], res_op->ops[2],
+ res_op->ops[3]))
+ {
+ *res_op = res_op2;
+ return true;
+ }
+
+ return false;
+}
/* If in GIMPLE the operation described by RES_OP should be single-rhs,
build a GENERIC tree for that expression and update RES_OP accordingly. */
@@ -256,7 +282,8 @@ build_call_internal (internal_fn fn, gimple_match_op *res_op)
return gimple_build_call_internal (fn, res_op->num_ops,
res_op->op_or_null (0),
res_op->op_or_null (1),
- res_op->op_or_null (2));
+ res_op->op_or_null (2),
+ res_op->op_or_null (3));
}
/* Push the exploded expression described by RES_OP as a statement to
@@ -343,7 +370,8 @@ maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
new_stmt = gimple_build_call (decl, num_ops,
res_op->op_or_null (0),
res_op->op_or_null (1),
- res_op->op_or_null (2));
+ res_op->op_or_null (2),
+ res_op->op_or_null (3));
}
if (!res)
{
@@ -654,7 +682,7 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
/* ??? This way we can't simplify calls with side-effects. */
if (gimple_call_lhs (stmt) != NULL_TREE
&& gimple_call_num_args (stmt) >= 1
- && gimple_call_num_args (stmt) <= 3)
+ && gimple_call_num_args (stmt) <= 4)
{
bool valueized = false;
combined_fn cfn;
@@ -697,6 +725,9 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
case 3:
return (gimple_resimplify3 (seq, res_op, valueize)
|| valueized);
+ case 4:
+ return (gimple_resimplify4 (seq, res_op, valueize)
+ || valueized);
default:
gcc_unreachable ();
}