From: kelefth <[email protected]>
In expressions like (a != b || ((a ^ b) & CST0) == CST1) and
(a != b || (a ^ b) == CST), (a ^ b) is folded to false.
In the equivalent expressions (((a ^ b) & CST0) == CST1 || a != b) and
((a ^ b) == CST, (a ^ b) || a != b) this is not happening.
This patch adds the following simplifications in match.pd:
((a ^ b) & CST0) == CST1 || a != b --> 0 == (CST1 || a != b)
(a ^ b) == CST || a != b --> 0 == CST || (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-1.c: New test.
* gcc.dg/tree-ssa/fold-xor-and-or-2.c: New test.
* gcc.dg/tree-ssa/fold-xor-or-1.c: New test.
* gcc.dg/tree-ssa/fold-xor-or-2.c: New test.
Reviewed-by: Christoph Müllner <[email protected]>
Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Konstantinos Eleftheriou <[email protected]>
---
gcc/match.pd | 30 +++++++++++++++++++
.../gcc.dg/tree-ssa/fold-xor-and-or-1.c | 17 +++++++++++
.../gcc.dg/tree-ssa/fold-xor-and-or-2.c | 19 ++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c | 17 +++++++++++
gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-2.c | 19 ++++++++++++
5 files changed, 102 insertions(+)
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-and-or-2.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-2.c
diff --git a/gcc/match.pd b/gcc/match.pd
index c9c8478d286..1c55bd72f09 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -10680,3 +10680,33 @@ and,
}
(if (full_perm_p)
(vec_perm (op@3 @0 @1) @3 @2))))))
+
+/* ((a ^ b) & CST0) == CST1 || a != b --> 0 == (CST1 || a != b). */
+(for cmp (simple_comparison)
+ (simplify
+ (bit_ior
+ (cmp
+ (bit_and
+ (bit_xor @0 @1)
+ INTEGER_CST)
+ @3)
+ (ne@4 @0 @1))
+ (bit_ior
+ (cmp
+ { build_zero_cst (TREE_TYPE (@0)); }
+ @3)
+ @4)))
+
+/* (a ^ b) == CST || a != b --> 0 == CST || (a != b). */
+(for cmp (simple_comparison)
+ (simplify
+ (bit_ior
+ (cmp
+ (bit_xor @0 @1)
+ @2)
+ (ne@3 @0 @1))
+ (bit_ior
+ (cmp
+ {build_zero_cst (TREE_TYPE (@0)); }
+ @2)
+ @3)))
\ No newline at end of file
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..0e6fc1d5515
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+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;
+}
+
+/* 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-and-or-2.c
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-2.c
new file mode 100644
index 00000000000..3f8da111354
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(uint64_t d1, uint64_t d2) {
+ if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2(uint64_t d1, uint64_t d2) {
+ if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
+ 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..0bc849a2d74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+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;
+}
+
+/* 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-2.c
b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-2.c
new file mode 100644
index 00000000000..2276fc1c2ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(uint64_t d1, uint64_t d2) {
+ if ((d1 ^ d2) == 0xabcd || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2(uint64_t d1, uint64_t d2) {
+ if (d1 != d2 || (d1 ^ d2) == 0xabcd)
+ 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" } } */
--
2.46.0