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.
{
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 ();
}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}