aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@marvell.com>2023-03-10 00:53:39 +0000
committerAndrew Pinski <apinski@marvell.com>2023-03-10 17:51:54 +0000
commitfcbc5c190c40b51c82f827830ce403c07d628960 (patch)
tree89071f26d2ff6e06cbca307e38ad9ad383c26088 /gcc
parentf8332e52a498df480f72303de32ad0751ad899fe (diff)
downloadgcc-fcbc5c190c40b51c82f827830ce403c07d628960.zip
gcc-fcbc5c190c40b51c82f827830ce403c07d628960.tar.gz
gcc-fcbc5c190c40b51c82f827830ce403c07d628960.tar.bz2
Fix PR 108874: aarch64 code regression with shift and ands
After r6-2044-g98e30e515f184b, code like "((x & 0xff00ff00U) >> 8)" would be optimized like (x >> 8) & 0xff00ffU which is normally better except on aarch64, the shift right could be combined with another operation in some cases. So we need to add a few define_splits to the aarch64 backends that match "((x >> shift) & CST0) OP Y" and splits it to: TMP = X & CST1 (TMP >> shift) OP Y Note this also gets us to matching rev16 back too so I added a testcase to make sure we don't lose that matching any more. Note when the generic patch to recognize those as bswap ROT 16, we might regress again and need to add a few more patterns to the aarch64 backend but will deal with that once that happens. Committed as approved after a bootstrapp/test on aarch64-linux-gnu with no regressions. gcc/ChangeLog: * config/aarch64/aarch64.md: Add a new define_split to help combine. gcc/testsuite/ChangeLog: * gcc.target/aarch64/rev16_2.c: New test. * gcc.target/aarch64/shift_and_operator-1.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/aarch64/aarch64.md23
-rw-r--r--gcc/testsuite/gcc.target/aarch64/rev16_2.c39
-rw-r--r--gcc/testsuite/gcc.target/aarch64/shift_and_operator-1.c22
3 files changed, 84 insertions, 0 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index af90875..022eef8 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4659,6 +4659,29 @@
(define_split
[(set (match_operand:GPI 0 "register_operand")
(LOGICAL_OR_PLUS:GPI
+ (and:GPI
+ (lshiftrt:GPI (match_operand:GPI 1 "register_operand")
+ (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
+ (match_operand:GPI 3 "aarch64_logical_immediate"))
+ (match_operand:GPI 4 "register_operand")))]
+ "can_create_pseudo_p ()
+ && aarch64_bitmask_imm (UINTVAL (operands[3]) << UINTVAL (operands[2]),
+ <MODE>mode)"
+ [(set (match_dup 5) (and:GPI (match_dup 1) (match_dup 6)))
+ (set (match_dup 0) (LOGICAL_OR_PLUS:GPI
+ (lshiftrt:GPI (match_dup 5) (match_dup 2))
+ (match_dup 4)))]
+ {
+ operands[5] = gen_reg_rtx (<MODE>mode);
+ operands[6]
+ = gen_int_mode (UINTVAL (operands[3]) << UINTVAL (operands[2]),
+ <MODE>mode);
+ }
+)
+
+(define_split
+ [(set (match_operand:GPI 0 "register_operand")
+ (LOGICAL_OR_PLUS:GPI
(and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand")
(match_operand:QI 2 "aarch64_shift_imm_<mode>"))
(match_operand:GPI 3 "const_int_operand"))
diff --git a/gcc/testsuite/gcc.target/aarch64/rev16_2.c b/gcc/testsuite/gcc.target/aarch64/rev16_2.c
new file mode 100644
index 0000000..621eb5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/rev16_2.c
@@ -0,0 +1,39 @@
+/* { dg-options "-O2" } */
+/* { dg-do compile } */
+
+extern void abort (void);
+
+typedef unsigned int __u32;
+
+__u32
+__rev16_32_alt (__u32 x)
+{
+ return (((__u32)(x) & (__u32)0xff00ff00UL) >> 8)
+ | (((__u32)(x) & (__u32)0x00ff00ffUL) << 8);
+}
+
+__u32
+__rev16_32 (__u32 x)
+{
+ return (((__u32)(x) & (__u32)0x00ff00ffUL) << 8)
+ | (((__u32)(x) & (__u32)0xff00ff00UL) >> 8);
+}
+
+typedef unsigned long long __u64;
+
+__u64
+__rev16_64_alt (__u64 x)
+{
+ return (((__u64)(x) & (__u64)0xff00ff00ff00ff00UL) >> 8)
+ | (((__u64)(x) & (__u64)0x00ff00ff00ff00ffUL) << 8);
+}
+
+__u64
+__rev16_64 (__u64 x)
+{
+ return (((__u64)(x) & (__u64)0x00ff00ff00ff00ffUL) << 8)
+ | (((__u64)(x) & (__u64)0xff00ff00ff00ff00UL) >> 8);
+}
+
+/* { dg-final { scan-assembler-times "rev16\\tx\[0-9\]+" 2 } } */
+/* { dg-final { scan-assembler-times "rev16\\tw\[0-9\]+" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/shift_and_operator-1.c b/gcc/testsuite/gcc.target/aarch64/shift_and_operator-1.c
new file mode 100644
index 0000000..49152c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/shift_and_operator-1.c
@@ -0,0 +1,22 @@
+/* { dg-options "-O2" } */
+/* { dg-do compile } */
+
+unsigned f(unsigned x, unsigned b)
+{
+ return ((x & 0xff00ff00U) >> 8) | b;
+}
+
+unsigned f0(unsigned x, unsigned b)
+{
+ return ((x & 0xff00ff00U) >> 8) ^ b;
+}
+unsigned f1(unsigned x, unsigned b)
+{
+ return ((x & 0xff00ff00U) >> 8) + b;
+}
+
+/* { dg-final { scan-assembler-times "lsr\\tw\[0-9\]+" 0 } } */
+/* { dg-final { scan-assembler-times "lsr 8" 3 } } */
+/* { dg-final { scan-assembler-times "eor\\tw\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "add\\tw\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "orr\\tw\[0-9\]+" 1 } } */