ping?

On Thu, 17 Dec 2020 at 18:48, Christophe Lyon
<christophe.l...@linaro.org> wrote:
>
> This patch enables MVE vshlq instructions for auto-vectorization.
>
> The existing mve_vshlq_n_<supf><mode> is kept, as it takes a single
> immediate as second operand, and is used by arm_mve.h.
>
> We move the vashl<mode>3 insn from neon.md to an expander in
> vec-common.md, and the mve_vshlq_<supf><mode> insn from mve.md to
> vec-common.md, adding the second alternative fron neon.md.
>
> mve_vshlq_<supf><mode> will be used by a later patch enabling
> vectorization for vshr, as a unified version of
> ashl3<mode3>_[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]<q> attribute is still
> suitable, since this insn is also used for MVE.
>
> I kept the mve_vshlq_<supf><mode> naming instead of renaming it to
> ashl3_<supf>_<mode> 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;
>
>     <bb 2> [local count: 119292720]:
>
>     <bb 3> [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 <bb 5>; [87.50%]
>     else
>       goto <bb 4>; [12.50%]
>
>     <bb 5> [local count: 835156386]:
>     goto <bb 3>; [100.00%]
>
>     <bb 4> [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  <christophe.l...@linaro.org>
>
>         gcc/
>         * config/arm/mve.md (mve_vshlq_<supf><mode>): Move to
>         vec-commond.md.
>         * config/arm/neon.md (vashl<mode>3): Delete.
>         * config/arm/vec-common.md (mve_vshlq_<supf><mode>): New.
>         (vasl<mode>3): New expander.
>
>         gcc/testsuite/
>         * gcc.target/arm/simd/mve-vshl.c: Add tests for vshl.
> ---
>  gcc/config/arm/mve.md                        | 13 +-----
>  gcc/config/arm/neon.md                       | 19 ---------
>  gcc/config/arm/vec-common.md                 | 30 ++++++++++++++
>  gcc/testsuite/gcc.target/arm/simd/mve-vshl.c | 62 
> ++++++++++++++++++++++++++++
>  4 files changed, 93 insertions(+), 31 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/arm/simd/mve-vshl.c
>
> diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
> index 673a83c..8bdb451 100644
> --- a/gcc/config/arm/mve.md
> +++ b/gcc/config/arm/mve.md
> @@ -822,18 +822,7 @@ (define_insn "mve_vcmpneq_<supf><mode>"
>
>  ;;
>  ;; [vshlq_s, vshlq_u])
> -;;
> -(define_insn "mve_vshlq_<supf><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")]
> -        VSHLQ))
> -  ]
> -  "TARGET_HAVE_MVE"
> -  "vshl.<supf>%#<V_sz_elem>\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 50220be..ac9bf74 100644
> --- a/gcc/config/arm/neon.md
> +++ b/gcc/config/arm/neon.md
> @@ -845,25 +845,6 @@ (define_insn "*smax<mode>3_neon"
>  ; generic vectorizer code.  It ends up creating a V2DI constructor with
>  ; SImode elements.
>
> -(define_insn "vashl<mode>3"
> -  [(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.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2";
> -        case 1: return neon_output_shift_immediate ("vshl", 'i', 
> &operands[2],
> -                                                   <MODE>mode,
> -                                                   VALID_NEON_QREG_MODE 
> (<MODE>mode),
> -                                                   true);
> -        default: gcc_unreachable ();
> -      }
> -  }
> -  [(set_attr "type" "neon_shift_reg<q>, neon_shift_imm<q>")]
> -)
> -
>  (define_insn "vashr<mode>3_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 f6a79e2..3a282f0 100644
> --- a/gcc/config/arm/vec-common.md
> +++ b/gcc/config/arm/vec-common.md
> @@ -229,3 +229,33 @@ (define_expand "movmisalign<mode>"
>    if (!neon_vector_mem_operand (adjust_mem, 2, true))
>      XEXP (adjust_mem, 0) = force_reg (Pmode, XEXP (adjust_mem, 0));
>  })
> +
> +(define_insn "mve_vshlq_<supf><mode>"
> +  [(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_<MODE>_ARITH"
> +{
> +  switch (which_alternative)
> +    {
> +      case 0: return "vshl.<supf>%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, 
> %<V_reg>2";
> +      case 1: return neon_output_shift_immediate ("vshl", 'i', &operands[2],
> +                                                 <MODE>mode,
> +                                                 VALID_NEON_QREG_MODE 
> (<MODE>mode),
> +                                                 true);
> +      default: gcc_unreachable ();
> +    }
> +}
> +  [(set_attr "type" "neon_shift_reg<q>, neon_shift_imm<q>")]
> +)
> +
> +(define_expand "vashl<mode>3"
> +  [(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_<MODE>_ARITH"
> +{
> +  emit_insn (gen_mve_vshlq_u<mode> (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 0000000..7a06449
> --- /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 <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 FUNC_IMM(SIGN, TYPE, BITS, NB, OP, NAME)                             
>   \
> +  void test_ ## NAME ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t * 
> __restrict__ dest, TYPE##BITS##_t *a) { \
> +    int i;                                                             \
> +    for (i=0; i<NB; i++) {                                             \
> +      dest[i] = a[i] OP 5;                                             \
> +    }                                                                  \
> +}
> +
> +/* 64-bit vectors.  */
> +FUNC(s, int, 32, 2, <<, vshl)
> +FUNC(u, uint, 32, 2, <<, vshl)
> +FUNC(s, int, 16, 4, <<, vshl)
> +FUNC(u, uint, 16, 4, <<, vshl)
> +FUNC(s, int, 8, 8, <<, vshl)
> +FUNC(u, uint, 8, 8, <<, vshl)
> +
> +/* 128-bit vectors.  */
> +FUNC(s, int, 32, 4, <<, vshl)
> +FUNC(u, uint, 32, 4, <<, vshl)
> +FUNC(s, int, 16, 8, <<, vshl)  /* FIXME: not vectorized */
> +FUNC(u, uint, 16, 8, <<, vshl) /* FIXME: not vectorized */
> +FUNC(s, int, 8, 16, <<, vshl)  /* FIXME: not vectorized */
> +FUNC(u, uint, 8, 16, <<, vshl) /* FIXME: not vectorized */
> +
> +/* 64-bit vectors.  */
> +FUNC_IMM(s, int, 32, 2, <<, vshlimm)
> +FUNC_IMM(u, uint, 32, 2, <<, vshlimm)
> +FUNC_IMM(s, int, 16, 4, <<, vshlimm)
> +FUNC_IMM(u, uint, 16, 4, <<, vshlimm)
> +FUNC_IMM(s, int, 8, 8, <<, vshlimm)
> +FUNC_IMM(u, uint, 8, 8, <<, vshlimm)
> +
> +/* 128-bit vectors.  */
> +FUNC_IMM(s, int, 32, 4, <<, vshlimm)
> +FUNC_IMM(u, uint, 32, 4, <<, vshlimm)
> +FUNC_IMM(s, int, 16, 8, <<, vshlimm)
> +FUNC_IMM(u, uint, 16, 8, <<, vshlimm)
> +FUNC_IMM(s, int, 8, 16, <<, vshlimm)
> +FUNC_IMM(u, uint, 8, 16, <<, vshlimm)
> +
> +/* MVE has only 128-bit vectors, so we can vectorize only half of the
> +   functions above.  */
> +/* We only emit vshl.u, which is equivalent to vshl.s anyway.  */
> +/* { dg-final { scan-assembler-times {vshl.u[0-9]+\tq[0-9]+, q[0-9]+} 2 } } 
> */
> +
> +/* We emit vshl.i when the shift amount is an immediate.  */
> +/* { dg-final { scan-assembler-times {vshl.i[0-9]+\tq[0-9]+, q[0-9]+} 6 } } 
> */
> --
> 2.7.4
>

Reply via email to