With constants we can match `~(a | CST)` into `CST & ~a`.
Likewise `~(a & CST)` into `CST | ~a`.
Built and tested for aarch64-linux-gnu with no regressions.
PR target/116013
PR target/115086
gcc/ChangeLog:
* match.pd (`~(a & CST)`, `~(a | CST)`): New pattern.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/bic-cst-2.c: New test.
* gcc.target/aarch64/bic_simd-2.c: New test.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/match.pd | 10 ++++++
gcc/testsuite/gcc.target/aarch64/bic-cst-2.c | 31 +++++++++++++++++
gcc/testsuite/gcc.target/aarch64/bic_simd-2.c | 33 +++++++++++++++++++
3 files changed, 74 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/bic-cst-2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/bic_simd-2.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 56f631dfeec..680dfea523f 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -9994,6 +9994,16 @@ and,
(simplify
(bitopc @0 CONSTANT_CLASS_P@1)
(bitop (bit_not! @1) @0)))
+
+/* Create bit_andc and bit_iorc internal functions. */
+(for rbitop (bit_ior bit_and)
+ bitopc (IFN_BIT_ANDN IFN_BIT_IORN)
+ (simplify
+ (bit_not (rbitop:s @0 CONSTANT_CLASS_P@1))
+ (if (canonicalize_math_after_vectorization_p ()
+ && direct_internal_fn_supported_p (as_internal_fn (bitopc),
+ type, OPTIMIZE_FOR_BOTH))
+ (bitopc (bit_not! @1) @0))))
#endif
/* For pointers @0 and @2 and nonnegative constant offset @1, look for
diff --git a/gcc/testsuite/gcc.target/aarch64/bic-cst-2.c
b/gcc/testsuite/gcc.target/aarch64/bic-cst-2.c
new file mode 100644
index 00000000000..b89ac72dae1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bic-cst-2.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+/**
+**bar1:
+** mov w([0-9]+), 4
+** bic w0, w\1, w1
+** ret
+*/
+int bar1(int a, int c)
+{
+ int b = ~((~4) | c);
+ return b;
+}
+
+/**
+**foo1:
+** mov w([0-9]+), 4
+** orn w0, w\1, w1
+** ret
+*/
+int foo1(int a, int c)
+{
+ int b = ~((~4) & c);
+ return b;
+}
+
+/* { dg-final { scan-tree-dump ".BIT_ANDN " "optimized" } } */
+/* { dg-final { scan-tree-dump ".BIT_IORN " "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/bic_simd-2.c
b/gcc/testsuite/gcc.target/aarch64/bic_simd-2.c
new file mode 100644
index 00000000000..8543ce61400
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bic_simd-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+/**
+**bar1:
+** movi v([0-9]+).2s, 0x4
+** bic v0.8b, v\1.8b, v1.8b
+** ret
+*/
+#define vect8 __attribute__((vector_size(8)))
+vect8 int bar1(vect8 int a, vect8 int c)
+{
+ vect8 int b = ~((~4) | c);
+ return b;
+}
+
+/**
+**foo1:
+** movi v([0-9]+).2s, 0x4
+** orn v0.8b, v\1.8b, v1.8b
+** ret
+*/
+#define vect8 __attribute__((vector_size(8)))
+vect8 int foo1(vect8 int a, vect8 int c)
+{
+ vect8 int b = ~((~4) & c);
+ return b;
+}
+
+/* { dg-final { scan-tree-dump ".BIT_ANDN " "optimized" } } */
+/* { dg-final { scan-tree-dump ".BIT_IORN " "optimized" } } */
+
--
2.43.0