Hello,

if we compare for instance size() and capacity() for a std::vector, we get this kind of pattern. I started with just nop conversions and got a bit carried away handling all those cases.

Bootstrap+regtest on x86_64-pc-linux-gnu.

2019-06-11  Marc Glisse  <marc.gli...@inria.fr>

gcc/
        * match.pd (X/[ex]4<Y/[ex]4): Handle conversions.

gcc/testsuite/
        * gcc.dg/tree-ssa/cmpexactdiv-5.c: New file.

--
Marc Glisse
Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 272105)
+++ gcc/match.pd	(working copy)
@@ -1496,25 +1496,40 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	&& TYPE_UNSIGNED (TREE_TYPE (@0))
 	&& TYPE_PRECISION (TREE_TYPE (@0)) > 1
 	&& (wi::to_wide (@2)
 	    == wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)), SIGNED) - 1))
     (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
      (icmp (convert:stype @0) { build_int_cst (stype, 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 (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2))))
-   (cmp @0 @1)
+  (cmp (convert?@3 (exact_div @0 INTEGER_CST@2)) (convert? (exact_div @1 @2)))
+  (if (element_precision (TREE_TYPE (@3)) >= element_precision (TREE_TYPE (@0))
+       && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
    (if (wi::lt_p (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2))))
-    (cmp @1 @0)))))
+    (if (!TYPE_UNSIGNED (TREE_TYPE (@3)))
+     (cmp @1 @0)
+     (if (tree_expr_nonzero_p (@0) && tree_expr_nonzero_p (@1))
+      (with
+       {
+	tree utype = unsigned_type_for (TREE_TYPE (@0));
+       }
+       (cmp (convert:utype @1) (convert:utype @0)))))
+    (if (wi::gt_p (wi::to_wide (@2), 1, TYPE_SIGN (TREE_TYPE (@2))))
+     (if (TYPE_UNSIGNED (TREE_TYPE (@0)) || !TYPE_UNSIGNED (TREE_TYPE (@3)))
+      (cmp @0 @1)
+      (with
+       {
+	tree utype = unsigned_type_for (TREE_TYPE (@0));
+       }
+       (cmp (convert:utype @0) (convert:utype @1)))))))))
 
 /* X / C1 op C2 into a simple range test.  */
 (for cmp (simple_comparison)
  (simplify
   (cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && integer_nonzerop (@1)
        && !TREE_OVERFLOW (@1)
        && !TREE_OVERFLOW (@2))
    (with { tree lo, hi; bool neg_overflow;
Index: gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c	(working copy)
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int f(int *a, int *b, int *c){
+  if(sizeof(__SIZE_TYPE__) != sizeof(__PTRDIFF_TYPE__)) return 2;
+  __SIZE_TYPE__ s = b - a;
+  __SIZE_TYPE__ t = c - a;
+  return s < t;
+}
+
+/* { dg-final { scan-tree-dump-not "exact_div_expr" "optimized" } } */

Reply via email to