arm: Auto-vectorization for MVE: vshl
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.lyon@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.
This commit is contained in:
parent
2ea6f4a377
commit
7432f255b7
@ -822,18 +822,7 @@
|
||||
|
||||
;;
|
||||
;; [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])
|
||||
|
@ -845,25 +845,6 @@
|
||||
; 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")
|
||||
|
@ -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_<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"
|
||||
"@
|
||||
vshl.<supf>%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
|
||||
* return neon_output_shift_immediate (\"vshl\", 'i', &operands[2], <MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode), true);"
|
||||
[(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;
|
||||
})
|
62
gcc/testsuite/gcc.target/arm/simd/mve-vshl.c
Normal file
62
gcc/testsuite/gcc.target/arm/simd/mve-vshl.c
Normal file
@ -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 } } */
|
Loading…
Reference in New Issue
Block a user