]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Fix V{64QI,32HI}mode constant permutations [PR94509]
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Apr 2020 12:39:24 +0000 (14:39 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 7 Apr 2020 19:02:06 +0000 (21:02 +0200)
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.

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/avx512bw-pr94509-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/avx512bw-pr94509-2.c [new file with mode: 0644]

index 7c873296c56d329bdc34efa575233bb3b8241566..9d077ed6e182f2b94a2b83a9b975d5bea31f6b77 100644 (file)
@@ -1,13 +1,15 @@
 2020-04-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/94509
+       * config/i386/i386.c (expand_vec_perm_pshufb): Fix the check
+       for inter-lane permutation for 64-byte modes.
+
        PR target/94488
        * config/aarch64/aarch64-simd.md (ashl<mode>3, lshr<mode>3,
        ashr<mode>3): Force operands[2] into reg whenever it is not CONST_INT.
        Assume it is a REG after that instead of testing it and doing FAIL
        otherwise.  Formatting fix.
 
-2020-04-07  Jakub Jelinek  <jakub@redhat.com>
-
        Backported from mainline
        2020-04-04  Hannes Domani  <ssbssa@yahoo.de>
                    Jakub Jelinek  <jakub@redhat.com>
index c9c33a8fd624a433f609eddf39bc56b356e4fd24..5d12d82db5b1f667576693c156f2218289d9c5ba 100644 (file)
@@ -46675,7 +46675,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;
            }
        }
index 7aed8e289c167fb01b8e52e17c40a83cfdad711e..605cd2e1c73441942de33ebcb9b5c7793864d458 100644 (file)
@@ -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 (file)
index 0000000..6cd79b7
--- /dev/null
@@ -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 (file)
index 0000000..089e3f2
--- /dev/null
@@ -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 ();
+}