summaryrefslogtreecommitdiff
path: root/gcc/gimple-match-head.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-07-12 13:01:33 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-07-12 13:01:33 +0000
commitb41d1f6ed753bf7ae7e68f745e50c26ee65b5711 (patch)
treeebae427289293f6e3740a7445a2efd490b062588 /gcc/gimple-match-head.c
parent6a86928d9882c17b7526d657a38cb314fa0aaba6 (diff)
Add IFN_COND_FMA functions
This patch adds conditional equivalents of the IFN_FMA built-in functions. Most of it is just a mechanical extension of the binary stuff. 2018-07-12 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * doc/md.texi (cond_fma, cond_fms, cond_fnma, cond_fnms): Document. * optabs.def (cond_fma_optab, cond_fms_optab, cond_fnma_optab) (cond_fnms_optab): New optabs. * internal-fn.def (COND_FMA, COND_FMS, COND_FNMA, COND_FNMS): New internal functions. (FMA): Use DEF_INTERNAL_FLT_FN rather than DEF_INTERNAL_FLT_FLOATN_FN. * internal-fn.h (get_conditional_internal_fn): Declare. (get_unconditional_internal_fn): Likewise. * internal-fn.c (cond_ternary_direct): New macro. (expand_cond_ternary_optab_fn): Likewise. (direct_cond_ternary_optab_supported_p): Likewise. (FOR_EACH_COND_FN_PAIR): Likewise. (get_conditional_internal_fn): New function. (get_unconditional_internal_fn): Likewise. * gimple-match.h (gimple_match_op::MAX_NUM_OPS): Bump to 5. (gimple_match_op::gimple_match_op): Add a new overload for 5 operands. (gimple_match_op::set_op): Likewise. (gimple_resimplify5): Declare. * genmatch.c (decision_tree::gen): Generate simplifications for 5 operands. * gimple-match-head.c (gimple_simplify): Define an overload for 5 operands. Handle calls with 5 arguments in the top-level overload. (convert_conditional_op): Handle conversions from unconditional internal functions to conditional ones. (gimple_resimplify5): New function. (build_call_internal): Pass a fifth operand. (maybe_push_res_to_seq): Likewise. (try_conditional_simplification): Try converting conditional internal functions to unconditional internal functions. Handle 3-operand unconditional forms. * match.pd (UNCOND_TERNARY, COND_TERNARY): Operator lists. Define ternary equivalents of the current rules for binary conditional internal functions. * config/aarch64/aarch64.c (aarch64_preferred_else_value): Handle ternary operations. * config/aarch64/iterators.md (UNSPEC_COND_FMLA, UNSPEC_COND_FMLS) (UNSPEC_COND_FNMLA, UNSPEC_COND_FNMLS): New unspecs. (optab): Handle them. (SVE_COND_FP_TERNARY): New int iterator. (sve_fmla_op, sve_fmad_op): New int attributes. * config/aarch64/aarch64-sve.md (cond_<optab><mode>) (*cond_<optab><mode>_2, *cond_<optab><mode_4) (*cond_<optab><mode>_any): New SVE_COND_FP_TERNARY patterns. gcc/testsuite/ * gcc.dg/vect/vect-cond-arith-3.c: New test. * gcc.target/aarch64/sve/vcond_13.c: Likewise. * gcc.target/aarch64/sve/vcond_13_run.c: Likewise. * gcc.target/aarch64/sve/vcond_14.c: Likewise. * gcc.target/aarch64/sve/vcond_14_run.c: Likewise. * gcc.target/aarch64/sve/vcond_15.c: Likewise. * gcc.target/aarch64/sve/vcond_15_run.c: Likewise. * gcc.target/aarch64/sve/vcond_16.c: Likewise. * gcc.target/aarch64/sve/vcond_16_run.c: Likewise. From-SVN: r262587
Diffstat (limited to 'gcc/gimple-match-head.c')
-rw-r--r--gcc/gimple-match-head.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index e165a77132b..414007ec1f9 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -54,6 +54,8 @@ 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);
+static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
+ code_helper, tree, tree, tree, tree, tree, tree);
const unsigned int gimple_match_op::MAX_NUM_OPS;
@@ -80,7 +82,12 @@ convert_conditional_op (gimple_match_op *orig_op,
if (orig_op->code.is_tree_code ())
ifn = get_conditional_internal_fn ((tree_code) orig_op->code);
else
- return false;
+ {
+ combined_fn cfn = orig_op->code;
+ if (!internal_fn_p (cfn))
+ return false;
+ ifn = get_conditional_internal_fn (as_internal_fn (cfn));
+ }
if (ifn == IFN_LAST)
return false;
unsigned int num_ops = orig_op->num_ops;
@@ -403,6 +410,34 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
return false;
}
+/* 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_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
+ tree (*valueize)(tree))
+{
+ /* No constant folding is defined for five-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->ops[4]))
+ {
+ *res_op = res_op2;
+ return true;
+ }
+
+ if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+ 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. */
@@ -444,7 +479,8 @@ build_call_internal (internal_fn fn, gimple_match_op *res_op)
res_op->op_or_null (0),
res_op->op_or_null (1),
res_op->op_or_null (2),
- res_op->op_or_null (3));
+ res_op->op_or_null (3),
+ res_op->op_or_null (4));
}
/* Push the exploded expression described by RES_OP as a statement to
@@ -538,7 +574,8 @@ maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
res_op->op_or_null (0),
res_op->op_or_null (1),
res_op->op_or_null (2),
- res_op->op_or_null (3));
+ res_op->op_or_null (3),
+ res_op->op_or_null (4));
}
if (!res)
{
@@ -745,14 +782,22 @@ static bool
try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
gimple_seq *seq, tree (*valueize) (tree))
{
+ code_helper op;
tree_code code = conditional_internal_fn_code (ifn);
- if (code == ERROR_MARK)
- return false;
+ if (code != ERROR_MARK)
+ op = code;
+ else
+ {
+ ifn = get_unconditional_internal_fn (ifn);
+ if (ifn == IFN_LAST)
+ return false;
+ op = as_combined_fn (ifn);
+ }
unsigned int num_ops = res_op->num_ops;
gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
res_op->ops[num_ops - 1]),
- code, res_op->type, num_ops - 2);
+ op, res_op->type, num_ops - 2);
for (unsigned int i = 1; i < num_ops - 1; ++i)
cond_op.ops[i - 1] = res_op->ops[i];
switch (num_ops - 2)
@@ -761,6 +806,10 @@ try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
if (!gimple_resimplify2 (seq, &cond_op, valueize))
return false;
break;
+ case 3:
+ if (!gimple_resimplify3 (seq, &cond_op, valueize))
+ return false;
+ break;
default:
gcc_unreachable ();
}
@@ -893,7 +942,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) <= 4)
+ && gimple_call_num_args (stmt) <= 5)
{
bool valueized = false;
combined_fn cfn;
@@ -943,6 +992,9 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
case 4:
return (gimple_resimplify4 (seq, res_op, valueize)
|| valueized);
+ case 5:
+ return (gimple_resimplify5 (seq, res_op, valueize)
+ || valueized);
default:
gcc_unreachable ();
}