aboutsummaryrefslogtreecommitdiff
path: root/gcc/internal-fn.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-07-12 13:01:33 +0000
committerRichard Sandiford <richard.sandiford@linaro.org>2018-07-12 13:01:33 +0000
commit3d131ceb7f5c3a5d68d9deacfe375dc7dddfb3db (patch)
treeebae427289293f6e3740a7445a2efd490b062588 /gcc/internal-fn.c
parent8e7d5f9a6ad8162bde1479600b63ec5b2ab3928e (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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@262587 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r--gcc/internal-fn.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index eb5493fcd81..474a16bc6fb 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -113,6 +113,7 @@ init_internal_fns ()
#define ternary_direct { 0, 0, true }
#define cond_unary_direct { 1, 1, true }
#define cond_binary_direct { 1, 1, true }
+#define cond_ternary_direct { 1, 1, true }
#define while_direct { 0, 2, false }
#define fold_extract_direct { 2, 2, false }
#define fold_left_direct { 1, 1, false }
@@ -2993,6 +2994,9 @@ expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
#define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
expand_direct_optab_fn (FN, STMT, OPTAB, 4)
+#define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
+ expand_direct_optab_fn (FN, STMT, OPTAB, 5)
+
#define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
expand_direct_optab_fn (FN, STMT, OPTAB, 3)
@@ -3075,6 +3079,7 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
#define direct_ternary_optab_supported_p direct_optab_supported_p
#define direct_cond_unary_optab_supported_p direct_optab_supported_p
#define direct_cond_binary_optab_supported_p direct_optab_supported_p
+#define direct_cond_ternary_optab_supported_p direct_optab_supported_p
#define direct_mask_load_optab_supported_p direct_optab_supported_p
#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
#define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
@@ -3277,6 +3282,57 @@ conditional_internal_fn_code (internal_fn ifn)
}
}
+/* Invoke T(IFN) for each internal function IFN that also has an
+ IFN_COND_* form. */
+#define FOR_EACH_COND_FN_PAIR(T) \
+ T (FMA) \
+ T (FMS) \
+ T (FNMA) \
+ T (FNMS)
+
+/* Return a function that only performs internal function FN when a
+ certain condition is met and that uses a given fallback value otherwise.
+ In other words, the returned function FN' is such that:
+
+ LHS = FN' (COND, A1, ... An, ELSE)
+
+ is equivalent to the C expression:
+
+ LHS = COND ? FN (A1, ..., An) : ELSE;
+
+ operating elementwise if the operands are vectors.
+
+ Return IFN_LAST if no such function exists. */
+
+internal_fn
+get_conditional_internal_fn (internal_fn fn)
+{
+ switch (fn)
+ {
+#define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
+ FOR_EACH_COND_FN_PAIR(CASE)
+#undef CASE
+ default:
+ return IFN_LAST;
+ }
+}
+
+/* If IFN implements the conditional form of an unconditional internal
+ function, return that unconditional function, otherwise return IFN_LAST. */
+
+internal_fn
+get_unconditional_internal_fn (internal_fn ifn)
+{
+ switch (ifn)
+ {
+#define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
+ FOR_EACH_COND_FN_PAIR(CASE)
+#undef CASE
+ default:
+ return IFN_LAST;
+ }
+}
+
/* Return true if IFN is some form of load from memory. */
bool