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