arm: Auto-vectorization for MVE: vmin/vmax
authorDennis Zhang <dennis.zh@live.com>
Thu, 22 Oct 2020 00:27:31 +0000 (01:27 +0100)
committerDennis Zhang <dennis.zh@live.com>
Thu, 22 Oct 2020 00:27:31 +0000 (01:27 +0100)
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.

gcc/ChangeLog
gcc/config/arm/mve.md
gcc/config/arm/vec-common.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/simd/mve-vminmax_1.c [new file with mode: 0644]

index d6a326c..59fa1ad 100644 (file)
@@ -1,5 +1,19 @@
 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
        using expression 'mult'.
        (mve_vmulq_f<mode>): Use mult instead of VMULQ_F.
index 764e201..47c34b9 100644 (file)
 ;;
 ;; [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"
index 45db60e..0f117d6 100644 (file)
   [(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")
index eb55a64..304d44c 100644 (file)
@@ -1,5 +1,9 @@
 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.
 
 2020-10-20  Jeff Law  <law@redhat.com>
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vminmax_1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vminmax_1.c
new file mode 100644 (file)
index 0000000..6c8e7d4
--- /dev/null
@@ -0,0 +1,61 @@
+/* { 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 } }  */
+