[PATCH 1/2] match/fold: Add support for NE, XOR, and EQ to combine_comparisons [PR107881]

Andrea Pinski <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
This adds support for !=, ^ and == to combine_comparisons and
uses combine_comparisons in match for those cases instead of what
was previously there. This allows for floating point comparisons to
be merged in some more cases. And simplifies the match code to read.
Also moves up the match pattern that uses combine_comparisons to
above the other comparisons combines so it is matched first.

Bootstrapped and tested on x86_64-linux-gnu.

	PR tree-optimization/107881

gcc/ChangeLog:

	* fold-const.cc (combine_comparisons): Add support for
	NE/XOR and EQ.
	* match.pd (`(a CMP1 b) OP (a CMP2 b)`): Move
	above others and add NE, XOR and EQ to the list of OPs.
	(`(a CMP1 b) ^ (a CMP2 b)`): Remove.
	(`(a CMP1 b) == (a CMP2 b)`): Remove.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/cmpeq-5.c: New test.
	* gcc.dg/tree-ssa/cmpxor-2.c: New test.

Signed-off-by: Andrea Pinski <[email protected]>
---
 gcc/fold-const.cc                        |  9 ++++
 gcc/match.pd                             | 68 +++++++-----------------
 gcc/testsuite/gcc.dg/tree-ssa/cmpeq-5.c  | 51 ++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/cmpxor-2.c | 51 ++++++++++++++++++
 4 files changed, 131 insertions(+), 48 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpeq-5.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpxor-2.c

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 420e3185a2a..dd6ce48f89a 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2964,6 +2964,15 @@ combine_comparisons (enum tree_code code, enum tree_code lcode,
       compcode = lcompcode | rcompcode;
       break;
 
+    case BIT_XOR_EXPR:
+    case NE_EXPR:
+      compcode = lcompcode ^ rcompcode;
+      break;
+
+    case EQ_EXPR:
+      compcode = (~(lcompcode ^ rcompcode)) & 0xf;
+      break;
+
     default:
       return ERROR_MARK;
     }
diff --git a/gcc/match.pd b/gcc/match.pd
index 02684d8a302..f8251885a7c 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3619,6 +3619,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
   (gt @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }))))
 
+/* Optimize (a CMP b) &| (a CMP b)
+   using the helper combine_comparisons function.  */
+(for bitop (bit_and bit_ior bit_xor ne eq)
+ (for cmp1 (tcc_comparison)
+  (for cmp2 (tcc_comparison)
+   (for rcmp (tcc_comparison)
+    (simplify
+     (bitop (cmp1 @0 @1) (cmp2 @0 @1))
+     (with {
+       tree_code rescode;
+       tree res;
+       bool honor_nans = HONOR_NANS (@0);
+       rescode = combine_comparisons (bitop, cmp1, cmp2,
+				      type, honor_nans, &res);
+      }
+      (if (rescode == INTEGER_CST)
+       { res; }
+       (if (rescode == rcmp)
+        (rcmp @0 @1)))))))))
+
 /* Convert (X == CST1) && ((other)X OP2 CST2) to a known value
    based on CST1 OP2 CST2.  Similarly for (X != CST1).  */
 /* Convert (X == Y) && (X OP2 Y) to a known value if X is an integral type.
@@ -3904,54 +3924,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       { constant_boolean_node (true, type); })
      ))))))
 
-/* Optimize (a CMP b) ^ (a CMP b)  */
-/* Optimize (a CMP b) != (a CMP b)  */
-(for op (bit_xor ne)
- (for cmp1 (lt lt lt le le le)
-      cmp2 (gt eq ne ge eq ne)
-      rcmp (ne le gt ne lt ge)
-  (simplify
-   (op:c (cmp1:c @0 @1) (cmp2 @0 @1))
-   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
-      || POINTER_TYPE_P (TREE_TYPE (@0))
-      || ((VECTOR_INTEGER_TYPE_P (TREE_TYPE (@1))
-	   || VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (@1)))
-      && expand_vec_cmp_expr_p (TREE_TYPE (@0), type, rcmp)))
-    (rcmp @0 @1)))))
-
-/* Optimize (a CMP b) == (a CMP b)  */
-(for cmp1 (lt lt lt le le le)
-     cmp2 (gt eq ne ge eq ne)
-     rcmp (eq gt le eq ge lt)
- (simplify
-  (eq:c (cmp1:c @0 @1) (cmp2 @0 @1))
-  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
-		|| POINTER_TYPE_P (TREE_TYPE (@0))
-      || ((VECTOR_INTEGER_TYPE_P (TREE_TYPE (@1))
-	   || VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (@1)))
-      && expand_vec_cmp_expr_p (TREE_TYPE (@0), type,  rcmp)))
-    (rcmp @0 @1))))
-
-/* Optimize (a CMP b) &| (a CMP b)
-   using the helper combine_comparisons function.  */
-(for bitop (bit_and bit_ior)
- (for cmp1 (tcc_comparison)
-  (for cmp2 (tcc_comparison)
-   (for rcmp (tcc_comparison)
-    (simplify
-     (bitop (cmp1 @0 @1) (cmp2 @0 @1))
-     (with {
-       tree_code rescode;
-       tree res;
-       bool honor_nans = HONOR_NANS (@0);
-       rescode = combine_comparisons (bitop, cmp1, cmp2,
-				      type, honor_nans, &res);
-      }
-      (if (rescode == INTEGER_CST)
-       { res; }
-       (if (rescode == rcmp)
-        (rcmp @0 @1)))))))))
-
 /* (type)([0,1]@a != 0) -> (type)a
    (type)([0,1]@a == 1) -> (type)a
    (type)([0,1]@a == 0) -> a ^ 1
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-5.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-5.c
new file mode 100644
index 00000000000..16dc35ca39e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-5.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math" } */
+/* PR tree-optimization/107881 */
+
+_Bool ltgt_eq(float a, float b)
+{
+  _Bool c = a < b;
+  _Bool d = a > b;
+  return c == d; // a u== b
+}
+/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. u== b_\[0-9\]+.D.|b_\[0-9\]+.D. u== a_\[0-9\]+.D." "optimized" } } */
+
+_Bool lteq_eq(float x, float y)
+{
+  _Bool c = x < y;
+  _Bool d = x == y;
+  return c == d; // x u> y
+}
+/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. u> y_\[0-9\]+.D.|y_\[0-9\]+.D. u< x_\[0-9\]+.D." "optimized" } } */
+
+_Bool ltne_eq(float z, float w)
+{
+  _Bool c = z < w;
+  _Bool d = z != w;
+  return c == d; // z <= w
+}
+/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. <= w_\[0-9\]+.D.|w_\[0-9\]+.D. >= y_\[0-9\]+.D." "optimized" } } */
+
+_Bool lege_eq(float i, float j)
+{
+  _Bool c = i <= j;
+  _Bool d = i >= j;
+  return c == d; // i u== j
+}
+/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. u== j_\[0-9\]+.D.|j_\[0-9\]+.D. u== i_\[0-9\]+.D." "optimized" } } */
+
+_Bool leeq_eq(float k, float l)
+{
+  _Bool c = k <= l;
+  _Bool d = k == l;
+  return c == d; // k u>= l
+}
+/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. u>= l_\[0-9\]+.D.|l_\[0-9\]+.D. u<= k_\[0-9\]+.D." "optimized" } } */
+
+_Bool lene_eq(float m, float n)
+{
+  _Bool c = m <= n;
+  _Bool d = m != n;
+  return c == d; // m < n
+}
+/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. < n_\[0-9\]+.D.|n_\[0-9\]+.D. > m_\[0-9\]+.D." "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-2.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-2.c
new file mode 100644
index 00000000000..00fa7120237
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-2.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math" } */
+/* PR tree-optimization/107881 */
+
+_Bool ltgtxor(float a, float b)
+{
+  _Bool c = a < b;
+  _Bool d = a > b;
+  return c ^ d; // a <> b
+}
+/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. <> b_\[0-9\]+.D.|b_\[0-9\]+.D. <> a_\[0-9\]+.D." "optimized" } } */
+
+_Bool lteqxor(float x, float y)
+{
+  _Bool c = x < y;
+  _Bool d = x == y;
+  return c ^ d; // x <= y (basically | here)
+}
+/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. <= y_\[0-9\]+.D.|y_\[0-9\]+.D. >= x_\[0-9\]+.D." "optimized" } } */
+
+_Bool ltnexor(float z, float w)
+{
+  _Bool c = z < w;
+  _Bool d = z != w;
+  return c ^ d; // z u> w
+}
+/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. u> w_\[0-9\]+.D.|w_\[0-9\]+.D. u< y_\[0-9\]+.D." "optimized" } } */
+
+_Bool legexor(float i, float j)
+{
+  _Bool c = i <= j;
+  _Bool d = i >= j;
+  return c ^ d; // i <> j
+}
+/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. <> j_\[0-9\]+.D.|j_\[0-9\]+.D. <> i_\[0-9\]+.D." "optimized" } } */
+
+_Bool leeqxor(float k, float l)
+{
+  _Bool c = k <= l;
+  _Bool d = k == l;
+  return c ^ d; // k < l
+}
+/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. < l_\[0-9\]+.D.|l_\[0-9\]+.D. > k_\[0-9\]+.D." "optimized" } } */
+
+_Bool lenexor(float m, float n)
+{
+  _Bool c = m <= n;
+  _Bool d = m != n;
+  return c ^ d; // m u>= n
+}
+/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. u>= n_\[0-9\]+.D.|n_\[0-9\]+.D. u<= m_\[0-9\]+.D." "optimized" } } */
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.