[gcc(refs/users/clyon/heads/mve-autovec)] arm: MVE vcmp auto-vectorization

Christophe Lyon clyon@gcc.gnu.org
Mon Mar 1 22:00:47 GMT 2021


https://gcc.gnu.org/g:926004d51d97e6a1044468cfb7cd5426493e13d5

commit 926004d51d97e6a1044468cfb7cd5426493e13d5
Author: Christophe Lyon <christophe.lyon@linaro.org>
Date:   Mon Mar 1 16:54:24 2021 +0000

    arm: MVE vcmp auto-vectorization

Diff:
---
 gcc/config/arm/arm.c                         |  7 ++--
 gcc/config/arm/neon.md                       | 13 -------
 gcc/config/arm/vec-common.md                 | 18 ++++++++++
 gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c | 53 ++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 15 deletions(-)

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f3424800f24..8f7843a973f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -31038,8 +31038,11 @@ arm_expand_vcond (rtx *operands, machine_mode cmp_result_mode)
 					     operands[4], operands[5], true);
   if (inverted)
     std::swap (operands[1], operands[2]);
-  emit_insn (gen_neon_vbsl (GET_MODE (operands[0]), operands[0],
-			    mask, operands[1], operands[2]));
+  if (TARGET_NEON)
+    emit_insn (gen_neon_vbsl (GET_MODE (operands[0]), operands[0],
+			      mask, operands[1], operands[2]));
+  else
+    emit_insn (gen_rtx_SET (operands[0], mask));
 }
 
 #define MAX_VECT_LEN 16
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 903f4b2d0eb..c6ca2859ec2 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -1439,19 +1439,6 @@
   DONE;
 })
 
-(define_expand "vcond_mask_<mode><v_cmp_result>"
-  [(set (match_operand:VDQW 0 "s_register_operand")
-	(if_then_else:VDQW
-	  (match_operand:<V_cmp_result> 3 "s_register_operand")
-	  (match_operand:VDQW 1 "s_register_operand")
-	  (match_operand:VDQW 2 "s_register_operand")))]
-  "TARGET_NEON"
-{
-  emit_insn (gen_neon_vbsl<mode> (operands[0], operands[3], operands[1],
-				  operands[2]));
-  DONE;
-})
-
 ;; Patterns for builtins.
 
 ; good for plain vadd, vaddq.
diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
index 9d784760a0d..5b13049b6a3 100644
--- a/gcc/config/arm/vec-common.md
+++ b/gcc/config/arm/vec-common.md
@@ -422,3 +422,21 @@
   DONE;
 })
 
+(define_expand "vcond_mask_<mode><v_cmp_result>"
+  [(set (match_operand:VDQW 0 "s_register_operand")
+        (if_then_else:VDQW
+          (match_operand:<V_cmp_result> 3 "s_register_operand")
+          (match_operand:VDQW 1 "s_register_operand")
+          (match_operand:VDQW 2 "s_register_operand")))]
+  "TARGET_NEON || TARGET_HAVE_MVE"
+{
+  if (TARGET_NEON) {
+    emit_insn (gen_neon_vbsl(<MODE>mode, operands[0], operands[3], operands[1],
+			     operands[2]));
+  }
+  else if (TARGET_HAVE_MVE) {
+    emit_insn (gen_mve_vpselq(VPSELQ_S, <MODE>mode, operands[0], operands[1],
+			      operands[2], operands[3]));
+  }
+  DONE;
+})
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c
new file mode 100644
index 00000000000..49b864f292d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vcmp.c
@@ -0,0 +1,53 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB, OP, NAME)				\
+  void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * __restrict__ dest, TYPE##BITS##_t *a, TYPE##BITS##_t *b) { \
+    int i;								\
+    for (i=0; i<NB; i++) {						\
+      dest[i] = a[i] OP b[i];						\
+    }									\
+}
+
+#define ALL_FUNCS(OP, NAME) \
+  FUNC(s, int, 32, 2, OP, NAME)			\
+  FUNC(u, uint, 32, 2, OP, NAME)		\
+  FUNC(s, int, 16, 4, OP, NAME)			\
+  FUNC(u, uint, 16, 4, OP, NAME)		\
+  FUNC(s, int, 8, 8, OP, NAME)			\
+  FUNC(u, uint, 8, 8, OP, NAME)			\
+  FUNC(s, int, 32, 4, OP, NAME)			\
+  FUNC(u, uint, 32, 4, OP, NAME)		\
+  FUNC(s, int, 16, 8, OP, NAME)			\
+  FUNC(u, uint, 16, 8, OP, NAME)		\
+  FUNC(s, int, 8, 16, OP, NAME)			\
+  FUNC(u, uint, 8, 16, OP, NAME)
+
+ALL_FUNCS(==, vcmpeq)
+ALL_FUNCS(!=, vcmpne)
+ALL_FUNCS(<, vcmplt)
+ALL_FUNCS(<=, vcmple)
+ALL_FUNCS(>, vcmpgt)
+ALL_FUNCS(>=, vcmpge)
+
+/* MVE has only 128-bit vectors, so we can vectorize only half of the
+   functions above.  */
+/* Although float16 and float32 types are supported at assembly level,
+   we cannot test them with the '==' operator, so we check only the
+   integer variants.  */
+/* { dg-final { scan-assembler-times {\tvcmp.i[0-9]+  eq, q[0-9]+, q[0-9]+\n} 6 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.i[0-9]+  ne, q[0-9]+, q[0-9]+\n} 6 } } */
+
+/* lt, le, gt, ge apply to signed types, cs and hi to unsigned types.  */
+/* lt and le with unsigned types are replaced with the opposite condition, hence
+   the double number of matches for cs and hi.  */
+/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+  lt, q[0-9]+, q[0-9]+\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+  le, q[0-9]+, q[0-9]+\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+  gt, q[0-9]+, q[0-9]+\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.s[0-9]+  ge, q[0-9]+, q[0-9]+\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.u[0-9]+  cs, q[0-9]+, q[0-9]+\n} 6 } } */
+/* { dg-final { scan-assembler-times {\tvcmp.u[0-9]+  hi, q[0-9]+, q[0-9]+\n} 6 } } */


More information about the Gcc-cvs mailing list