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" } } */

Reply via email to