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/internal-fn.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/internal-fn.c')
-rw-r--r-- | gcc/internal-fn.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index eb5493f..474a16b 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 |