Hello,surprisingly, this did not cause any Wstrict-overflow failure. Some of it sounds more like reassoc's job, but it is convenient to handle simple cases in match.pd. I think we could wait until there are reports of regressions related to register pressure before adding single_use tests.
For a std::vector<long> v, we now simplify v.size()==v.capacity() to a single comparison (long)finish==(long)end_storage (I guess I could still try to drop the casts to consider it really done). Handling v.size()<v.capacity() seems much harder, because of C++'s questionable choice to use unsigned types. I may still be able to remove the divisions, I'll see if I can sprinkle some 'convert' in recent transformations.
Bootstrap+regtest on powerpc64le-unknown-linux-gnu. 2017-04-28 Marc Glisse <marc.gli...@inria.fr> gcc/ * match.pd (X+Z CMP Y+Z, X-Z CMP Y-Z, Z-X CMP Z-Y): New transformations. gcc/testsuite/ * gcc.dg/tree-ssa/cmpexactdiv-2.c: Update for X-Z CMP Y-Z. -- Marc Glisse
Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 247362) +++ gcc/match.pd (working copy) @@ -1035,20 +1035,68 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && wi::neg_p (@1, TYPE_SIGN (TREE_TYPE (@1)))) (cmp @2 @0)))))) /* X / 4 < Y / 4 iff X < Y when the division is known to be exact. */ (for cmp (simple_comparison) (simplify (cmp (exact_div @0 INTEGER_CST@2) (exact_div @1 @2)) (if (wi::gt_p(@2, 0, TYPE_SIGN (TREE_TYPE (@2)))) (cmp @0 @1)))) +/* X + Z < Y + Z iff X < Y when there is no overflow. */ +(for cmp (lt le ge gt) + (simplify + (cmp (plus:c @0 @2) (plus:c @1 @2)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + (cmp @0 @1)))) +/* For ==, this is also true with wrapping overflow. */ +(for cmp (eq ne minus) + (simplify + (cmp (plus:c @0 @2) (plus:c @1 @2)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) + (cmp @0 @1)))) + +/* X - Z < Y - Z iff X < Y when there is no overflow. */ +(for cmp (lt le ge gt) + (simplify + (cmp (minus @0 @2) (minus @1 @2)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + (cmp @0 @1)))) +/* For ==, this is also true with wrapping overflow. */ +(for cmp (eq ne minus) + (simplify + (cmp (minus @0 @2) (minus @1 @2)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) + (cmp @0 @1)))) + +/* Z - X < Z - Y iff Y < X when there is no overflow. */ +(for cmp (lt le ge gt) + (simplify + (cmp (minus @2 @0) (minus @2 @1)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + (cmp @1 @0)))) +/* For ==, this is also true with wrapping overflow. */ +(for cmp (eq ne minus) + (simplify + (cmp (minus @2 @0) (minus @2 @1)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) + (cmp @1 @0)))) + /* ((X inner_op C0) outer_op C1) With X being a tree where value_range has reasoned certain bits to always be zero throughout its computed value range, inner_op = {|,^}, outer_op = {|,^} and inner_op != outer_op where zero_mask has 1's for all bits that are sure to be 0 in and 0's otherwise. if (inner_op == '^') C0 &= ~C1; if ((C0 & ~zero_mask) == 0) then emit (X outer_op (C0 outer_op C1) if ((C1 & ~zero_mask) == 0) then emit (X inner_op (C0 outer_op C1) */ Index: gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-2.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-2.c (revision 247362) +++ gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-2.c (working copy) @@ -1,11 +1,11 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-optimized-raw" } */ +/* { dg-options "-O -fstrict-overflow -fdump-tree-optimized-raw" } */ int f (long *a, long *b, long *c) { __PTRDIFF_TYPE__ l1 = b - a; __PTRDIFF_TYPE__ l2 = c - a; return l1 < l2; } -/* Eventually we also want to remove all minus_expr. */ +/* { dg-final { scan-tree-dump-not "minus_expr" "optimized" } } */ /* { dg-final { scan-tree-dump-not "exact_div_expr" "optimized" } } */