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 make most of PRED_m and PRED_x handling use the same
code.

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.
        (unspec_mve_function_exact_insn_vshl): Likewise.
        (unspec_based_mve_function_exact_insn_vcmp): Initialize new
        inherited members.
        (unspec_mve_function_exact_insn_rot): Merge PRED_m and PRED_x
        handling.
        (unspec_mve_function_exact_insn_vmull): Likewise.
        (unspec_mve_function_exact_insn_vmull_poly): Likewise.
---
 gcc/config/arm/arm-mve-builtins-functions.h | 607 +++++++-------------
 1 file changed, 211 insertions(+), 396 deletions(-)

diff --git a/gcc/config/arm/arm-mve-builtins-functions.h 
b/gcc/config/arm/arm-mve-builtins-functions.h
index ac2a731bff4..43c4aaffeb1 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,142 +104,146 @@ 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;
 };
 
-/* 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
-   rtx_code.  This is useful when the basic operation is mapped to a
-   standard RTX code and all other versions use different unspecs.  */
-class unspec_based_mve_function_exact_insn : public 
unspec_based_mve_function_base
+/* 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
 {
-public:
-  CONSTEXPR unspec_based_mve_function_exact_insn (rtx_code code_for_sint,
-                                                 rtx_code code_for_uint,
-                                                 rtx_code code_for_fp,
-                                                 int unspec_for_n_sint,
-                                                 int unspec_for_n_uint,
-                                                 int unspec_for_n_fp,
-                                                 int unspec_for_m_sint,
-                                                 int unspec_for_m_uint,
-                                                 int unspec_for_m_fp,
-                                                 int unspec_for_m_n_sint,
-                                                 int unspec_for_m_n_uint,
-                                                 int unspec_for_m_n_fp)
-    : unspec_based_mve_function_base (code_for_sint,
-                                     code_for_uint,
-                                     code_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)
-  {}
-
-  rtx
-  expand (function_expander &e) const override
-  {
-    /* No suffix, no predicate, use the right RTX code.  */
-    if ((e.mode_suffix_id != MODE_n)
-       && (e.pred == PRED_none))
-      return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
-                                m_code_for_fp);
-
+    machine_mode mode = e.vector_mode (0);
     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.  */
+           /* No predicate, no suffix.  */
            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));
+               code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, 
mode);
              else
-               code = code_for_mve_q_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, e.vector_mode (0));
+               code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, 
mode);
            else
-             code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0));
+             code = code_for_mve_q_f (m_unspec_for_fp, mode);
            break;
 
          case MODE_n:
-           /* _n suffix, "m" predicate.  */
+           /* No predicate, _n suffix.  */
            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));
+               code = code_for_mve_q_n (m_unspec_for_n_uint, 
m_unspec_for_n_uint, mode);
              else
-               code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, 
m_unspec_for_m_n_sint, e.vector_mode (0));
+               code = code_for_mve_q_n (m_unspec_for_n_sint, 
m_unspec_for_n_sint, mode);
            else
-             code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode 
(0));
+             code = code_for_mve_q_n_f (m_unspec_for_n_fp, mode);
            break;
 
          default:
            gcc_unreachable ();
          }
-       return e.use_cond_insn (code, 0);
+       return e.use_exact_insn (code);
 
+      case PRED_m:
       case PRED_x:
        switch (e.mode_suffix_id)
          {
          case MODE_none:
-           /* No suffix, "x" 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, e.vector_mode (0));
+               code = code_for_mve_q_m (m_unspec_for_m_uint, 
m_unspec_for_m_uint, mode);
              else
-               code = code_for_mve_q_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, e.vector_mode (0));
+               code = code_for_mve_q_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, mode);
            else
-             code = code_for_mve_q_m_f (m_unspec_for_m_fp, e.vector_mode (0));
+             code = code_for_mve_q_m_f (m_unspec_for_m_fp, mode);
            break;
 
          case MODE_n:
-           /* _n suffix, "x" predicate.  */
+           /* _n 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_n (m_unspec_for_m_n_uint, 
m_unspec_for_m_n_uint, e.vector_mode (0));
+               code = code_for_mve_q_m_n (m_unspec_for_m_n_uint, 
m_unspec_for_m_n_uint, mode);
              else
-               code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, 
m_unspec_for_m_n_sint, e.vector_mode (0));
+               code = code_for_mve_q_m_n (m_unspec_for_m_n_sint, 
m_unspec_for_m_n_sint, mode);
            else
-             code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, e.vector_mode 
(0));
+             code = code_for_mve_q_m_n_f (m_unspec_for_m_n_fp, mode);
            break;
 
          default:
            gcc_unreachable ();
          }
-       return e.use_pred_x_insn (code);
+
+       if (e.pred == PRED_m)
+         return e.use_cond_insn (code, 0);
+       else
+         return e.use_pred_x_insn (code);
+       break;
 
       default:
        gcc_unreachable ();
       }
+}
 
-    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
+   rtx_code.  This is useful when the basic operation is mapped to a
+   standard RTX code and all other versions use different unspecs.  */
+class unspec_based_mve_function_exact_insn : public 
unspec_based_mve_function_base
+{
+public:
+  CONSTEXPR unspec_based_mve_function_exact_insn (rtx_code code_for_sint,
+                                                 rtx_code code_for_uint,
+                                                 rtx_code code_for_fp,
+                                                 int unspec_for_n_sint,
+                                                 int unspec_for_n_uint,
+                                                 int unspec_for_n_fp,
+                                                 int unspec_for_m_sint,
+                                                 int unspec_for_m_uint,
+                                                 int unspec_for_m_fp,
+                                                 int unspec_for_m_n_sint,
+                                                 int unspec_for_m_n_uint,
+                                                 int unspec_for_m_n_fp)
+    : 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,
+                                     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)
+  {}
+
+  rtx
+  expand (function_expander &e) const override
+  {
+    /* No suffix, no predicate, use the right RTX code.  */
+    if ((e.mode_suffix_id != MODE_n)
+       && (e.pred == PRED_none))
+      return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
+                                m_code_for_fp);
+
+    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 +258,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 +293,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;
@@ -440,45 +350,30 @@ public:
            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));
+    if (e.pred == PRED_p)
+      {
+       machine_mode mode = e.vector_mode (0);
 
-           return e.use_exact_insn (code);
+       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, 
mode);
+         else
+           code = code_for_mve_q_p (m_unspec_for_p_sint, m_unspec_for_p_sint, 
mode);
+       else
+         code = code_for_mve_q_p_f (m_unspec_for_p_fp, mode);
 
-         default:
-           gcc_unreachable ();
-         }
+       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 +388,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 +420,38 @@ public:
   expand (function_expander &e) const override
   {
     insn_code code;
-    switch (e.pred)
+    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));
+             code = code_for_mve_q_r (m_unspec_for_r_uint, 
m_unspec_for_r_uint, mode);
            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);
+             code = code_for_mve_q_r (m_unspec_for_r_sint, 
m_unspec_for_r_sint, mode);
+           return e.use_exact_insn (code);
 
-      case PRED_x:
-       switch (e.mode_suffix_id)
-         {
-         case MODE_none:
-           /* No suffix, "x" predicate.  */
+         case PRED_m:
+         case PRED_x:
+           /* _r suffix, "m" or "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));
+             code = code_for_mve_q_m_r (m_unspec_for_m_r_uint, 
m_unspec_for_m_r_uint, mode);
            else
-             code = code_for_mve_q_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, e.vector_mode (0));
-           break;
+             code = code_for_mve_q_m_r (m_unspec_for_m_r_sint, 
m_unspec_for_m_r_sint, mode);
 
-         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));
+           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 +471,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,
@@ -738,7 +567,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,6 +600,7 @@ public:
   rtx
   expand (function_expander &e) const override
   {
+    machine_mode mode = e.vector_mode (0);
     insn_code code;
 
     switch (e.pred)
@@ -780,11 +612,11 @@ public:
            /* 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));
+               code = code_for_mve_q (m_unspec_for_uint, m_unspec_for_uint, 
m_unspec_for_uint, mode);
              else
-               code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, 
m_unspec_for_sint, e.vector_mode (0));
+               code = code_for_mve_q (m_unspec_for_sint, m_unspec_for_sint, 
m_unspec_for_sint, 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 +625,28 @@ 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));
+               code = code_for_mve_q_m (m_unspec_for_m_uint, 
m_unspec_for_m_uint, m_unspec_for_m_uint, mode);
              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));
+               code = code_for_mve_q_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, m_unspec_for_m_sint, 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,6 +684,7 @@ public:
   rtx
   expand (function_expander &e) const override
   {
+    machine_mode mode = e.vector_mode (0);
     insn_code code;
 
     if (! e.type_suffix (0).integer_p)
@@ -879,29 +698,24 @@ 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));
+         code = code_for_mve_q_int (m_unspec_for_uint, m_unspec_for_uint, 
mode);
        else
-         code = code_for_mve_q_int (m_unspec_for_sint, m_unspec_for_sint, 
e.vector_mode (0));
+         code = code_for_mve_q_int (m_unspec_for_sint, m_unspec_for_sint, 
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.  */
+       /* No suffix, "m" or "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));
+         code = code_for_mve_q_int_m (m_unspec_for_m_uint, 
m_unspec_for_m_uint, mode);
        else
-         code = code_for_mve_q_int_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, e.vector_mode (0));
+         code = code_for_mve_q_int_m (m_unspec_for_m_sint, 
m_unspec_for_m_sint, mode);
 
-       return e.use_pred_x_insn (code);
+       if (e.pred == PRED_m)
+         return e.use_cond_insn (code, 0);
+       else
+         return e.use_pred_x_insn (code);
 
       default:
        gcc_unreachable ();
@@ -933,6 +747,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 +760,18 @@ public:
       {
       case PRED_none:
        /* No predicate, no suffix.  */
-       code = code_for_mve_q_poly (m_unspec_for_poly, m_unspec_for_poly, 
e.vector_mode (0));
+       code = code_for_mve_q_poly (m_unspec_for_poly, m_unspec_for_poly, mode);
        return e.use_exact_insn (code);
 
       case PRED_m:
-       /* No suffix, "m" predicate.  */
-       code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, 
e.vector_mode (0));
-       return e.use_cond_insn (code, 0);
-
       case PRED_x:
-       /* No suffix, "x" predicate.  */
-       code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, 
e.vector_mode (0));
-       return e.use_pred_x_insn (code);
+       /* No suffix, "m" or "x" predicate.  */
+       code = code_for_mve_q_poly_m (m_unspec_for_m_poly, m_unspec_for_m_poly, 
mode);
+
+       if (e.pred == PRED_m)
+         return e.use_cond_insn (code, 0);
+       else
+         return e.use_pred_x_insn (code);
 
       default:
        gcc_unreachable ();
-- 
2.34.1


Reply via email to