This patch brings no functional change but removes some code
duplication in arm-mve-builtins-functions.h and makes it easier to
read and maintain.
It introduces a new expand_unspec () member of
unspec_based_mve_function_base and makes a few classes inherit from it
instead of function_base.

This adds 3 new members containing the unspec codes for signed-int,
unsigned-int and floating-point intrinsics (no mode, no predicate).
Depending on the derived class, these will be used instead of the 3
similar RTX codes.

The new expand_unspec () handles all the possible unspecs, some of
which maybe not be supported by a given intrinsics family: such code
paths won't be used in that case.  Similarly, codes specific to a
family (RTX, or PRED_p for instance) should be handled by the caller
of expand_unspec ().

Thanks to this, expand () for unspec_based_mve_function_exact_insn,
unspec_mve_function_exact_insn, unspec_mve_function_exact_insn_pred_p,
unspec_mve_function_exact_insn_vshl no longer duplicate a lot of code.

The patch also makes most of PRED_m and PRED_x handling use the same
code, and uses conditional operators when computing which RTX
code/unspec to use when calling code_for_mve_q_XXX.

2024-07-11  Christophe Lyon  <christophe.l...@linaro.org>

        gcc/
        * config/arm/arm-mve-builtins-functions.h
        (unspec_based_mve_function_base): Add m_unspec_for_sint,
        m_unspec_for_uint, m_unspec_for_fp and expand_unspec members.
        (unspec_based_mve_function_exact_insn): Inherit from
        unspec_based_mve_function_base and use expand_unspec.
        (unspec_mve_function_exact_insn): Likewise.
        (unspec_mve_function_exact_insn_pred_p): Likewise.  Use
        conditionals.
        (unspec_mve_function_exact_insn_vshl): Likewise.
        (unspec_based_mve_function_exact_insn_vcmp): Initialize new
        inherited members.  Use conditionals.
        (unspec_mve_function_exact_insn_rot): Merge PRED_m and PRED_x
        handling.  Use conditionals.
        (unspec_mve_function_exact_insn_vmull): Likewise.
        (unspec_mve_function_exact_insn_vmull_poly): Likewise.
---
 gcc/config/arm/arm-mve-builtins-functions.h | 726 ++++++++------------
 1 file changed, 286 insertions(+), 440 deletions(-)

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

Reply via email to