This patch brings no functional change but removes some code duplication in arm-mve-builtins-functions.h and makes it easier to read and maintain.
It introduces a new expand_unspec () member of unspec_based_mve_function_base and makes a few classes inherit from it instead of function_base. This adds 3 new members containing the unspec codes for signed-int, unsigned-int and floating-point intrinsics (no mode, no predicate). Depending on the derived class, these will be used instead of the 3 similar RTX codes. The new expand_unspec () handles all the possible unspecs, some of which maybe not be supported by a given intrinsics family: such code paths won't be used in that case. Similarly, codes specific to a family (RTX, or PRED_p for instance) should be handled by the caller of expand_unspec (). Thanks to this, expand () for unspec_based_mve_function_exact_insn, unspec_mve_function_exact_insn, unspec_mve_function_exact_insn_pred_p, unspec_mve_function_exact_insn_vshl no longer duplicate a lot of code. The patch also makes most of PRED_m and PRED_x handling use the same code, and uses conditional operators when computing which RTX code/unspec to use when calling code_for_mve_q_XXX. 2024-07-11 Christophe Lyon <christophe.l...@linaro.org> gcc/ * config/arm/arm-mve-builtins-functions.h (unspec_based_mve_function_base): Add m_unspec_for_sint, m_unspec_for_uint, m_unspec_for_fp and expand_unspec members. (unspec_based_mve_function_exact_insn): Inherit from unspec_based_mve_function_base and use expand_unspec. (unspec_mve_function_exact_insn): Likewise. (unspec_mve_function_exact_insn_pred_p): Likewise. Use conditionals. (unspec_mve_function_exact_insn_vshl): Likewise. (unspec_based_mve_function_exact_insn_vcmp): Initialize new inherited members. Use conditionals. (unspec_mve_function_exact_insn_rot): Merge PRED_m and PRED_x handling. Use conditionals. (unspec_mve_function_exact_insn_vmull): Likewise. (unspec_mve_function_exact_insn_vmull_poly): Likewise. --- gcc/config/arm/arm-mve-builtins-functions.h | 726 ++++++++------------ 1 file changed, 286 insertions(+), 440 deletions(-) diff --git a/gcc/config/arm/arm-mve-builtins-functions.h b/gcc/config/arm/arm-mve-builtins-functions.h index ac2a731bff4..35cb5242b77 100644 --- a/gcc/config/arm/arm-mve-builtins-functions.h +++ b/gcc/config/arm/arm-mve-builtins-functions.h @@ -40,17 +40,23 @@ public: }; /* An incomplete function_base for functions that have an associated - rtx_code for signed integers, unsigned integers and floating-point - values for the non-predicated, non-suffixed intrinsic, and unspec - codes, with separate codes for signed integers, unsigned integers - and floating-point values. The class simply records information - about the mapping for derived classes to use. */ + rtx_code or an unspec for signed integers, unsigned integers and + floating-point values for the non-predicated, non-suffixed + intrinsics, and unspec codes, with separate codes for signed + integers, unsigned integers and floating-point values for + predicated and/or suffixed intrinsics. The class simply records + information about the mapping for derived classes to use and + provides a generic expand_unspec () to avoid duplicating expansion + code in derived classes. */ class unspec_based_mve_function_base : public function_base { public: CONSTEXPR unspec_based_mve_function_base (rtx_code code_for_sint, rtx_code code_for_uint, rtx_code code_for_fp, + int unspec_for_sint, + int unspec_for_uint, + int unspec_for_fp, int unspec_for_n_sint, int unspec_for_n_uint, int unspec_for_n_fp, @@ -63,6 +69,9 @@ public: : m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint), m_code_for_fp (code_for_fp), + m_unspec_for_sint (unspec_for_sint), + m_unspec_for_uint (unspec_for_uint), + m_unspec_for_fp (unspec_for_fp), m_unspec_for_n_sint (unspec_for_n_sint), m_unspec_for_n_uint (unspec_for_n_uint), m_unspec_for_n_fp (unspec_for_n_fp), @@ -83,6 +92,9 @@ public: /* The unspec code associated with signed-integer, unsigned-integer and floating-point operations respectively. It covers the cases with the _n suffix, and/or the _m predicate. */ + int m_unspec_for_sint; + int m_unspec_for_uint; + int m_unspec_for_fp; int m_unspec_for_n_sint; int m_unspec_for_n_uint; int m_unspec_for_n_fp; @@ -92,8 +104,101 @@ public: int m_unspec_for_m_n_sint; int m_unspec_for_m_n_uint; int m_unspec_for_m_n_fp; + + rtx expand_unspec (function_expander &e) const; }; +/* Expand the unspecs, which is common to all intrinsics using + unspec_based_mve_function_base. If some combinations are not + supported for an intrinsics family, they should be handled by the + caller (and not crash here). */ +rtx +unspec_based_mve_function_base::expand_unspec (function_expander &e) const +{ + machine_mode mode = e.vector_mode (0); + insn_code code; + + switch (e.pred) + { + case PRED_none: + switch (e.mode_suffix_id) + { + case MODE_none: + /* No predicate, no suffix. */ + if (e.type_suffix (0).integer_p) + { + int unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_uint + : m_unspec_for_sint); + code = code_for_mve_q (unspec, unspec, mode); + } + else + code = code_for_mve_q_f (m_unspec_for_fp, mode); + break; + + case MODE_n: + /* No predicate, _n suffix. */ + if (e.type_suffix (0).integer_p) + { + int unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_n_uint + : m_unspec_for_n_sint); + code = code_for_mve_q_n (unspec, unspec, mode); + } + else + code = code_for_mve_q_n_f (m_unspec_for_n_fp, mode); + break; + + default: + gcc_unreachable (); + } + return e.use_exact_insn (code); + + case PRED_m: + case PRED_x: + switch (e.mode_suffix_id) + { + case MODE_none: + /* No suffix, "m" or "x" predicate. */ + if (e.type_suffix (0).integer_p) + { + int unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_uint + : m_unspec_for_m_sint); + code = code_for_mve_q_m (unspec, unspec, mode); + } + else + code = code_for_mve_q_m_f (m_unspec_for_m_fp, mode); + break; + + case MODE_n: + /* _n suffix, "m" or "x" predicate. */ + if (e.type_suffix (0).integer_p) + { + int unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_n_uint + : m_unspec_for_m_n_sint); + code = code_for_mve_q_m_n (unspec, unspec, mode); + } + else + code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, mode); + break; + + default: + gcc_unreachable (); + } + + if (e.pred == PRED_m) + return e.use_cond_insn (code, 0); + else + return e.use_pred_x_insn (code); + break; + + default: + gcc_unreachable (); + } +} + /* Map the function directly to CODE (UNSPEC, M) where M is the vector mode associated with type suffix 0, except when there is no predicate and no _n suffix, in which case we use the appropriate @@ -117,6 +222,9 @@ public: : unspec_based_mve_function_base (code_for_sint, code_for_uint, code_for_fp, + -1, + -1, + -1, unspec_for_n_sint, unspec_for_n_uint, unspec_for_n_fp, @@ -137,97 +245,13 @@ public: return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint, m_code_for_fp); - insn_code code; - switch (e.pred) - { - case PRED_none: - if (e.mode_suffix_id == MODE_n) - /* No predicate, _n suffix. */ - { - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_n (m_unspec_for_n_uint, m_unspec_for_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_n (m_unspec_for_n_sint, m_unspec_for_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_n_f (m_unspec_for_n_fp, e.vector_mode (0)); - - return e.use_exact_insn (code); - } - gcc_unreachable (); - break; - - case PRED_m: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "m" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0)); - break; - - case MODE_n: - /* _n suffix, "m" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_cond_insn (code, 0); - - case PRED_x: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "x" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0)); - break; - - case MODE_n: - /* _n suffix, "x" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_pred_x_insn (code); - - default: - gcc_unreachable (); - } - - gcc_unreachable (); + return expand_unspec (e); } }; /* Map the function directly to CODE (UNSPEC, M) where M is the vector mode associated with type suffix 0. */ -class unspec_mve_function_exact_insn : public function_base +class unspec_mve_function_exact_insn : public unspec_based_mve_function_base { public: CONSTEXPR unspec_mve_function_exact_insn (int unspec_for_sint, @@ -242,143 +266,33 @@ public: int unspec_for_m_n_sint, int unspec_for_m_n_uint, int unspec_for_m_n_fp) - : m_unspec_for_sint (unspec_for_sint), - m_unspec_for_uint (unspec_for_uint), - m_unspec_for_fp (unspec_for_fp), - m_unspec_for_n_sint (unspec_for_n_sint), - m_unspec_for_n_uint (unspec_for_n_uint), - m_unspec_for_n_fp (unspec_for_n_fp), - m_unspec_for_m_sint (unspec_for_m_sint), - m_unspec_for_m_uint (unspec_for_m_uint), - m_unspec_for_m_fp (unspec_for_m_fp), - m_unspec_for_m_n_sint (unspec_for_m_n_sint), - m_unspec_for_m_n_uint (unspec_for_m_n_uint), - m_unspec_for_m_n_fp (unspec_for_m_n_fp) + : unspec_based_mve_function_base (UNKNOWN, + UNKNOWN, + UNKNOWN, + unspec_for_sint, + unspec_for_uint, + unspec_for_fp, + unspec_for_n_sint, + unspec_for_n_uint, + unspec_for_n_fp, + unspec_for_m_sint, + unspec_for_m_uint, + unspec_for_m_fp, + unspec_for_m_n_sint, + unspec_for_m_n_uint, + unspec_for_m_n_fp) {} - /* The unspec code associated with signed-integer, unsigned-integer - and floating-point operations respectively. It covers the cases - with the _n suffix, and/or the _m predicate. */ - int m_unspec_for_sint; - int m_unspec_for_uint; - int m_unspec_for_fp; - int m_unspec_for_n_sint; - int m_unspec_for_n_uint; - int m_unspec_for_n_fp; - int m_unspec_for_m_sint; - int m_unspec_for_m_uint; - int m_unspec_for_m_fp; - int m_unspec_for_m_n_sint; - int m_unspec_for_m_n_uint; - int m_unspec_for_m_n_fp; - rtx expand (function_expander &e) const override { - insn_code code; - switch (e.pred) - { - case PRED_none: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No predicate, no suffix. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, e.vector_mode (0)); - else - code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, e.vector_mode (0)); - else - code = code_for_mve_q_f (m_unspec_for_fp, e.vector_mode (0)); - break; - - case MODE_n: - /* No predicate, _n suffix. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_n (m_unspec_for_n_uint, m_unspec_for_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_n (m_unspec_for_n_sint, m_unspec_for_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_n_f (m_unspec_for_n_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_exact_insn (code); - - case PRED_m: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "m" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0)); - break; - - case MODE_n: - /* _n suffix, "m" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_cond_insn (code, 0); - - case PRED_x: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "x" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0)); - break; - - case MODE_n: - /* _n suffix, "x" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_pred_x_insn (code); - - default: - gcc_unreachable (); - } - - gcc_unreachable (); + return expand_unspec (e); } }; /* Map the function directly to CODE (UNSPEC), when there is a non-predicated version and one with the "_p" predicate. */ -class unspec_mve_function_exact_insn_pred_p : public function_base +class unspec_mve_function_exact_insn_pred_p : public unspec_based_mve_function_base { public: CONSTEXPR unspec_mve_function_exact_insn_pred_p (int unspec_for_sint, @@ -387,19 +301,23 @@ public: int unspec_for_p_sint, int unspec_for_p_uint, int unspec_for_p_fp) - : m_unspec_for_sint (unspec_for_sint), - m_unspec_for_uint (unspec_for_uint), - m_unspec_for_fp (unspec_for_fp), + : unspec_based_mve_function_base (UNKNOWN, /* No RTX code. */ + UNKNOWN, + UNKNOWN, + unspec_for_sint, + unspec_for_uint, + unspec_for_fp, + -1, -1, -1, /* No _n intrinsics. */ + -1, -1, -1, /* No _m intrinsics. */ + -1, -1, -1), /* No _m_n intrinsics. */ m_unspec_for_p_sint (unspec_for_p_sint), m_unspec_for_p_uint (unspec_for_p_uint), m_unspec_for_p_fp (unspec_for_p_fp) {} - /* The unspec code associated with signed-integer and unsigned-integer - operations, with no predicate, or with "_p" predicate. */ - int m_unspec_for_sint; - int m_unspec_for_uint; - int m_unspec_for_fp; + /* The unspec code associated with signed-integer and + unsigned-integer or floating-point operations with "_p" + predicate. */ int m_unspec_for_p_sint; int m_unspec_for_p_uint; int m_unspec_for_p_fp; @@ -408,6 +326,7 @@ public: expand (function_expander &e) const override { insn_code code; + int unspec; if (m_unspec_for_sint == VADDLVQ_S || m_unspec_for_sint == VADDLVAQ_S @@ -423,62 +342,49 @@ public: switch (e.pred) { case PRED_none: - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_v4si (m_unspec_for_uint, m_unspec_for_uint); - else - code = code_for_mve_q_v4si (m_unspec_for_sint, m_unspec_for_sint); + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_uint + : m_unspec_for_sint); + code = code_for_mve_q_v4si (unspec, unspec); return e.use_exact_insn (code); case PRED_p: - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_p_v4si (m_unspec_for_p_uint, m_unspec_for_p_uint); - else - code = code_for_mve_q_p_v4si (m_unspec_for_p_sint, m_unspec_for_p_sint); + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_p_uint + : m_unspec_for_p_sint); + code = code_for_mve_q_p_v4si (unspec, unspec); return e.use_exact_insn (code); default: gcc_unreachable (); } } - else - { - switch (e.pred) - { - case PRED_none: - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, e.vector_mode (0)); - else - code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, e.vector_mode (0)); - else - code = code_for_mve_q_f (m_unspec_for_fp, e.vector_mode (0)); - - return e.use_exact_insn (code); - case PRED_p: - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_p (m_unspec_for_p_uint, m_unspec_for_p_uint, e.vector_mode (0)); - else - code = code_for_mve_q_p (m_unspec_for_p_sint, m_unspec_for_p_sint, e.vector_mode (0)); - else - code = code_for_mve_q_p_f (m_unspec_for_p_fp, e.vector_mode (0)); - - return e.use_exact_insn (code); + if (e.pred == PRED_p) + { + machine_mode mode = e.vector_mode (0); - default: - gcc_unreachable (); + if (e.type_suffix (0).integer_p) + { + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_p_uint + : m_unspec_for_p_sint); + code = code_for_mve_q_p (unspec, unspec, mode); } + else + code = code_for_mve_q_p_f (m_unspec_for_p_fp, mode); + + return e.use_exact_insn (code); } - gcc_unreachable (); + return expand_unspec (e); } }; /* Map the function directly to CODE (UNSPEC, M) for vshl-like builtins. The difference with unspec_mve_function_exact_insn is that this function handles MODE_r and the related unspecs.. */ -class unspec_mve_function_exact_insn_vshl : public function_base +class unspec_mve_function_exact_insn_vshl : public unspec_based_mve_function_base { public: CONSTEXPR unspec_mve_function_exact_insn_vshl (int unspec_for_sint, @@ -493,31 +399,29 @@ public: int unspec_for_m_r_uint, int unspec_for_r_sint, int unspec_for_r_uint) - : m_unspec_for_sint (unspec_for_sint), - m_unspec_for_uint (unspec_for_uint), - m_unspec_for_n_sint (unspec_for_n_sint), - m_unspec_for_n_uint (unspec_for_n_uint), - m_unspec_for_m_sint (unspec_for_m_sint), - m_unspec_for_m_uint (unspec_for_m_uint), - m_unspec_for_m_n_sint (unspec_for_m_n_sint), - m_unspec_for_m_n_uint (unspec_for_m_n_uint), + : unspec_based_mve_function_base (UNKNOWN, + UNKNOWN, + UNKNOWN, + unspec_for_sint, + unspec_for_uint, + -1, + unspec_for_n_sint, + unspec_for_n_uint, + -1, + unspec_for_m_sint, + unspec_for_m_uint, + -1, + unspec_for_m_n_sint, + unspec_for_m_n_uint, + -1), m_unspec_for_m_r_sint (unspec_for_m_r_sint), m_unspec_for_m_r_uint (unspec_for_m_r_uint), m_unspec_for_r_sint (unspec_for_r_sint), m_unspec_for_r_uint (unspec_for_r_uint) {} - /* The unspec code associated with signed-integer, unsigned-integer - and floating-point operations respectively. It covers the cases - with the _n suffix, and/or the _m predicate. */ - int m_unspec_for_sint; - int m_unspec_for_uint; - int m_unspec_for_n_sint; - int m_unspec_for_n_uint; - int m_unspec_for_m_sint; - int m_unspec_for_m_uint; - int m_unspec_for_m_n_sint; - int m_unspec_for_m_n_uint; + /* The unspec code associated with signed-integer and unsigned-integer + operations with MODE_r with or without PRED_m. */ int m_unspec_for_m_r_sint; int m_unspec_for_m_r_uint; int m_unspec_for_r_sint; @@ -527,101 +431,40 @@ public: expand (function_expander &e) const override { insn_code code; - switch (e.pred) + int unspec; + + if (e.mode_suffix_id == MODE_r) { - case PRED_none: - switch (e.mode_suffix_id) + machine_mode mode = e.vector_mode (0); + switch (e.pred) { - case MODE_none: - /* No predicate, no suffix. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, e.vector_mode (0)); - else - code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, e.vector_mode (0)); - break; - - case MODE_n: - /* No predicate, _n suffix. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_n (m_unspec_for_n_uint, m_unspec_for_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_n (m_unspec_for_n_sint, m_unspec_for_n_sint, e.vector_mode (0)); - break; - - case MODE_r: + case PRED_none: /* No predicate, _r suffix. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_r (m_unspec_for_r_uint, m_unspec_for_r_uint, e.vector_mode (0)); - else - code = code_for_mve_q_r (m_unspec_for_r_sint, m_unspec_for_r_sint, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_exact_insn (code); - - case PRED_m: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "m" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - break; - - case MODE_n: - /* _n suffix, "m" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - break; - - case MODE_r: - /* _r suffix, "m" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_r (m_unspec_for_m_r_uint, m_unspec_for_m_r_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m_r (m_unspec_for_m_r_sint, m_unspec_for_m_r_sint, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_cond_insn (code, 0); - - case PRED_x: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "x" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - break; + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_r_uint + : m_unspec_for_r_sint); + code = code_for_mve_q_r (unspec, unspec, mode); + return e.use_exact_insn (code); - case MODE_n: - /* _n suffix, "x" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, e.vector_mode (0)); + case PRED_m: + case PRED_x: + /* _r suffix, "m" or "x" predicate. */ + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_r_uint + : m_unspec_for_m_r_sint); + code = code_for_mve_q_m_r (unspec, unspec, mode); + + if (e.pred == PRED_m) + return e.use_cond_insn (code, 0); else - code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, e.vector_mode (0)); - break; + return e.use_pred_x_insn (code); default: gcc_unreachable (); } - return e.use_pred_x_insn (code); - - default: - gcc_unreachable (); } - gcc_unreachable (); + return expand_unspec (e); } }; @@ -641,9 +484,8 @@ public: : unspec_based_mve_function_base (code_for_sint, code_for_uint, code_for_fp, - -1, - -1, - -1, + -1, -1, -1, /* No non-predicated, no mode intrinsics. */ + -1, -1, -1, /* No _n intrinsics. */ unspec_for_m_sint, unspec_for_m_uint, unspec_for_m_fp, @@ -662,24 +504,30 @@ public: /* No suffix, no predicate, use the right RTX code. */ if (e.pred == PRED_none) { + rtx_code r_code; + switch (e.mode_suffix_id) { case MODE_none: if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_vcmpq (m_code_for_uint, mode); - else - code = code_for_mve_vcmpq (m_code_for_sint, mode); + { + r_code = (e.type_suffix (0).unsigned_p + ? m_code_for_uint + : m_code_for_sint); + code = code_for_mve_vcmpq (r_code, mode); + } else code = code_for_mve_vcmpq_f (m_code_for_fp, mode); break; case MODE_n: if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_vcmpq_n (m_code_for_uint, mode); - else - code = code_for_mve_vcmpq_n (m_code_for_sint, mode); + { + r_code = (e.type_suffix (0).unsigned_p + ? m_code_for_uint + : m_code_for_sint); + code = code_for_mve_vcmpq_n (r_code, mode); + } else code = code_for_mve_vcmpq_n_f (m_code_for_fp, mode); break; @@ -691,6 +539,8 @@ public: } else { + int unspec; + switch (e.pred) { case PRED_m: @@ -699,10 +549,12 @@ public: case MODE_none: /* No suffix, "m" predicate. */ if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_vcmpq_m (m_unspec_for_m_uint, m_unspec_for_m_uint, mode); - else - code = code_for_mve_vcmpq_m (m_unspec_for_m_sint, m_unspec_for_m_sint, mode); + { + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_uint + : m_unspec_for_m_sint); + code = code_for_mve_vcmpq_m (unspec, unspec, mode); + } else code = code_for_mve_vcmpq_m_f (m_unspec_for_m_fp, mode); break; @@ -710,10 +562,12 @@ public: case MODE_n: /* _n suffix, "m" predicate. */ if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_vcmpq_m_n (m_unspec_for_m_n_uint, m_unspec_for_m_n_uint, mode); - else - code = code_for_mve_vcmpq_m_n (m_unspec_for_m_n_sint, m_unspec_for_m_n_sint, mode); + { + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_n_uint + : m_unspec_for_m_n_sint); + code = code_for_mve_vcmpq_m_n (unspec, unspec, mode); + } else code = code_for_mve_vcmpq_m_n_f (m_unspec_for_m_n_fp, mode); break; @@ -738,7 +592,9 @@ public: /* Map the function directly to CODE (UNSPEC, UNSPEC, UNSPEC, M) where M is the vector mode associated with type suffix 0. USed for the operations where there is a "rot90" or "rot270" suffix, depending - on the UNSPEC. */ + on the UNSPEC. We cannot use + unspec_based_mve_function_base::expand_unspec () because we call + code_for_mve_q with one more parameter. */ class unspec_mve_function_exact_insn_rot : public function_base { public: @@ -769,7 +625,9 @@ public: rtx expand (function_expander &e) const override { + machine_mode mode = e.vector_mode (0); insn_code code; + int unspec; switch (e.pred) { @@ -779,12 +637,14 @@ public: case MODE_none: /* No predicate, no suffix. */ if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, m_unspec_for_uint, e.vector_mode (0)); - else - code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, m_unspec_for_sint, e.vector_mode (0)); + { + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_uint + : m_unspec_for_sint); + code = code_for_mve_q (unspec, unspec, unspec, mode); + } else - code = code_for_mve_q_f (m_unspec_for_fp, m_unspec_for_fp, e.vector_mode (0)); + code = code_for_mve_q_f (m_unspec_for_fp, m_unspec_for_fp, mode); break; default: @@ -793,42 +653,30 @@ public: return e.use_exact_insn (code); case PRED_m: + case PRED_x: switch (e.mode_suffix_id) { case MODE_none: - /* No suffix, "m" predicate. */ + /* No suffix, "m" or "x" predicate. */ if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); + { + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_uint + : m_unspec_for_m_sint); + code = code_for_mve_q_m (unspec, unspec, unspec, mode); + } else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, m_unspec_for_m_fp, e.vector_mode (0)); - break; - - default: - gcc_unreachable (); - } - return e.use_cond_insn (code, 0); + code = code_for_mve_q_m_f (m_unspec_for_m_fp, m_unspec_for_m_fp, mode); - case PRED_x: - switch (e.mode_suffix_id) - { - case MODE_none: - /* No suffix, "x" predicate. */ - if (e.type_suffix (0).integer_p) - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_m (m_unspec_for_m_uint, m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_m (m_unspec_for_m_sint, m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); + if (e.pred == PRED_m) + return e.use_cond_insn (code, 0); else - code = code_for_mve_q_m_f (m_unspec_for_m_fp, m_unspec_for_m_fp, e.vector_mode (0)); + return e.use_pred_x_insn (code); break; default: gcc_unreachable (); } - return e.use_pred_x_insn (code); default: gcc_unreachable (); @@ -866,7 +714,9 @@ public: rtx expand (function_expander &e) const override { + machine_mode mode = e.vector_mode (0); insn_code code; + int unspec; if (! e.type_suffix (0).integer_p) gcc_unreachable (); @@ -878,30 +728,25 @@ public: { case PRED_none: /* No predicate, no suffix. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_int (m_unspec_for_uint, m_unspec_for_uint, e.vector_mode (0)); - else - code = code_for_mve_q_int (m_unspec_for_sint, m_unspec_for_sint, e.vector_mode (0)); + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_uint + : m_unspec_for_sint); + code = code_for_mve_q_int (unspec, unspec, mode); return e.use_exact_insn (code); case PRED_m: - /* No suffix, "m" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_int_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); - else - code = code_for_mve_q_int_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - - return e.use_cond_insn (code, 0); - case PRED_x: - /* No suffix, "x" predicate. */ - if (e.type_suffix (0).unsigned_p) - code = code_for_mve_q_int_m (m_unspec_for_m_uint, m_unspec_for_m_uint, e.vector_mode (0)); + /* No suffix, "m" or "x" predicate. */ + unspec = (e.type_suffix (0).unsigned_p + ? m_unspec_for_m_uint + : m_unspec_for_m_sint); + code = code_for_mve_q_int_m (unspec, unspec, mode); + + if (e.pred == PRED_m) + return e.use_cond_insn (code, 0); else - code = code_for_mve_q_int_m (m_unspec_for_m_sint, m_unspec_for_m_sint, e.vector_mode (0)); - - return e.use_pred_x_insn (code); + return e.use_pred_x_insn (code); default: gcc_unreachable (); @@ -933,6 +778,7 @@ public: rtx expand (function_expander &e) const override { + machine_mode mode = e.vector_mode (0); insn_code code; if (e.mode_suffix_id != MODE_none) @@ -945,18 +791,18 @@ public: { case PRED_none: /* No predicate, no suffix. */ - code = code_for_mve_q_poly (m_unspec_for_poly, m_unspec_for_poly, e.vector_mode (0)); + code = code_for_mve_q_poly (m_unspec_for_poly, m_unspec_for_poly, mode); return e.use_exact_insn (code); case PRED_m: - /* No suffix, "m" predicate. */ - code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, e.vector_mode (0)); - return e.use_cond_insn (code, 0); - case PRED_x: - /* No suffix, "x" predicate. */ - code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, e.vector_mode (0)); - return e.use_pred_x_insn (code); + /* No suffix, "m" or "x" predicate. */ + code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, mode); + + if (e.pred == PRED_m) + return e.use_cond_insn (code, 0); + else + return e.use_pred_x_insn (code); default: gcc_unreachable (); -- 2.34.1