The patterns can be simplified as shown below:

(a != b) & ((a|b) != 0)  -> (a != b)
(a != b) | ((a|b) != 0)  -> ((a|b) != 0)

The similar simplification can be there for (a == b). This patch adds
simplification for above patterns. The forwprop pass was modifying the
patterns to some other form and they were not getting simplified. The
patch also adds simplification for those patterns.

Bootstrapped and tested on x86_64-linux-gnu with no regressions.

        PR 117760

gcc/ChangeLog:

        * match.pd ((a != b) and/or ((a | b) != 0)): New pattern.
  ((a == b) and/or (a | b) == 0): New pattern.
  ((a == b) & (a | b) == 0): New pattern.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/pr117760-1.c: New test.
        * gcc.dg/tree-ssa/pr117760-2.c: New test.
        * gcc.dg/tree-ssa/pr117760.c: New test.

Signed-off-by: Eikansh Gupta <quic_eikag...@quicinc.com>
---
 gcc/match.pd                               | 58 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c | 51 +++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c | 37 ++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr117760.c   | 51 +++++++++++++++++++
 4 files changed, 197 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117760.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 5c679848bdf..291c08d5882 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4852,6 +4852,64 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && expr_no_side_effects_p (@1))
    @2)))
 
+(for cmp (eq ne)
+ (for bitop (bit_ior bit_and)
+  /* ((a != b) & ((a | b) != 0)) -> (a != b) */
+  /* ((a != b) | ((a | b) != 0)) -> ((a|b) != 0) */
+  /* ((a == b) & (a | b) == 0) -> ((a|b) == 0) */
+  /* ((a == b) | (a | b) == 0) -> (a == b) */
+  (simplify
+   (bitop:c
+    (cmp@3 @1 @2)
+     (cmp@4 (bit_ior @1 @2) integer_zerop))
+   (if ((cmp == EQ_EXPR) ^ (bitop == BIT_IOR_EXPR))
+    @4 @3))
+
+  /* ((a == b) | (a == 0) | (b == 0)) -> (a == b) */
+  /* ((a == b) & ((a == 0) | (b == 0))) -> ((a|b) == 0) */
+  (simplify
+   (bitop:c
+    (eq:c@3 @1 @2)
+     (bit_ior (eq @1 integer_zerop) (eq @2 integer_zerop)))
+   (if (bitop == BIT_IOR_EXPR)
+    @3 (eq (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); }))))
+
+  /* (((a == b) & (a == 0)) | (b == 0)) -> ((a|b) == 0) */
+  /* (((a != b) & (a != 0)) | (b != 0)) -> (a != b) */
+  (simplify
+   (bit_ior:c (bit_and (cmp @1 integer_zerop) (cmp:c @1 @2))
+    (cmp @2 integer_zerop))
+   (if (cmp == EQ_EXPR)
+    (eq (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); })
+     (ne @1 @2))))
+
+/* ((a != b) | (a != 0) | (b != 0)) -> ((a|b) != 0) */
+(simplify
+ (bit_ior:c
+  (ne @1 @2)
+   (bit_ior:c (ne @1 integer_zerop) (ne @2 integer_zerop)))
+ (ne (bit_ior @1 @2) { build_zero_cst (TREE_TYPE (@1)); }))
+
+/* ((a != b) & ((a | b) == 0)) -> false */
+(simplify
+ (bit_and:c
+  (ne @1 @2)
+   (eq (bit_ior @1 @2) integer_zerop))
+ { constant_boolean_node (false, type); })
+
+/* ((a != b) & ((a == 0) | (b == 0))) -> false */
+(simplify
+ (bit_and:c
+  (ne:c@3 @1 @2)
+   (bit_ior:c (eq @1 integer_zerop) (eq @2 integer_zerop)))
+ { constant_boolean_node (false, type); })
+
+/* (((a != b) & (a == 0)) | (b == 0)) -> false */
+(simplify
+ (bit_ior:c (bit_and:c (eq @1 integer_zerop) (ne:c @1 @2))
+  (eq @2 integer_zerop))
+ { constant_boolean_node (false, type); })
+
 /* Simplifications of shift and rotates.  */
 
 (for rotate (lrotate rrotate)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c
new file mode 100644
index 00000000000..94a05f20ff0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-1.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+
+int f1(int a, int b)
+{
+  if (a == 0 || b == 0)
+    return a == b;
+  return 0;
+}
+
+int f2(int a, int b)
+{
+  int c = a == 0;
+  int d = b == 0;
+  int e = a == b;
+  return c|d|e;
+}
+
+int f3(int a, int b)
+{
+  int c = a == 0;
+  int d = b == 0;
+  int e = a == b;
+  return (c|d)&e;
+}
+
+int f4(int a, int b)
+{
+  int c = a == 0;
+  int d = b == 0;
+  int e = a == b;
+  return c|d&e;
+}
+
+int f5(int a, int b)
+{
+  int c = (a|b) == 0;
+  int e = a == b;
+  return c|e;
+}
+
+int f6(int a, int b)
+{
+  int c = (a|b) == 0;
+  int e = a == b;
+  return c&e;
+}
+
+/* { dg-final { scan-tree-dump-times "eq_expr, " 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "nop_expr, " 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c
new file mode 100644
index 00000000000..62c147cd6a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760-2.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+
+int f1(int a, int b)
+{
+  int c = a == 0;
+  int d = b == 0;
+  int e = a != b;
+  return (c|d)&e;
+}
+
+int f2(int a, int b)
+{
+  int c = (a|b) == 0;
+  int e = a != b;
+  return c&e;
+}
+
+int f3(int a, int b)
+{
+  int c = a == 0;
+  int d = b == 0;
+  int e = a != b;
+  return c|d&e;
+}
+
+int f4(int a, int b)
+{
+  if (a == 0 || b == 0)
+    return a != b;
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "ne_expr," "optimized"  } } */
+/* { dg-final { scan-tree-dump-not "eq_expr," "optimized"  } } */
+/* { dg-final { scan-tree-dump-not "bit_ior_expr," "optimized"  } } */
+/* { dg-final { scan-tree-dump-not "bit_and_expr," "optimized"  } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c
new file mode 100644
index 00000000000..c5f5dbd6123
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117760.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+
+int f1(int a, int b)
+{
+  if (a != 0 || b != 0)
+    return a != b;
+  return 0;
+}
+
+int f2(int a, int b)
+{
+  int c = a != 0;
+  int d = b != 0;
+  int e = a != b;
+  return c|d|e;
+}
+
+int f3(int a, int b)
+{
+  int c = a != 0;
+  int d = b != 0;
+  int e = a != b;
+  return (c|d)&e;
+}
+
+int f4(int a, int b)
+{
+  int c = a != 0;
+  int d = b != 0;
+  int e = a != b;
+  return c|d&e;
+}
+
+int f5(int a, int b)
+{
+  int c = (a|b) != 0;
+  int e = a != b;
+  return c|e;
+}
+
+int f6(int a, int b)
+{
+  int c = (a|b) != 0;
+  int e = a != b;
+  return c&e;
+}
+
+/* { dg-final { scan-tree-dump-times "ne_expr, " 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "nop_expr, " 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 2 "optimized" } } */
-- 
2.17.1

Reply via email to