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".
PR tree-optimization/112533
Changes since v1:
* v4: Moved match rule to right place alongside other
simple_comparison narrowing cases.
* v3: Simplify match rule.
Add more cases in test file.
* v2: Generalize the match rule to generic narrowing
integral equality comparisons from bool equality.
gcc/ChangeLog:
* match.pd: Add integral 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 for
narrowing integral eq/ne simplification.
Signed-off-by: Shivam Gupta <[email protected]>
---
gcc/match.pd | 14 ++-
.../gcc.dg/tree-ssa/narrow-eq-simplify.c | 95 +++++++++++++++++++
2 files changed, 108 insertions(+), 1 deletion(-)
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..195d10c80c7 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -7804,7 +7804,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (cmp == LT_EXPR || cmp == LE_EXPR)
{ constant_boolean_node (above ? true : false, type); }
(if (cmp == GT_EXPR || cmp == GE_EXPR)
- { constant_boolean_node (above ? false : true, type); })))))))))
+ { constant_boolean_node (above ? false : true, type); })))))))
+
+ /* For eq/ne with narrowing conversion:
+ (T)(X) == (T)(Y) -> (T)(X ^ Y) == 0 */
+ (if (TYPE_PRECISION (TREE_TYPE (@0))
+ < TYPE_PRECISION (TREE_TYPE (@00))
+ && (cmp == EQ_EXPR || cmp == NE_EXPR)
+ && types_match (TREE_TYPE (@00),
+ TREE_TYPE (@10)))
+ (with { tree itype = TREE_TYPE (@0); }
+ (cmp (convert:itype (bit_xor @00 @10))
+ { build_zero_cst (itype); })))))
+
/* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
(if (FLOAT_TYPE_P (TREE_TYPE (@00))
&& (DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0))
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..6e48e40dd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/narrow-eq-simplify.c
@@ -0,0 +1,95 @@
+/* { 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;
+}
+
+int
+eq_float_no_xor (double a, double b)
+{
+ float fa = a;
+ float fb = b;
+ return fa == fb;
+}
+
+/* Verify the XOR form is produced for integral narrowing comparisons. */
+/* { dg-final { scan-tree-dump-times "\\\^" 7 "optimized" } } */
--
2.34.1