This patch enables MVE vmin/vmax instructions for auto-vectorization.
MVE target is included in expander smin<mode>3, umin<mode>3, smax<mode>3
and umax<mode>3 for vectorization. Related insns for vmin/vmax in mve.md
are modified to use smin, umin, smax and umax expressions instead of
unspec to support the expanders.
gcc/ChangeLog:
2020-10-22  Dennis Zhang  <dennis.zhang@arm.com>
	* config/arm/mve.md (mve_vmaxq_<supf><mode>): Replace with ...
	(mve_vmaxq_s<mode>, mve_vmaxq_u<mode>): ... these new insns to
	use smax/umax instead of VMAXQ.
	(mve_vminq_<supf><mode>): Replace with ...
	(mve_vminq_s<mode>, mve_vminq_u<mode>): ... these new insns to
	use smin/umin instead of VMINQ.
	(mve_vmaxnmq_f<mode>): Use smax instead of VMAXNMQ_F.
	(mve_vminnmq_f<mode>): Use smin instead of VMINNMQ_F.
	* config/arm/vec-common.md (smin<mode>3): Use the new mode macros
	ARM_HAVE_<MODE>_ARITH.
	(umin<mode>3, smax<mode>3, umax<mode>3): Likewise.
gcc/testsuite/ChangeLog:
	* gcc.target/arm/simd/mve-vminmax_1.c: New test.
+2020-10-22  Dennis Zhang  <dennis.zhang@arm.com>
+
+       * config/arm/mve.md (mve_vmaxq_<supf><mode>): Replace with ...
+       (mve_vmaxq_s<mode>, mve_vmaxq_u<mode>): ... these new insns to
+       use smax/umax instead of VMAXQ.
+       (mve_vminq_<supf><mode>): Replace with ...
+       (mve_vminq_s<mode>, mve_vminq_u<mode>): ... these new insns to
+       use smin/umin instead of VMINQ.
+       (mve_vmaxnmq_f<mode>): Use smax instead of VMAXNMQ_F.
+       (mve_vminnmq_f<mode>): Use smin instead of VMINNMQ_F.
+       * config/arm/vec-common.md (smin<mode>3): Use the new mode macros
+       ARM_HAVE_<MODE>_ARITH.
+       (umin<mode>3, smax<mode>3, umax<mode>3): Likewise.
+
 2020-10-22  Dennis Zhang  <dennis.zhang@arm.com>
 
        * config/arm/mve.md (mve_vmulq<mode>): New entry for vmul instruction
 
 ;;
 ;; [vmaxq_u, vmaxq_s])
 ;;
-(define_insn "mve_vmaxq_<supf><mode>"
+(define_insn "mve_vmaxq_s<mode>"
   [
    (set (match_operand:MVE_2 0 "s_register_operand" "=w")
-       (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
-                      (match_operand:MVE_2 2 "s_register_operand" "w")]
-        VMAXQ))
+       (smax:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
+                   (match_operand:MVE_2 2 "s_register_operand" "w")))
+  ]
+  "TARGET_HAVE_MVE"
+  "vmax.%#<V_s_elem>\t%q0, %q1, %q2"
+  [(set_attr "type" "mve_move")
+])
+
+(define_insn "mve_vmaxq_u<mode>"
+  [
+   (set (match_operand:MVE_2 0 "s_register_operand" "=w")
+       (umax:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
+                   (match_operand:MVE_2 2 "s_register_operand" "w")))
   ]
   "TARGET_HAVE_MVE"
-  "vmax.<supf>%#<V_sz_elem>\t%q0, %q1, %q2"
+  "vmax.%#<V_u_elem>\t%q0, %q1, %q2"
   [(set_attr "type" "mve_move")
 ])
 
 ;;
 ;; [vminq_s, vminq_u])
 ;;
-(define_insn "mve_vminq_<supf><mode>"
+(define_insn "mve_vminq_s<mode>"
   [
    (set (match_operand:MVE_2 0 "s_register_operand" "=w")
-       (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand" "w")
-                      (match_operand:MVE_2 2 "s_register_operand" "w")]
-        VMINQ))
+       (smin:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
+                   (match_operand:MVE_2 2 "s_register_operand" "w")))
   ]
   "TARGET_HAVE_MVE"
-  "vmin.<supf>%#<V_sz_elem>\t%q0, %q1, %q2"
+  "vmin.%#<V_s_elem>\t%q0, %q1, %q2"
+  [(set_attr "type" "mve_move")
+])
+
+(define_insn "mve_vminq_u<mode>"
+  [
+   (set (match_operand:MVE_2 0 "s_register_operand" "=w")
+       (umin:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w")
+                   (match_operand:MVE_2 2 "s_register_operand" "w")))
+  ]
+  "TARGET_HAVE_MVE"
+  "vmin.%#<V_u_elem>\t%q0, %q1, %q2"
   [(set_attr "type" "mve_move")
 ])
 
 (define_insn "mve_vmaxnmq_f<mode>"
   [
    (set (match_operand:MVE_0 0 "s_register_operand" "=w")
-       (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
-                      (match_operand:MVE_0 2 "s_register_operand" "w")]
-        VMAXNMQ_F))
+       (smax:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")
+                   (match_operand:MVE_0 2 "s_register_operand" "w")))
   ]
   "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
   "vmaxnm.f%#<V_sz_elem>       %q0, %q1, %q2"
 (define_insn "mve_vminnmq_f<mode>"
   [
    (set (match_operand:MVE_0 0 "s_register_operand" "=w")
-       (unspec:MVE_0 [(match_operand:MVE_0 1 "s_register_operand" "w")
-                      (match_operand:MVE_0 2 "s_register_operand" "w")]
-        VMINNMQ_F))
+       (smin:MVE_0 (match_operand:MVE_0 1 "s_register_operand" "w")
+                   (match_operand:MVE_0 2 "s_register_operand" "w")))
   ]
   "TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT"
   "vminnm.f%#<V_sz_elem>       %q0, %q1, %q2"
 
   [(set (match_operand:VALLW 0 "s_register_operand")
        (smin:VALLW (match_operand:VALLW 1 "s_register_operand")
                    (match_operand:VALLW 2 "s_register_operand")))]
-  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
-                   || flag_unsafe_math_optimizations))
-   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
-{
-})
+   "ARM_HAVE_<MODE>_ARITH"
+)
 
 (define_expand "umin<mode>3"
   [(set (match_operand:VINTW 0 "s_register_operand")
        (umin:VINTW (match_operand:VINTW 1 "s_register_operand")
                    (match_operand:VINTW 2 "s_register_operand")))]
-  "TARGET_NEON
-   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
-{
-})
+   "ARM_HAVE_<MODE>_ARITH"
+)
 
 (define_expand "smax<mode>3"
   [(set (match_operand:VALLW 0 "s_register_operand")
        (smax:VALLW (match_operand:VALLW 1 "s_register_operand")
                    (match_operand:VALLW 2 "s_register_operand")))]
-  "(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
-                   || flag_unsafe_math_optimizations))
-   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
-{
-})
+   "ARM_HAVE_<MODE>_ARITH"
+)
 
 (define_expand "umax<mode>3"
   [(set (match_operand:VINTW 0 "s_register_operand")
        (umax:VINTW (match_operand:VINTW 1 "s_register_operand")
                    (match_operand:VINTW 2 "s_register_operand")))]
-  "TARGET_NEON
-   || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
-{
-})
+   "ARM_HAVE_<MODE>_ARITH"
+)
 
 (define_expand "vec_perm<mode>"
   [(match_operand:VE 0 "s_register_operand")
 
+2020-10-22  Dennis Zhang  <dennis.zhang@arm.com>
+
+       * gcc.target/arm/simd/mve-vminmax_1.c: New test.
+
 2020-10-22  Dennis Zhang  <dennis.zhang@arm.com>
 
        * gcc.target/arm/simd/mve-vmul_1.c: New test.
 
--- /dev/null
+/* { dg-do compile }  */
+/* { dg-require-effective-target arm_v8_1m_mve_ok }  */
+/* { dg-options "-O3" }  */
+/* { dg-add-options arm_v8_1m_mve }  */
+
+#include <stdint.h>
+
+#define MAX(a, b) ((a) > (b)) ? (a) : (b)
+#define MIN(a, b) ((a) < (b)) ? (a) : (b)
+
+
+#define TEST_BINOP(OP, TY, N)          \
+  TY test_##OP##_##TY (TY * dest, TY * a, TY * b)      \
+  {                                                    \
+    int i;                                             \
+    for (i=0; i<N; i++)                                        \
+    {                                                  \
+      dest[i] = OP (a[i], b[i]);                       \
+    }                                                  \
+  }
+
+/* Test vmax.  */
+
+TEST_BINOP (MAX, int32_t, 4)
+/* { dg-final { scan-assembler-times {vmax\.s32\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MAX, uint32_t, 4)
+/* { dg-final { scan-assembler-times {vmax\.u32\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MAX, int16_t, 8)
+/* { dg-final { scan-assembler-times {vmax\.s16\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MAX, uint16_t, 8)
+/* { dg-final { scan-assembler-times {vmax\.u16\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MAX, int8_t, 16)
+/* { dg-final { scan-assembler-times {vmax\.s8\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MAX, uint8_t, 16)
+/* { dg-final { scan-assembler-times {vmax\.u8\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+/* Test vmin.  */
+
+TEST_BINOP (MIN, int32_t, 4)
+/* { dg-final { scan-assembler-times {vmin\.s32\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MIN, uint32_t, 4)
+/* { dg-final { scan-assembler-times {vmin\.u32\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MIN, int16_t, 8)
+/* { dg-final { scan-assembler-times {vmin\.s16\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MIN, uint16_t, 8)
+/* { dg-final { scan-assembler-times {vmin\.u16\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MIN, int8_t, 16)
+/* { dg-final { scan-assembler-times {vmin\.s8\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+
+TEST_BINOP (MIN, uint8_t, 16)
+/* { dg-final { scan-assembler-times {vmin\.u8\tq[0-9]+, q[0-9]+, q[0-9]+} 1 } }  */
+