From: Christophe Lyon Date: Mon, 16 Nov 2020 14:58:19 +0000 (+0000) Subject: arm: Auto-vectorization for MVE: vshl X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7432f255b70811dafaf325d94036ac580891de69;p=gcc.git arm: Auto-vectorization for MVE: vshl This patch enables MVE vshlq instructions for auto-vectorization. The existing mve_vshlq_n_ is kept, as it takes a single immediate as second operand, and is used by arm_mve.h. We move the vashl3 insn from neon.md to an expander in vec-common.md, and the mve_vshlq_ insn from mve.md to vec-common.md, adding the second alternative fron neon.md. mve_vshlq_ will be used by a later patch enabling vectorization for vshr, as a unified version of ashl3_[signed|unsigned] from neon.md. Keeping the use of unspec VSHLQ enables to generate both 's' and 'u' variants. It is not clear whether the neon_shift_[reg|imm] attribute is still suitable, since this insn is also used for MVE. I kept the mve_vshlq_ naming instead of renaming it to ashl3__ as discussed because the reference in arm_mve_builtins.def automatically inserts the "mve_" prefix and I didn't want to make a special case for this. I haven't yet found why the v16qi and v8hi tests are not vectorized. With dest[i] = a[i] << b[i] and: { int i; unsigned int i.24_1; unsigned int _2; int16_t * _3; short int _4; int _5; int16_t * _6; short int _7; int _8; int _9; int16_t * _10; short int _11; unsigned int ivtmp_42; unsigned int ivtmp_43; [local count: 119292720]: [local count: 954449105]: i.24_1 = (unsigned int) i_23; _2 = i.24_1 * 2; _3 = a_15(D) + _2; _4 = *_3; _5 = (int) _4; _6 = b_16(D) + _2; _7 = *_6; _8 = (int) _7; _9 = _5 << _8; _10 = dest_17(D) + _2; _11 = (short int) _9; *_10 = _11; i_19 = i_23 + 1; ivtmp_42 = ivtmp_43 - 1; if (ivtmp_42 != 0) goto ; [87.50%] else goto ; [12.50%] [local count: 835156386]: goto ; [100.00%] [local count: 119292720]: return; } the vectorizer says: mve-vshl.c:37:96: note: ==> examining statement: _5 = (int) _4; mve-vshl.c:37:96: note: vect_is_simple_use: operand *_3, type of def: internal mve-vshl.c:37:96: note: vect_is_simple_use: vectype vector(8) short int mve-vshl.c:37:96: missed: conversion not supported by target. mve-vshl.c:37:96: note: vect_is_simple_use: operand *_3, type of def: internal mve-vshl.c:37:96: note: vect_is_simple_use: vectype vector(8) short int mve-vshl.c:37:96: note: vect_is_simple_use: operand *_3, type of def: internal mve-vshl.c:37:96: note: vect_is_simple_use: vectype vector(8) short int mve-vshl.c:37:117: missed: not vectorized: relevant stmt not supported: _5 = (int) _4; mve-vshl.c:37:96: missed: bad operation or unsupported loop bound. mve-vshl.c:37:96: note: ***** Analysis failed with vector mode V8HI 2020-12-03 Christophe Lyon gcc/ * config/arm/mve.md (mve_vshlq_): Move to vec-commond.md. * config/arm/neon.md (vashl3): Delete. * config/arm/vec-common.md (mve_vshlq_): New. (vasl3): New expander. gcc/testsuite/ * gcc.target/arm/simd/mve-vshl.c: Add tests for vshl. --- diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 7fb69aae119..89ee172471d 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -822,18 +822,7 @@ ;; ;; [vshlq_s, vshlq_u]) -;; -(define_insn "mve_vshlq_" - [ - (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")] - VSHLQ)) - ] - "TARGET_HAVE_MVE" - "vshl.%#\t%q0, %q1, %q2" - [(set_attr "type" "mve_move") -]) +;; See vec-common.md ;; ;; [vabdq_s, vabdq_u]) diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 317b98e5620..b229834b30f 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -845,25 +845,6 @@ ; generic vectorizer code. It ends up creating a V2DI constructor with ; SImode elements. -(define_insn "vashl3" - [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w") - (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w,w") - (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dm")))] - "TARGET_NEON" - { - switch (which_alternative) - { - case 0: return "vshl.\t%0, %1, %2"; - case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2], - mode, - VALID_NEON_QREG_MODE (mode), - true); - default: gcc_unreachable (); - } - } - [(set_attr "type" "neon_shift_reg, neon_shift_imm")] -) - (define_insn "vashr3_imm" [(set (match_operand:VDQIW 0 "s_register_operand" "=w") (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md index 32387e11d61..5dfdf99be2d 100644 --- a/gcc/config/arm/vec-common.md +++ b/gcc/config/arm/vec-common.md @@ -238,3 +238,25 @@ if (!neon_vector_mem_operand (adjust_mem, 2, true)) XEXP (adjust_mem, 0) = force_reg (Pmode, XEXP (adjust_mem, 0)); }) + +(define_insn "mve_vshlq_" + [(set (match_operand:VDQIW 0 "s_register_operand" "=w,w") + (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w,w") + (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "w,Dm")] + VSHLQ))] + "ARM_HAVE__ARITH" + "@ + vshl.%#\t%0, %1, %2 + * return neon_output_shift_immediate (\"vshl\", 'i', &operands[2], mode, VALID_NEON_QREG_MODE (mode), true);" + [(set_attr "type" "neon_shift_reg, neon_shift_imm")] +) + +(define_expand "vashl3" + [(set (match_operand:VDQIW 0 "s_register_operand" "") + (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") + (match_operand:VDQIW 2 "imm_lshift_or_reg_neon" "")))] + "ARM_HAVE__ARITH" +{ + emit_insn (gen_mve_vshlq_u (operands[0], operands[1], operands[2])); + DONE; +}) \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vshl.c b/gcc/testsuite/gcc.target/arm/simd/mve-vshl.c new file mode 100644 index 00000000000..7a0644997c8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/simd/mve-vshl.c @@ -0,0 +1,62 @@ +/* { 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