From 11a0beff64f71d03fa6614a985b6a870da6cc821 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Thu, 12 Nov 2020 20:16:05 +0000 Subject: [PATCH] arm: Auto-vectorization for MVE: vand This patch enables MVE vandq instructions for auto-vectorization. MVE vandq insns in mve.md are modified to use 'and' instead of unspec expression to support and3. The and3 expander is added to vec-common.md 2020-12-03 Christophe Lyon gcc/ * config/arm/iterators.md (supf): Remove VANDQ_S and VANDQ_U. (VANQ): Remove. (VDQ): Add TARGET_HAVE_MVE condition where relevant. * config/arm/mve.md (mve_vandq_u): New entry for vand instruction using expression 'and'. (mve_vandq_s): New expander. (mve_vaddq_n_f): Use 'and' code instead of unspec. * config/arm/neon.md (and3): Rename into and3_neon. * config/arm/predicates.md (imm_for_neon_inv_logic_operand): Enable for MVE. * config/arm/unspecs.md (VANDQ_S, VANDQ_U, VANDQ_F): Remove. * config/arm/vec-common.md (and3): New expander. gcc/testsuite/ * gcc.target/arm/simd/mve-vand.c: New test. --- gcc/config/arm/iterators.md | 11 ++-- gcc/config/arm/mve.md | 30 +++++++--- gcc/config/arm/neon.md | 2 +- gcc/config/arm/predicates.md | 2 +- gcc/config/arm/unspecs.md | 3 - gcc/config/arm/vec-common.md | 8 +++ gcc/testsuite/gcc.target/arm/simd/mve-vand.c | 63 ++++++++++++++++++++ 7 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vand.c diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 592af35f038..badad2bf293 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -147,7 +147,12 @@ (define_mode_iterator VN [V8HI V4SI V2DI]) ;; All supported vector modes (except singleton DImode). -(define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V4HF V8HF V2SF V4SF V2DI]) +(define_mode_iterator VDQ [(V8QI "!TARGET_HAVE_MVE") V16QI + (V4HI "!TARGET_HAVE_MVE") V8HI + (V2SI "!TARGET_HAVE_MVE") V4SI + (V4HF "!TARGET_HAVE_MVE") V8HF + (V2SF "!TARGET_HAVE_MVE") V4SF + (V2DI "!TARGET_HAVE_MVE")]) ;; All supported floating-point vector modes (except V2DF). (define_mode_iterator VF [(V4HF "TARGET_NEON_FP16INST") @@ -1232,8 +1237,7 @@ (VADDLVQ_P_U "u") (VCMPNEQ_U "u") (VCMPNEQ_S "s") (VABDQ_M_S "s") (VABDQ_M_U "u") (VABDQ_S "s") (VABDQ_U "u") (VADDQ_N_S "s") (VADDQ_N_U "u") - (VADDVQ_P_S "s") (VADDVQ_P_U "u") (VANDQ_S "s") - (VANDQ_U "u") (VBICQ_S "s") (VBICQ_U "u") + (VADDVQ_P_S "s") (VADDVQ_P_U "u") (VBICQ_S "s") (VBICQ_U "u") (VBRSRQ_N_S "s") (VBRSRQ_N_U "u") (VCADDQ_ROT270_S "s") (VCADDQ_ROT270_U "u") (VCADDQ_ROT90_S "s") (VCMPEQQ_S "s") (VCMPEQQ_U "u") (VCADDQ_ROT90_U "u") @@ -1501,7 +1505,6 @@ (define_int_iterator VADDQ_N [VADDQ_N_S VADDQ_N_U]) (define_int_iterator VADDVAQ [VADDVAQ_S VADDVAQ_U]) (define_int_iterator VADDVQ_P [VADDVQ_P_U VADDVQ_P_S]) -(define_int_iterator VANDQ [VANDQ_U VANDQ_S]) (define_int_iterator VBICQ [VBICQ_S VBICQ_U]) (define_int_iterator VBRSRQ_N [VBRSRQ_N_U VBRSRQ_N_S]) (define_int_iterator VCADDQ_ROT270 [VCADDQ_ROT270_S VCADDQ_ROT270_U]) diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index ecbaaa91501..1ec0d1aa323 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -894,17 +894,30 @@ ;; ;; [vandq_u, vandq_s]) ;; -(define_insn "mve_vandq_" +;; signed and unsigned versions are the same: define the unsigned +;; insn, and use an expander for the signed one as we still reference +;; both names from arm_mve.h. +;; We use the same code as in neon.md (TODO: avoid this duplication). +(define_insn "mve_vandq_u" [ - (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")] - VANDQ)) + (set (match_operand:MVE_2 0 "s_register_operand" "=w,w") + (and:MVE_2 (match_operand:MVE_2 1 "s_register_operand" "w,0") + (match_operand:MVE_2 2 "neon_inv_logic_op2" "w,DL"))) ] "TARGET_HAVE_MVE" - "vand %q0, %q1, %q2" + "@ + vand\t%q0, %q1, %q2 + * return neon_output_logic_immediate (\"vand\", &operands[2], mode, 1, VALID_NEON_QREG_MODE (mode));" [(set_attr "type" "mve_move") ]) +(define_expand "mve_vandq_s" + [ + (set (match_operand:MVE_2 0 "s_register_operand") + (and:MVE_2 (match_operand:MVE_2 1 "s_register_operand") + (match_operand:MVE_2 2 "neon_inv_logic_op2"))) + ] + "TARGET_HAVE_MVE" +) ;; ;; [vbicq_s, vbicq_u]) @@ -2019,9 +2032,8 @@ (define_insn "mve_vandq_f" [ (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")] - VANDQ_F)) + (and: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" "vand %q0, %q1, %q2" diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 2d767698378..dc4707d7447 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -712,7 +712,7 @@ ;; corresponds to the canonical form the middle-end expects to use for ;; immediate bitwise-ANDs. -(define_insn "and3" +(define_insn "and3_neon" [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))] diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 2144520829c..5f58f7c837e 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -107,7 +107,7 @@ (define_predicate "imm_for_neon_inv_logic_operand" (match_code "const_vector") { - return (TARGET_NEON + return ((TARGET_NEON || TARGET_HAVE_MVE) && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL)); }) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index a3844e9a72a..18b30487435 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -601,7 +601,6 @@ VADDQ_N_S VADDVAQ_S VADDVQ_P_S - VANDQ_S VBICQ_S VBRSRQ_N_S VCADDQ_ROT270_S @@ -648,7 +647,6 @@ VADDQ_N_U VADDVAQ_U VADDVQ_P_U - VANDQ_U VBICQ_U VBRSRQ_N_U VCADDQ_ROT270_U @@ -721,7 +719,6 @@ VABDQ_M_U VABDQ_F VADDQ_N_F - VANDQ_F VBICQ_F VCADDQ_ROT270_F VCADDQ_ROT90_F diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index 250e503876a..2117e5be5c2 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -172,3 +172,11 @@ GEN_INT (elem), operands[0])); DONE; }) + +(define_expand "and3" + [(set (match_operand:VDQ 0 "s_register_operand" "") + (and:VDQ (match_operand:VDQ 1 "s_register_operand" "") + (match_operand:VDQ 2 "neon_inv_logic_op2" "")))] + "TARGET_NEON + || TARGET_HAVE_MVE" +) diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vand.c b/gcc/testsuite/gcc.target/arm/simd/mve-vand.c new file mode 100644 index 00000000000..26247dc4105 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vand.c @@ -0,0 +1,63 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-additional-options "-O3" } */ + +#include + +#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