Turns out it was easy to fix these patterns for
`--param=logical-op-non-short-circuit=0` case after all.
Just add support for `((a ^ b) & c) cmp d && a == b`
which is the same as `!(((a ^ b) & c) cmp d || a != b)`.
So this adds the bit_and case to support exactly that.
Also fixes up some of the `:c` on the operands.
`:c` needs to be on the outer bitop and does not need to be
on the inner one for bit_xor as it will be the same order as ne/eq.

gcc/ChangeLog:

        * match.pd (`((a ^ b) & c) cmp d || a != b`): Expand
        to support bit_and and fix up the :c.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/fold-xor-and-or-1.c: New test.
        * gcc.dg/tree-ssa/fold-xor-or-1.c: New test.
        * gcc.dg/tree-ssa/pr102793-1.c: Update for the optimization
        happening in pre.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/match.pd                                  | 32 ++++++-----
 .../gcc.dg/tree-ssa/fold-xor-and-or-1.c       | 55 +++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c | 55 +++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c    | 10 +++-
 4 files changed, 134 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-1.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 7da15cc4cdc..07fbb91eeb1 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3820,35 +3820,37 @@ 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)
+/* ((a ^ b) & c) cmp d && a == b --> (0 cmp d && a == b). */
+(for bitop (bit_ior bit_and)
+     neeq  (ne      eq)
+ (for cmp  (simple_comparison)
   (simplify
-    (bit_ior
+    (bitop:c
       (cmp:c
        (bit_and:c
-         (bit_xor:c @0 @1)
+         (bit_xor @0 @1)
          tree_expr_nonzero_p@2)
        @3)
-      (ne@4 @0 @1))
-    (bit_ior
+      (neeq@4 @0 @1))
+    (bitop
       (cmp
        { build_zero_cst (TREE_TYPE (@0)); }
        @3)
-      @4)))
-
+      @4))
 /* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
-(for cmp (simple_comparison)
+/* (a ^ b) cmp c && a == b --> (0 cmp c || a == b). */
   (simplify
-    (bit_ior
+    (bitop:c
       (cmp:c
-       (bit_xor:c @0 @1)
+       (bit_xor @0 @1)
        @2)
-      (ne@3 @0 @1))
-    (bit_ior
+      (neeq@3 @0 @1))
+    (bitop
       (cmp
-       { build_zero_cst (TREE_TYPE (@0)); }
-       @2)
-      @3)))
+       { 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-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-1.c
new file mode 100644
index 00000000000..609532b9599
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized --param 
logical-op-non-short-circuit=0" } */
+
+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-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c
new file mode 100644
index 00000000000..be66dec523c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized --param 
logical-op-non-short-circuit=0" } */
+
+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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c
index 436b4e4bf05..c4c84dcbb46 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102793-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -fdump-tree-pre --param logical-op-non-short-circuit=1" } 
*/
+/* { dg-options "-O3 -fdump-tree-pre -fdump-tree-optimized --param 
logical-op-non-short-circuit=1" } */
 
 typedef __UINT64_TYPE__ uint64_t;
 
@@ -45,5 +45,9 @@ int noccmp1(uint64_t* s1, uint64_t* s2)
     return 0;
 }
 
-/* Check for condition assignments for noccmp0 and noccmp1.  */
-/* { dg-final { scan-tree-dump-times {_\d+ = d\d+_\d+ != d\d+_\d+;\n  _\d+ = 
bar_\d+ == 0;} 2 "pre" } } */
+/* Check for condition assignments for noccmp1 and noccmp0.  */
+/* { dg-final { scan-tree-dump-times {_\d+ = d\d+_\d+ != d\d+_\d+;\n  _\d+ = 
bar_\d+ == 0;} 1 "pre" } } */
+/* { dg-final { scan-tree-dump-times "optimizing two comparisons " 2 "pre" } } 
*/
+/* The conditional in noccmp1 should be optimized in pre */
+/* { dg-final { scan-tree-dump-times " if " 1 "pre" } } */
+/* { dg-final { scan-tree-dump-times " if " 1 "optimized" } } */
-- 
2.43.0

Reply via email to