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 ();


Reply via email to