https://gcc.gnu.org/g:a88d6c6d777ad7c9235e2e620318f26e5347e50a

commit r15-3866-ga88d6c6d777ad7c9235e2e620318f26e5347e50a
Author: Konstantinos Eleftheriou <konstantinos.elefther...@vrull.eu>
Date:   Wed Aug 7 17:54:30 2024 +0200

    match: Fix A || B not optimized to true when !B implies A [PR114326]
    
    In expressions like (a != b || ((a ^ b) & c) == d) and
    (a != b || (a ^ b) == c), (a ^ b) is folded to false.
    In the equivalent expressions (((a ^ b) & c) == d || a != b) and
    ((a ^ b) == c || a != b) this is not happening.
    
    This patch adds the following simplifications in match.pd:
    ((a ^ b) & c) cmp d || a != b --> 0 cmp d || a != b
    (a ^ b) cmp c || a != b --> 0 cmp c || a != b
    
            PR tree-optimization/114326
    
    gcc/ChangeLog:
    
            * match.pd: Add two patterns to fold a ^ b to 0, when a == b.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/fold-xor-and-or.c: New test.
            * gcc.dg/tree-ssa/fold-xor-or.c: New test.
    
    Tested-by: Christoph Müllner <christoph.muell...@vrull.eu>
    Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu>
    Signed-off-by: Konstantinos Eleftheriou <konstantinos.elefther...@vrull.eu>

Diff:
---
 gcc/match.pd                                    | 30 ++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c | 55 +++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c     | 55 +++++++++++++++++++++++++
 3 files changed, 140 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index 7150b8e78cab..d10ac7d6cd20 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3787,6 +3787,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (types_match (type, TREE_TYPE (@0)))
      (bit_xor @0 { build_one_cst (type); } ))))))
 
+/* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
+(for cmp (simple_comparison)
+  (simplify
+    (bit_ior
+      (cmp:c
+       (bit_and:c
+         (bit_xor:c @0 @1)
+         tree_expr_nonzero_p@2)
+       @3)
+      (ne:c@4 @0 @1))
+    (bit_ior
+      (cmp
+       { build_zero_cst (TREE_TYPE (@0)); }
+       @3)
+      @4)))
+
+/* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
+(for cmp (simple_comparison)
+  (simplify
+    (bit_ior
+      (cmp:c
+       (bit_xor:c @0 @1)
+       @2)
+      (ne:c@3 @0 @1))
+    (bit_ior
+      (cmp
+       { build_zero_cst (TREE_TYPE (@0)); }
+       @2)
+      @3)))
+
 /* We can't reassociate at all for saturating types.  */
 (if (!TYPE_SATURATING (type))
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
new file mode 100644
index 000000000000..e5dc98e7541d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(int d1, int d2) {
+  if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
+    return 0;
+  return 1;
+}
+
+int cmp2(int d1, int d2) {
+  if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
+    return 0;
+  return 1;
+}
+
+int cmp3(int d1, int d2) {
+  if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
+    return 0;
+  return 1;
+}
+
+int cmp4(int d1, int d2) {
+  if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
+    return 0;
+  return 1;
+}
+
+int cmp1_64(uint64_t d1, uint64_t d2) {
+  if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
+    return 0;
+  return 1;
+}
+
+int cmp2_64(uint64_t d1, uint64_t d2) {
+  if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
+    return 0;
+  return 1;
+}
+
+int cmp3_64(uint64_t d1, uint64_t d2) {
+  if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
+    return 0;
+  return 1;
+}
+
+int cmp4_64(uint64_t d1, uint64_t d2) {
+  if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
+    return 0;
+  return 1;
+}
+
+/* The if should be removed, so the condition should not exist */
+/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." 
"optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
new file mode 100644
index 000000000000..c55cfbcc84c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(int d1, int d2) {
+  if ((d1 ^ d2) == 0xabcd || d1 != d2)
+    return 0;
+  return 1;
+}
+
+int cmp2(int d1, int d2) {
+  if (d1 != d2 || (d1 ^ d2) == 0xabcd)
+    return 0;
+  return 1;
+}
+
+int cmp3(int d1, int d2) {
+  if (0xabcd > (d2 ^ d1) || d2 != d1)
+    return 0;
+  return 1;
+}
+
+int cmp4(int d1, int d2) {
+  if (d2 != d1 || 0xabcd > (d2 ^ d1))
+    return 0;
+  return 1;
+}
+
+int cmp1_64(uint64_t d1, uint64_t d2) {
+  if ((d1 ^ d2) == 0xabcd || d1 != d2)
+    return 0;
+  return 1;
+}
+
+int cmp2_64(uint64_t d1, uint64_t d2) {
+  if (d1 != d2 || (d1 ^ d2) == 0xabcd)
+    return 0;
+  return 1;
+}
+
+int cmp3_64(uint64_t d1, uint64_t d2) {
+  if (0xabcd > (d2 ^ d1) || d2 != d1)
+    return 0;
+  return 1;
+}
+
+int cmp4_64(uint64_t d1, uint64_t d2) {
+  if (d2 != d1 || 0xabcd > (d2 ^ d1))
+    return 0;
+  return 1;
+}
+
+/* The if should be removed, so the condition should not exist */
+/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." 
"optimized" } } */

Reply via email to