Recognize XOR patterns involving zero_one_valued operands compared
against zero and simplify them to direct equality or inequality tests.
Specifically:
(a == 0) ^ (b != 0) -> a == b
(a != 0) ^ (b == 0) -> a == b
(a == 0) ^ (b == 0) -> a != b
(a != 0) ^ (b != 0) -> a != b
Also handle a specific case:
(a == 0) ^ b -> b != (a ^ 1)
Regression tested on aarch64-linux-gnu.
gcc/ChangeLog:
* match.pd: Add simplifications for XORs of zero_one_valued
comparisons against zero.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/bool-eq-bitxor.c: Update expected number
of optimized XOR forms.
* gcc.dg/tree-ssa/bool-xor-zero-one-valued.c: New test.
Signed-off-by: Shivam Gupta <[email protected]>
---
gcc/match.pd | 29 +++++++++++++++
.../gcc.dg/tree-ssa/bool-eq-bitxor.c | 4 +-
.../tree-ssa/bool-xor-zero-one-valued.c | 37 +++++++++++++++++++
3 files changed, 67 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 228bab78428..1be34516338 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3765,6 +3765,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (types_match (type, TREE_TYPE (@0)))
(bit_xor @0 { build_one_cst (type); } ))))))
+/* For zero_one_valued operands:
+ (a == 0) != b -> b != (a ^ 1). */
+(simplify
+ (ne (convert:s (eq zero_one_valued_p@0 integer_zerop))
+ (convert:s zero_one_valued_p@1))
+ (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (ne @1 (bit_xor @0 { build_one_cst (TREE_TYPE (@0)); }))))
+
+/* For zero_one_valued operands:
+ (a == 0) != (b != 0) -> a == b
+ (a != 0) != (b == 0) -> a == b. */
+(for op1 (eq ne)
+ op2 (ne eq)
+ (simplify
+ (ne:c (op1 zero_one_valued_p@0 integer_zerop)
+ (op2 zero_one_valued_p@1 integer_zerop))
+ (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (eq @0 @1))))
+
+/* For zero_one_valued operands:
+ (a == 0) != (b == 0) -> a != b
+ (a != 0) != (b != 0) -> a != b. */
+(for op (eq ne)
+ (simplify
+ (ne:c (op zero_one_valued_p@0 integer_zerop)
+ (op zero_one_valued_p@1 integer_zerop))
+ (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (ne @0 @1))))
+
/* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
(for cmp (simple_comparison)
(simplify
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
index bc263e80977..e39e82589b6 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-eq-bitxor.c
@@ -36,7 +36,5 @@ xor_ne_ne (u32 a, u32 b)
}
/* Verify all functions canonicalize to xor-mask tests. */
-/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) \\^ b_\[0-9\]+\\(D\\)"
3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) \\^ b_\[0-9\]+\\(D\\)"
4 "optimized" } } */
-/* xor_eq_ne not optimized yet due to zero_one_valued_p canonicalization. */
-/* { dg-final { scan-tree-dump-times "& 1" 2 "optimized" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
b/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
new file mode 100644
index 00000000000..71f70f3cf0c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-xor-zero-one-valued.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+_Bool
+f1 (unsigned a, unsigned b)
+{
+ if (a != 0 && a != 1) __builtin_unreachable();
+ if (b != 0 && b != 1) __builtin_unreachable();
+ return (a == 0) ^ (b != 0);
+}
+
+_Bool
+f2 (unsigned a, unsigned b)
+{
+ if (a != 0 && a != 1) __builtin_unreachable();
+ if (b != 0 && b != 1) __builtin_unreachable();
+ return (a != 0) ^ (b == 0);
+}
+
+_Bool
+f3 (unsigned a, unsigned b)
+{
+ if (a != 0 && a != 1) __builtin_unreachable();
+ if (b != 0 && b != 1) __builtin_unreachable();
+ return (a == 0) ^ (b == 0);
+}
+
+_Bool
+f4 (unsigned a, unsigned b)
+{
+ if (a != 0 && a != 1) __builtin_unreachable();
+ if (b != 0 && b != 1) __builtin_unreachable();
+ return (a != 0) ^ (b != 0);
+}
+
+/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) == b_\[0-9\]+\\(D\\)"
2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "a_\[0-9\]+\\(D\\) != b_\[0-9\]+\\(D\\)"
2 "optimized" } } */
--
2.34.1