On Sun, Aug 16, 2026 at 4:12 AM Andrea Pinski
<[email protected]> wrote:
>
> 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.

Nice.

OK.

THanks,
Richard.

>         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
>

Reply via email to