On Mon, Jul 21, 2025 at 1:30 AM Andrew Pinski <quic_apin...@quicinc.com> wrote: > > I have seen this a few places though the testcase from PR 95906 > is an obvious place where this shows up for sure. > This convert `cmp - 1` into `-icmp` as that form is more useful > in many cases. > > Bootstrapped and tested on x86_64-linux-gnu.
I think we want to ensure that TYPE_PRECISION (type) > 1 (considering a cast from unsigned bool to signed and thus UB for -1 + -1). OK with that change. Thanks, Richard. > PR tree-optimization/110949 > PR tree-optimization/95906 > > gcc/ChangeLog: > > * match.pd (cmp - 1): New pattern. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/cmp-2.c: New test. > * gcc.dg/tree-ssa/max-bitcmp-1.c: New test. > > Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> > --- > gcc/match.pd | 17 ++++++++++++++++- > gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c | 14 ++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c | 19 +++++++++++++++++++ > 3 files changed, 49 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 7f84d5149f4..3e8b324e376 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -7035,6 +7035,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (icmp @0 @1) > (if (ic == ncmp) > (ncmp @0 @1))))) > + /* ((cast)cmp) - 1 -> -(cast)icmp . */ > + (simplify > + (plus (convert? (cmp@2 @0 @1)) integer_minus_onep) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@2)) && TYPE_PRECISION (TREE_TYPE (@2)) > == 1) > + /* Comparison inversion may be impossible for trapping math, > + invert_tree_comparison will tell us. But we can't use > + a computed operator in the replacement tree thus we have > + to play the trick below. */ > + (with { enum tree_code ic = invert_tree_comparison > + (cmp, HONOR_NANS (@0)); > + tree cmptype = TREE_TYPE (@2); } > + (if (ic == icmp) > + (negate (convert (icmp:cmptype @0 @1))) > + (if (ic == ncmp) > + (negate (convert (ncmp:cmptype @0 @1)))))))) > /* The following bits are handled by fold_binary_op_with_conditional_arg. > */ > (simplify > (ne (cmp@2 @0 @1) integer_zerop) > @@ -11678,4 +11693,4 @@ and, > && VECTOR_TYPE_P (type) > && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, > OPTIMIZE_FOR_BOTH)) > (IFN_AVG_CEIL @0 @2))) > -#endif > \ No newline at end of file > +#endif > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c > b/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c > new file mode 100644 > index 00000000000..9b029019c06 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fdump-tree-forwprop" } */ > + > +/* PR tree-optimization/110949 */ > +/* Transform `(cmp) - 1` into `-icmp`. */ > + > +int f1(int a) > +{ > + int t = a == 115; > + return t - 1; > +} > + > +/* { dg-final { scan-tree-dump " != 115" "forwprop1" } } */ > +/* { dg-final { scan-tree-dump-not " == 115" "forwprop1" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c > new file mode 100644 > index 00000000000..81b5a27c045 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c > @@ -0,0 +1,19 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fdump-tree-forwprop -fdump-tree-optimized" } */ > + > +/* PR tree-optimization/95906 */ > +/* this should become MAX_EXPR<a,b> */ > + > +int f2(int a, int b) > +{ > + int cmp = -(a > b); > + return (cmp & a) | (~cmp & b); > +} > + > +/* we should not end up with -_2 */ > +/* we should not end up and & nor a `+ -1` */ > +/* In optimized we should have a max. */ > +/* { dg-final { scan-tree-dump-not " -\[a-zA-Z_\]" "forwprop1" } } */ > +/* { dg-final { scan-tree-dump-not " & " "forwprop1" } } */ > +/* { dg-final { scan-tree-dump-not " . -1" "forwprop1" } } */ > +/* { dg-final { scan-tree-dump-times "MAX_EXPR " 1 "optimized" } } */ > -- > 2.43.0 >