This adds the simplification of:
_1 = ~x_4(D);
_2 = _1 & y_5(D);
_3 = x_4(D) | y_5(D);
_6 = _2 ^ _3;
return _6;
to:
return x_1(D);
also for ((~x) | y) ^ (x & y) version
_1 = ~x_4(D);
_2 = _1 | y_5(D);
_3 = x_4(D) & y_5(D);
_6 = _2 ^ _3;
return _6;
to:
int _2;
_2 = ~x_1(D);
return _2;
Bootstrapped and tested on aarch64-linux-gnu with
RUNTESTFLAGS="tree-ssa.exp".
PR tree-optimization/112095
gcc/ChangeLog:
* match.pd: Simplify ((~x) & y) ^ (x | y)
to x and ((~x) | y) ^ (x & y) to ~x.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr112095.c: New test.
Signed-off-by: Shivam Gupta <[email protected]>
---
gcc/match.pd | 9 +++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr112095.c | 19 +++++++++++++++++++
2 files changed, 28 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr112095.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 7b652afb43d..08df727ea9d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2627,6 +2627,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(negate (nop_convert? (bit_not @0)))
(plus (view_convert @0) { build_each_one_cst (type); }))
+/* ((~a) & b) ^ (a | b) -> a */
+/* ((~a) | b) ^ (a & b) -> ~a */
+(simplify
+ (bit_xor:c (bit_ior:c @0 @1) (bit_and:c @2 @1))
+ (with { bool wascmp; }
+ (if (bitwise_inverted_equal_p (@0, @2, wascmp)
+ && (!wascmp || element_precision (type) == 1))
+ @0)))
+
/* (a & b) ^ (a == b) -> !(a | b) */
/* (a & b) == (a ^ b) -> !(a | b) */
(for first_op (bit_xor eq)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112095.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr112095.c
new file mode 100644
index 00000000000..126705d7731
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112095.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+int
+f (int a, int b)
+{
+ return ((~a) & b) ^ (a | b);
+}
+
+int
+g (int a, int b)
+{
+ return ((~a) | b) ^ (a & b);
+}
+
+/* Above patterns should simplify to a and ~a respectively. */
+/* { dg-final { scan-tree-dump "return a_" "optimized" } } */
+/* { dg-final { scan-tree-dump "~a_" "optimized" } } */
+
--
2.34.1