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 <quic_apin...@quicinc.com>
---
 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

Reply via email to