]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: PR target/94591: Don't generate invalid REV64 insns
authorAlex Coplan <alex.coplan@arm.com>
Fri, 29 May 2020 13:19:23 +0000 (14:19 +0100)
committerAlex Coplan <alex.coplan@arm.com>
Fri, 29 May 2020 13:19:23 +0000 (14:19 +0100)
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)

gcc/config/aarch64/aarch64.c
gcc/testsuite/gcc.c-torture/execute/pr94591.c [new file with mode: 0644]

index e61c9bb00cb50aeaff51cdf0f58fb9a0617d41bb..35b5b2fd3a652b6aa1c6956c8e02858c3a167696 100644 (file)
@@ -16520,7 +16520,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 (file)
index 0000000..42271ad
--- /dev/null
@@ -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();
+}