From: Kyrylo Tkachov <[email protected]> The zero-vector insertion pattern requires its scalar input in an FP register. A scalar in a general register therefore produces two moves:
fmov d0, x0 fmov d0, d0 Add a general-register alternative that emits the first move directly. It copies the scalar element and clears the remaining SVE lanes. Use the general-to-FP transfer instruction type for this alternative. This removes the redundant self-move in the SVE256 filter handler. Code-generation tests cover 16-, 32- and 64-bit elements, and runtime checks cover the scalar value and all remaining lanes. Tests at SVE lengths from 128 through 2048 bits pass, including floating bit patterns. Bootstrapped and tested on aarch64-none-linux-gnu. Ok for trunk? Thanks, Kyrill Cc: Tamar Christina <[email protected]> Cc: Wilco Dijkstra <wilco@[email protected]> gcc/ChangeLog: * config/aarch64/aarch64-sve.md (*aarch64_vec_shl_insert_into_zero_<mode>): Add a general-register alternative and set its instruction type. gcc/testsuite/ChangeLog: * gcc.target/aarch64/sve/copsi.c (func_init3): Update expected assembly. * gcc.target/aarch64/sve/insr-zero-gpr.c: New test. * gcc.target/aarch64/sve/insr-zero-gpr-run.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]> --- gcc/config/aarch64/aarch64-sve.md | 3 +- gcc/testsuite/gcc.target/aarch64/sve/copsi.c | 1 - .../aarch64/sve/insr-zero-gpr-run.c | 47 +++++++++++ .../gcc.target/aarch64/sve/insr-zero-gpr.c | 80 +++++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr-run.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index dc92cef4d88..c2c2b905d6e 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -3031,8 +3031,9 @@ "TARGET_SVE" {@ [ cons: =0 , 1 , 2 ] [ w , Dz , w ] fmov\t%<Vetype>0, %<Vetype>2 + [ w , Dz , r ] fmov\t%<Vetype>0, %<vccore>2 } - [(set_attr "type" "neon_move")] + [(set_attr "type" "neon_move,f_mcr")] ) ;; Shift an SVE vector left and insert a scalar into element 0 of a zero diff --git a/gcc/testsuite/gcc.target/aarch64/sve/copsi.c b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c index d85403640b9..6bcbffe6446 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/copsi.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c @@ -20,7 +20,6 @@ func_init4 (int64_t a, int64_t b) /* ** func_init3: ** fmov s0, w2 -** fmov s0, s0 ** insr z0\.s, w1 ** insr z0\.s, w0 ** ret diff --git a/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr-run.c b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr-run.c new file mode 100644 index 00000000000..fff3abc6024 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr-run.c @@ -0,0 +1,47 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -march=armv8.2-a+sve" } */ + +#include "insr-zero-gpr.c" +#include <stdint.h> + +#define CHECK(BITS, COUNT) \ +static __attribute__ ((noinline, noclone)) void \ +check_##BITS (uint##BITS##_t value) \ +{ \ + unsigned long count = COUNT; \ + uint##BITS##_t input[count], output[count]; \ + for (unsigned long i = 0; i < count; ++i) \ + input[i] = (uint##BITS##_t) (i * 13 + 7); \ + svst1_u##BITS (svptrue_b##BITS (), output, zero_##BITS (value)); \ + if (output[0] != value) \ + __builtin_abort (); \ + for (unsigned long i = 1; i < count; ++i) \ + if (output[i] != 0) \ + __builtin_abort (); \ + svuint##BITS##_t v = svld1_u##BITS (svptrue_b##BITS (), input); \ + svst1_u##BITS (svptrue_b##BITS (), output, nonzero_##BITS (v, value)); \ + if (output[0] != value) \ + __builtin_abort (); \ + for (unsigned long i = 1; i < count; ++i) \ + if (output[i] != input[i - 1]) \ + __builtin_abort (); \ +} + +CHECK (16, svcnth ()) +CHECK (32, svcntw ()) +CHECK (64, svcntd ()) + +int +main (void) +{ + const uint64_t values[] = { 0, 1, 0x80, 0x8000, 0x80000000ULL, + 0x8000000000000000ULL, UINT64_MAX, + 0x123456789abcdef0ULL }; + for (unsigned int i = 0; i < sizeof (values) / sizeof (values[0]); ++i) + { + check_16 (values[i]); + check_32 (values[i]); + check_64 (values[i]); + } + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c new file mode 100644 index 00000000000..65e15551292 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/insr-zero-gpr.c @@ -0,0 +1,80 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv8.2-a+sve" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <arm_sve.h> + +/* Insert a scalar word from a general register into an otherwise zero + vector. The scalar move also clears the rest of the SVE register. */ + +/* +** zero_16: +** fmov h0, w0 +** ret +*/ +__attribute__ ((noipa)) +svuint16_t +zero_16 (uint16_t value) +{ + return svinsr_n_u16 (svdup_n_u16 (0), value); +} + +/* +** nonzero_16: +** insr z0.h, w0 +** ret +*/ +__attribute__ ((noipa)) +svuint16_t +nonzero_16 (svuint16_t vector, uint16_t value) +{ + return svinsr_n_u16 (vector, value); +} + +/* +** zero_32: +** fmov s0, w0 +** ret +*/ +__attribute__ ((noipa)) +svuint32_t +zero_32 (uint32_t value) +{ + return svinsr_n_u32 (svdup_n_u32 (0), value); +} + +/* +** nonzero_32: +** insr z0.s, w0 +** ret +*/ +__attribute__ ((noipa)) +svuint32_t +nonzero_32 (svuint32_t vector, uint32_t value) +{ + return svinsr_n_u32 (vector, value); +} + +/* +** zero_64: +** fmov d0, x0 +** ret +*/ +__attribute__ ((noipa)) +svuint64_t +zero_64 (uint64_t value) +{ + return svinsr_n_u64 (svdup_n_u64 (0), value); +} + +/* +** nonzero_64: +** insr z0.d, x0 +** ret +*/ +__attribute__ ((noipa)) +svuint64_t +nonzero_64 (svuint64_t vector, uint64_t value) +{ + return svinsr_n_u64 (vector, value); +} -- 2.50.1 (Apple Git-155)
