From: Alex Coplan Date: Fri, 29 May 2020 13:05:11 +0000 (+0100) Subject: aarch64: PR target/94591: Don't generate invalid REV64 insns X-Git-Tag: releases/gcc-10.2.0~307 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49824d35e0c87a5fdb3f5ea41223aa21d6ca6bfc;p=thirdparty%2Fgcc.git aarch64: PR target/94591: Don't generate invalid REV64 insns This fixes PR94591. The problem was the function aarch64_evpc_rev_local() matching vector permutations that were not reversals. In particular, prior to this patch, this function matched the identity permutation which led to generating bogus REV64 insns which were rejected by the assembler. gcc/ PR target/94591 * config/aarch64/aarch64.c (aarch64_evpc_rev_local): Don't match identity permutation. gcc/testsuite/ PR target/94591 * gcc.c-torture/execute/pr94591.c: New test. (cherry picked from commit 98452668d362bb9e6358f7eb5cff69f4f5ab1d45) --- diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 52787401e5da..8aeb78a4793c 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -20185,7 +20185,8 @@ aarch64_evpc_rev_local (struct expand_vec_perm_d *d) if (d->vec_flags == VEC_SVE_PRED || !d->one_vector_p - || !d->perm[0].is_constant (&diff)) + || !d->perm[0].is_constant (&diff) + || !diff) return false; size = (diff + 1) * GET_MODE_UNIT_SIZE (d->vmode); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr94591.c b/gcc/testsuite/gcc.c-torture/execute/pr94591.c new file mode 100644 index 000000000000..42271ad8bce9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr94591.c @@ -0,0 +1,32 @@ +typedef unsigned __attribute__((__vector_size__(8))) V2SI_u; +typedef int __attribute__((__vector_size__(8))) V2SI_d; + +typedef unsigned long __attribute__((__vector_size__(16))) V2DI_u; +typedef long __attribute__((__vector_size__(16))) V2DI_d; + +void id_V2SI(V2SI_d *v) +{ + *v = __builtin_shuffle(*v, (V2SI_d)(V2SI_u) { 0, 1 }); +} + +void id_V2DI(V2DI_d *v) +{ + *v = __builtin_shuffle(*v, (V2DI_d)(V2DI_u) { 0, 1 }); +} + +extern void abort(void); + +int main(void) +{ + V2SI_d si = { 35, 42 }; + id_V2SI(&si); + + if (si[0] != 35 || si[1] != 42) + abort(); + + V2DI_d di = { 63, 38 }; + id_V2DI(&di); + + if (di[0] != 63 || di[1] != 38) + abort(); +}