This is a follow-up to the -O1 patch for PR112533.

At -O2, GCC lowers (~x & 1) == (~y & 1) via inlining into:
  _14 = ~x;
  _12 = (bool) _14;
  _13 = ~y;
  _9  = (bool) _13;
  _8  = _9 == _12;

The NOT cancellation (~x == ~y -> x == y) is handled by existing
forwprop rules before this rule fires.

Add match.pd rule for eq and ne:

  (T)(x) == (T)(y) -> (T)(x ^ y) == 0
  (T)(x) != (T)(y) -> (T)(x ^ y) != 0

Bootstrapped and regression tested on aarch64-linux-gnu with
RUNTESTFLAGS="tree-ssa.exp".

Changes since v1:
* v3: Simplify match rule.
      Add more cases in test file.
* v2: Generalize the match rule to generic narrowing
      integral equality comparisons from bool equality.

        PR tree-optimization/112533

gcc/ChangeLog:
        * match.pd: Add generic narrowing eq/ne to XOR-against-zero
        rule for (T)(x) == (T)(y) where precision(T) < precision(x).

gcc/testsuite/ChangeLog:
        * gcc.dg/tree-ssa/narrow-eq-simplify.c: New test covering
        bool parity and short truncation cases.

Signed-off-by: Shivam Gupta <[email protected]>
---
 gcc/match.pd                                  | 14 +++
 .../gcc.dg/tree-ssa/narrow-eq-simplify.c      | 87 +++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c

diff --git a/gcc/match.pd b/gcc/match.pd
index ff13a07ea94..7f15a475f98 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2033,6 +2033,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && element_precision (type) <= element_precision (TREE_TYPE (@1)))
   (bit_xor (convert @0) (convert @1))))
 
+/* For narrowing integral conversions:
+   (T)(X) == (T)(Y) -> (T)(X ^ Y) == 0
+   (T)(X) != (T)(Y) -> (T)(X ^ Y) != 0  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (convert@0 @00) (convert@1 @10))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@00))
+       && types_match (@00, @10)
+       && TYPE_PRECISION (TREE_TYPE (@0))
+            < TYPE_PRECISION (TREE_TYPE (@00)))
+   (with { tree itype = TREE_TYPE (@0); }
+    (cmp (convert:itype (bit_xor @00 @10))
+         { build_zero_cst (itype); })))))
+
 /* Convert ~X ^ C to X ^ ~C.  */
 (simplify
  (bit_xor (convert? (bit_not @0)) INTEGER_CST@1)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c 
b/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
new file mode 100644
index 00000000000..117c7f937b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Verify the fix for PR112533 at -O2.
+   (~a & 1) == (~a & 1) is lowered via inlining to
+   (bool)(~a) == (bool)(~b), then existing forwprop rules cancel
+   the NOTs giving (bool)(a) == (bool)(b), which this rule
+   simplifies to (bool)(a ^ b) == 0.  */
+
+typedef unsigned int u32;
+
+static _Bool
+is_even (u32 a)
+{
+  return a % 2 == 0;
+}
+
+_Bool
+same_evenness (u32 a, u32 b)
+{
+  return is_even (a) == is_even (b);
+}
+
+_Bool
+diff_evenness (u32 a, u32 b)
+{
+  return is_even (a) != is_even (b);
+}
+
+short
+eq_short_not (int a, int b)
+{
+  short sa = ~a;
+  short sb = ~b;
+  return sa == sb;
+}
+
+short
+ne_short_not (int a, int b)
+{
+  short sa = ~a;
+  short sb = ~b;
+  return sa != sb;
+}
+
+unsigned char
+eq_uchar (unsigned int a, unsigned int b)
+{
+  unsigned char sa = a;
+  unsigned char sb = b;
+  return sa == sb;
+}
+
+signed char
+ne_schar (int a, int b)
+{
+  signed char sa = a;
+  signed char sb = b;
+  return sa != sb;
+}
+
+int
+eq_int_from_ll (long long a, long long b)
+{
+  int ia = a;
+  int ib = b;
+  return ia == ib;
+}
+
+int
+eq_int_no_narrow (int a, int b)
+{
+  int ia = a;
+  int ib = b;
+  return ia == ib;
+}
+
+long long
+eq_widen (int a, int b)
+{
+  long long la = a;
+  long long lb = b;
+  return la == lb;
+}
+
+/* Verify the XOR form is produced for narrowing comparison.  */
+/* { dg-final { scan-tree-dump-times "\\\^" 7 "optimized" } } */
-- 
2.34.1

Reply via email to