diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2018-07-12 13:01:33 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-07-12 13:01:33 +0000 |
commit | b41d1f6ed753bf7ae7e68f745e50c26ee65b5711 (patch) | |
tree | ebae427289293f6e3740a7445a2efd490b062588 /gcc/gimple-match-head.c | |
parent | 6a86928d9882c17b7526d657a38cb314fa0aaba6 (diff) | |
download | gcc-b41d1f6ed753bf7ae7e68f745e50c26ee65b5711.zip gcc-b41d1f6ed753bf7ae7e68f745e50c26ee65b5711.tar.gz gcc-b41d1f6ed753bf7ae7e68f745e50c26ee65b5711.tar.bz2 |
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.c | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index e165a77..414007e 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 (); } |