Message ID | 20240904132650.2720446-4-christophe.lyon@linaro.org |
---|---|
State | New |
Headers | show |
Series | arm: [MVE intrinsics] Re-implement more intrinsics | expand |
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.lyon@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 ();
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 ();