On 04/09/2024 14:26, Christophe Lyon wrote: > 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.
OK. R. > --- > 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 ();