On Fri, Jul 3, 2026 at 12:47 AM Richard Biener
<[email protected]> wrote:
>
> On Wed, Jul 1, 2026 at 7:12 AM Andrew Pinski
> <[email protected]> wrote:
> >
> > This finishes up simplifications of most comparisons
> > outside of reassiocation. Including but not limited to
> > many floating point comparisons.
> > Instead of Redoig what is done in fold-cost.cc's combine_comparisons,
> > this reuses combine_comparisons to find the new CMP.
> >
> > In the case of `-fno-trapping-math`, this allows to optimize `<=>`
> > which it was not before.
>
> OK with the typo fixes.
>
> I wonder how much of forwprop combine_cond_expr_cond dispatch
> to GENERIC folding still results in sth that match cannot handle?

There are still some, I recorded them in https://gcc.gnu.org/PR120206 already.
If I get some time after finishing up the phiopt/cselim/factor
improvements I am currently working on, I will get back to trying to
remove forward_propagate_into_comparison/combine_cond_expr_cond.

Anyways here is the patch I pushed. I also added a C testcase and
fixed the typos.

Thanks,
Andrea


>
> Richard.
>
> > Bootstrapped and tested on x86_64-linux-gnu.
> >
> >         PR tree-optimization/106164
> >         PR tree-optimization/126042
> >         PR tree-optimization/94589
> >
> > gcc/ChangeLog:
> >
> >         * fold-const.cc (combine_comparisons): Split into
> >         2 versions. Also handle BIT_AND_EXPR and BIT_IOR_EXPR.
> >         * fold-const.h (combine_comparisons): New declaration.
> >         * match.pd (`(a CMP1 b) BITOP (a CMP2 b)`): New pattern.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * g++.dg/opt/pr94589-5a.C: New test.
> >
> > Signed-off-by: Andrew Pinski <[email protected]>
> > ---
> >  gcc/fold-const.cc                     | 65 ++++++++++++++++++---------
> >  gcc/fold-const.h                      |  2 +
> >  gcc/match.pd                          | 20 +++++++++
> >  gcc/testsuite/g++.dg/opt/pr94589-5a.C | 27 +++++++++++
> >  4 files changed, 93 insertions(+), 21 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-5a.C
> >
> > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> > index 11d1129f125..899212bfdff 100644
> > --- a/gcc/fold-const.cc
> > +++ b/gcc/fold-const.cc
> > @@ -2935,35 +2935,37 @@ inverse_conditions_p (const_tree cond1, const_tree 
> > cond2)
> >                               TREE_OPERAND (cond2, 1), 0));
> >  }
> >
> > -/* Return a tree for the comparison which is the combination of
> > +/* Return a coide for the comparison which is the combination of
> >     doing the AND or OR (depending on CODE) of the two operations LCODE
> >     and RCODE on the identical operands LL_ARG and LR_ARG.  Take into 
> > account
> > -   the possibility of trapping if the mode has NaNs, and return NULL_TREE
> > -   if this makes the transformation invalid.  */
> > +   the possibility of trapping if the mode has NaNs, and return ERROR_MARK
> > +   if this makes the transformation invalid. If the resulting code is
> > +   INTEGER_CST, then *RES will be set to a non-NULL CONSTANT.  */
> >
> > -tree
> > -combine_comparisons (location_t loc,
> > -                    enum tree_code code, enum tree_code lcode,
> > -                    enum tree_code rcode, tree truth_type,
> > -                    tree ll_arg, tree lr_arg)
> > +enum tree_code
> > +combine_comparisons (enum tree_code code, enum tree_code lcode,
> > +                      enum tree_code rcode, tree truth_type,
> > +                      bool honor_nans, tree *res)
> >  {
> > -  bool honor_nans = HONOR_NANS (ll_arg);
> >    enum comparison_code lcompcode = comparison_to_compcode (lcode);
> >    enum comparison_code rcompcode = comparison_to_compcode (rcode);
> >    int compcode;
> > +  *res = NULL_TREE;
> >
> >    switch (code)
> >      {
> >      case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR:
> > +    case BIT_AND_EXPR:
> >        compcode = lcompcode & rcompcode;
> >        break;
> >
> >      case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR:
> > +    case BIT_IOR_EXPR:
> >        compcode = lcompcode | rcompcode;
> >        break;
> >
> >      default:
> > -      return NULL_TREE;
> > +      return ERROR_MARK;
> >      }
> >
> >    if (!honor_nans)
> > @@ -3004,24 +3006,45 @@ combine_comparisons (location_t loc,
> >            trapped, we may now generate a spurious trap.  */
> >         if (rtrap && !ltrap
> >             && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
> > -         return NULL_TREE;
> > +         return ERROR_MARK;
> >
> >         /* If we changed the conditions that cause a trap, we lose.  */
> >         if ((ltrap || rtrap) != trap)
> > -         return NULL_TREE;
> > +         return ERROR_MARK;
> >        }
> >
> > -  if (compcode == COMPCODE_TRUE)
> > -    return constant_boolean_node (true, truth_type);
> > -  else if (compcode == COMPCODE_FALSE)
> > -    return constant_boolean_node (false, truth_type);
> > -  else
> > +  if (compcode == COMPCODE_TRUE || compcode == COMPCODE_FALSE)
> >      {
> > -      enum tree_code tcode;
> > -
> > -      tcode = compcode_to_comparison ((enum comparison_code) compcode);
> > -      return fold_build2_loc (loc, tcode, truth_type, ll_arg, lr_arg);
> > +      *res = constant_boolean_node (compcode == COMPCODE_TRUE, truth_type);
> > +      return INTEGER_CST;
> >      }
> > +  else
> > +    return compcode_to_comparison ((enum comparison_code) compcode);
> > +}
> > +
> > +/* Return a tree for the comparison which is the combination of
> > +   doing the AND or OR (depending on CODE) of the two operations LCODE
> > +   and RCODE on the identical operands LL_ARG and LR_ARG.  Take into 
> > account
> > +   the possibility of trapping if the mode has NaNs, and return NULL_TREE
> > +   if this makes the transformation invalid.  */
> > +
> > +tree
> > +combine_comparisons (location_t loc,
> > +                    enum tree_code code, enum tree_code lcode,
> > +                    enum tree_code rcode, tree truth_type,
> > +                    tree ll_arg, tree lr_arg)
> > +{
> > +  bool honor_nans = HONOR_NANS (ll_arg);
> > +  tree_code rescode;
> > +  tree res;
> > +  rescode = combine_comparisons (code, lcode, rcode, truth_type,
> > +                                honor_nans, &res);
> > +  if (rescode == ERROR_MARK)
> > +    return NULL_TREE;
> > +  if (rescode == INTEGER_CST)
> > +    return res;
> > +
> > +  return fold_build2_loc (loc, rescode, truth_type, ll_arg, lr_arg);
> >  }
> >
> >  /* Return nonzero if two operands (typically of the same tree node)
> > diff --git a/gcc/fold-const.h b/gcc/fold-const.h
> > index 57d32b1b6ca..8c0c3edba17 100644
> > --- a/gcc/fold-const.h
> > +++ b/gcc/fold-const.h
> > @@ -175,6 +175,8 @@ extern bool fold_real_zero_addition_p (const_tree, 
> > const_tree, const_tree,
> >                                        int);
> >  extern tree combine_comparisons (location_t, enum tree_code, enum 
> > tree_code,
> >                                  enum tree_code, tree, tree, tree);
> > +extern tree_code combine_comparisons (enum tree_code, enum tree_code,
> > +                                     enum tree_code, tree, bool, tree*);
> >  extern void debug_fold_checksum (const_tree);
> >  extern bool may_negate_without_overflow_p (const_tree);
> >  #define round_up(T,N) round_up_loc (UNKNOWN_LOCATION, T, N)
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index ddf3b61638c..87695d9d667 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -3784,6 +3784,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >        && 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/g++.dg/opt/pr94589-5a.C 
> > b/gcc/testsuite/g++.dg/opt/pr94589-5a.C
> > new file mode 100644
> > index 00000000000..d1c9b56b414
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/opt/pr94589-5a.C
> > @@ -0,0 +1,27 @@
> > +// PR tree-optimization/94589
> > +// { dg-do compile { target c++20 } }
> > +// { dg-require-effective-target inf }
> > +// { dg-options "-O2 -g0 -fdump-tree-optimized -fno-trapping-math" }
> > +// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) 
> > (?:<|<=|>|>=|u>=|u<=) \[ij]_\[0-9]+\\(D\\)" 8 "optimized" } }
> > +// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) 
> > (?:<|<=|>|>=|u>=|u<=) 5\\.0" 8 "optimized" } }
> > +// { dg-final { scan-tree-dump-not " if " "optimized" } }
> > +
> > +#include <compare>
> > +
> > +#define A __attribute__((noipa))
> > +A bool f3 (double i, double j) { auto c = i <=> j; return c > 0; }
> > +A bool f4 (double i, double j) { auto c = i <=> j; return c < 0; }
> > +A bool f5 (double i, double j) { auto c = i <=> j; return c >= 0; }
> > +A bool f6 (double i, double j) { auto c = i <=> j; return c <= 0; }
> > +A bool f7 (double i, double j) { auto c = i <=> j; return c == 
> > std::partial_ordering::less; }
> > +A bool f8 (double i, double j) { auto c = i <=> j; return c != 
> > std::partial_ordering::less; }
> > +A bool f11 (double i, double j) { auto c = i <=> j; return c == 
> > std::partial_ordering::greater; }
> > +A bool f12 (double i, double j) { auto c = i <=> j; return c != 
> > std::partial_ordering::greater; }
> > +A bool f15 (double i) { auto c = i <=> 5.0; return c > 0; }
> > +A bool f16 (double i) { auto c = i <=> 5.0; return c < 0; }
> > +A bool f17 (double i) { auto c = i <=> 5.0; return c >= 0; }
> > +A bool f18 (double i) { auto c = i <=> 5.0; return c <= 0; }
> > +A bool f19 (double i) { auto c = i <=> 5.0; return c == 
> > std::partial_ordering::less; }
> > +A bool f20 (double i) { auto c = i <=> 5.0; return c != 
> > std::partial_ordering::less; }
> > +A bool f23 (double i) { auto c = i <=> 5.0; return c == 
> > std::partial_ordering::greater; }
> > +A bool f24 (double i) { auto c = i <=> 5.0; return c != 
> > std::partial_ordering::greater; }
> > --
> > 2.43.0
> >

Attachment: 0001-match-Simplify-a-CMP1-b-AND-IOR-a-CMP2-b-PR126042.patch
Description: Binary data

Reply via email to