aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-04-07 14:39:24 +0200
committerJakub Jelinek <jakub@redhat.com>2020-04-07 14:39:24 +0200
commitd51af82b4cf4c95c4a7451df2180cc6ebb44856b (patch)
tree83cf14d47f41bf298b86f5e1d8960ede45a9ee9d /gcc
parent4df50a059fbd4d4a1cb067bd43caccdfca0327a8 (diff)
i386: Fix V{64QI,32HI}mode constant permutations [PR94509]
The following testcases are miscompiled, because expand_vec_perm_pshufb incorrectly thinks it can use vpshufb instruction for the permutations when it can't. The if (vmode == V32QImode) { /* vpshufb only works intra lanes, it is not possible to shuffle bytes in between the lanes. */ for (i = 0; i < nelt; ++i) if ((d->perm[i] ^ i) & (nelt / 2)) return false; } intra-lane check which is correct has been copied and adjusted for 64-byte modes into: if (vmode == V64QImode) { /* vpshufb only works intra lanes, it is not possible to shuffle bytes in between the lanes. */ for (i = 0; i < nelt; ++i) if ((d->perm[i] ^ i) & (nelt / 4)) return false; } which is not correct, because 64-byte modes have 4 lanes rather than just two and the above is only testing that the permutation grabs even lane elts from even lanes and odd lane elts from odd lanes, but not that they are from the same 256-bit half. The following patch fixes it by using 3 * nelt / 4 instead of nelt / 4, so we actually check the most significant 2 bits rather than just one. 2020-04-07 Jakub Jelinek <jakub@redhat.com> PR target/94509 * config/i386/i386-expand.c (expand_vec_perm_pshufb): Fix the check for inter-lane permutation for 64-byte modes. * gcc.target/i386/avx512bw-pr94509-1.c: New test. * gcc.target/i386/avx512bw-pr94509-2.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/i386-expand.c2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr94509-1.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr94509-2.c38
5 files changed, 79 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c6e0db0f869..566967cd62f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/94509
+ * config/i386/i386-expand.c (expand_vec_perm_pshufb): Fix the check
+ for inter-lane permutation for 64-byte modes.
+
2020-04-07 Sebastian Huber <sebastian.huber@embedded-brains.de>
* config/rs6000/t-rtems: Delete mcpu=8540 multilib.
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 066de99e660..48f00c5fcfc 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -16781,7 +16781,7 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
/* vpshufb only works intra lanes, it is not
possible to shuffle bytes in between the lanes. */
for (i = 0; i < nelt; ++i)
- if ((d->perm[i] ^ i) & (nelt / 4))
+ if ((d->perm[i] ^ i) & (3 * nelt / 4))
return false;
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index da2664b7d7f..af475d42de4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2020-04-07 Jakub Jelinek <jakub@redhat.com>
+ PR target/94509
+ * gcc.target/i386/avx512bw-pr94509-1.c: New test.
+ * gcc.target/i386/avx512bw-pr94509-2.c: New test.
+
PR c++/94512
* g++.dg/gomp/pr94512.C: New test.
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-1.c
new file mode 100644
index 00000000000..6cd79b7443f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-1.c
@@ -0,0 +1,30 @@
+/* PR target/94509 */
+/* { dg-do run { target avx512bw } } */
+/* { dg-options "-O2 -mavx512bw" } */
+
+#define AVX512BW
+#include "avx512f-helper.h"
+
+typedef unsigned short __attribute__ ((__vector_size__ (64))) V;
+
+__attribute__((noipa)) V
+foo (V x)
+{
+ return __builtin_shuffle (x, (V) { 0, 0, 0, 0, 0, 0, 0, 0,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 15, 15, 15, 15, 15, 15, 15, 15 });
+}
+
+static void
+TEST (void)
+{
+ V v = foo ((V) { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32 });
+ unsigned int i;
+ for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ if (v[i] != ((i & 8) ? 16 : 1))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-2.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-2.c
new file mode 100644
index 00000000000..089e3f211b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr94509-2.c
@@ -0,0 +1,38 @@
+/* PR target/94509 */
+/* { dg-do run { target avx512bw } } */
+/* { dg-options "-O2 -mavx512bw" } */
+
+#define AVX512BW
+#include "avx512f-helper.h"
+
+typedef unsigned char __attribute__ ((__vector_size__ (64))) V;
+
+__attribute__((noipa)) V
+foo (V x)
+{
+ return __builtin_shuffle (x, (V) { 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1,
+ 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31,
+ 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1,
+ 30, 31, 30, 31, 30, 31, 30, 31,
+ 30, 31, 30, 31, 30, 31, 30, 31 });
+}
+
+static void
+TEST (void)
+{
+ V v = foo ((V) { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64 });
+ unsigned int i;
+ for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ if (v[i] != ((i & 16) ? 31 : 1) + (i & 1))
+ abort ();
+}