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 > >
0001-match-Simplify-a-CMP1-b-AND-IOR-a-CMP2-b-PR126042.patch
Description: Binary data
