]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Fix up *aarch64_bfxilsi_uxtw [PR98853]
authorJakub Jelinek <jakub@redhat.com>
Wed, 27 Jan 2021 19:35:21 +0000 (20:35 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 29 Jan 2021 16:51:06 +0000 (17:51 +0100)
The https://gcc.gnu.org/legacy-ml/gcc-patches/2018-07/msg01895.html
patch that introduced this pattern claimed:
Would generate:

combine_balanced_int:
        bfxil   w0, w1, 0, 16
        uxtw    x0, w0
        ret

But with this patch generates:

combine_balanced_int:
        bfxil   w0, w1, 0, 16
        ret
and it is indeed what it should generate, but it doesn't do that,
it emits bfxil  x0, x1, 0, 16
instead which doesn't zero extend from 32 to 64 bits, but preserves
the bits from the destination register.

2021-01-27  Jakub Jelinek  <jakub@redhat.com>

PR target/98853
* config/aarch64/aarch64.md (*aarch64_bfxilsi_uxtw): Use
%w0, %w1 and %2 instead of %0, %1 and %2.

* gcc.c-torture/execute/pr98853-1.c: New test.
* gcc.c-torture/execute/pr98853-2.c: New test.

gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.c-torture/execute/pr98853-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr98853-2.c [new file with mode: 0644]

index da3ab66893a4c9bd55fb8d31d08375b6f64f077f..7f262e067ce90918c6c6ae0336cd102cfbc459da 100644 (file)
     {
       case 0:
        operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
-       return "bfxil\\t%0, %1, 0, %3";
+       return "bfxil\\t%w0, %w1, 0, %3";
       case 1:
        operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
-       return "bfxil\\t%0, %2, 0, %3";
+       return "bfxil\\t%w0, %w2, 0, %3";
       default:
        gcc_unreachable ();
     }
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98853-1.c b/gcc/testsuite/gcc.c-torture/execute/pr98853-1.c
new file mode 100644 (file)
index 0000000..b5a3786
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR target/98853 */
+
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+__attribute__((__noipa__)) unsigned long long
+foo (unsigned x, unsigned long long y, unsigned long long z)
+{
+  __builtin_memcpy (2 + (char *) &x, 2 + (char *) &y, 2);
+  return x + z;
+}
+#endif
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  if (foo (0x44444444U, 0x1111111111111111ULL, 0x2222222222222222ULL)
+      != 0x2222222233336666ULL)
+    __builtin_abort ();
+#endif
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98853-2.c b/gcc/testsuite/gcc.c-torture/execute/pr98853-2.c
new file mode 100644 (file)
index 0000000..2a3b0f2
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR target/98853 */
+
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+__attribute__((noipa)) unsigned long long
+foo (unsigned long long x, unsigned int y)
+{
+  return ((unsigned) x & 0xfffe0000U) | (y & 0x1ffff);
+}
+#endif
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8
+  if (foo (0xdeadbeefcaf2babeULL, 0xdeaffeedU) != 0x00000000caf3feedULL)
+    __builtin_abort ();
+#endif
+  return 0;
+}