Simplify X /[ex] 8 == 0
authorMarc Glisse <marc.glisse@inria.fr>
Sun, 20 Nov 2016 15:32:37 +0000 (16:32 +0100)
committerMarc Glisse <glisse@gcc.gnu.org>
Sun, 20 Nov 2016 15:32:37 +0000 (15:32 +0000)
2016-11-20  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* fold-const.c (fold_comparison): Ignore EXACT_DIV_EXPR.
* match.pd (A /[ex] B CMP C): New simplifications.

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

From-SVN: r242638

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv.c [new file with mode: 0644]

index c64b349..d02d6e5 100644 (file)
@@ -1,5 +1,10 @@
 2016-11-20  Marc Glisse  <marc.glisse@inria.fr>
 
+       * fold-const.c (fold_comparison): Ignore EXACT_DIV_EXPR.
+       * match.pd (A /[ex] B CMP C): New simplifications.
+
+2016-11-20  Marc Glisse  <marc.glisse@inria.fr>
+
        * match.pd (0 / X, X / X, X % X): New simplifications.
 
 2016-11-19  Jakub Jelinek  <jakub@redhat.com>
index f4b2cfa..3c5a77e 100644 (file)
@@ -8700,8 +8700,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 
   /* We can fold X/C1 op C2 where C1 and C2 are integer constants
      into a single range test.  */
-  if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
-       || TREE_CODE (arg0) == EXACT_DIV_EXPR)
+  if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
       && TREE_CODE (arg1) == INTEGER_CST
       && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
       && !integer_zerop (TREE_OPERAND (arg0, 1))
index f97a998..36270d0 100644 (file)
@@ -2351,6 +2351,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
           (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
           (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))))))))))
 
+/* Fold A /[ex] B CMP C to A CMP B * C.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (exact_div @0 @1) INTEGER_CST@2)
+  (if (!integer_zerop (@1))
+   (if (wi::eq_p (@2, 0))
+    (cmp @0 @2)
+    (if (TREE_CODE (@1) == INTEGER_CST)
+     (with
+      {
+       bool ovf;
+       wide_int prod = wi::mul (@2, @1, TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+      }
+      (if (ovf)
+       { constant_boolean_node (cmp == NE_EXPR, type); }
+       (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))))
+(for cmp (lt le gt ge)
+ (simplify
+  (cmp (exact_div @0 INTEGER_CST@1) INTEGER_CST@2)
+  (if (wi::gt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1))))
+   (with
+    {
+      bool ovf;
+      wide_int prod = wi::mul (@2, @1, TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+    }
+    (if (ovf)
+     { constant_boolean_node (wi::lt_p (@2, 0, TYPE_SIGN (TREE_TYPE (@2)))
+                             != (cmp == LT_EXPR || cmp == LE_EXPR), type); }
+     (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))
+
 /* Unordered tests if either argument is a NaN.  */
 (simplify
  (bit_ior (unordered @0 @0) (unordered @1 @1))
index c20d91d..2c81bf4 100644 (file)
@@ -1,3 +1,7 @@
+2016-11-20  Marc Glisse  <marc.glisse@inria.fr>
+
+       * gcc.dg/tree-ssa/cmpexactdiv.c: New file.
+
 2016-11-20  Andre Vehreschild  <vehre@gcc.gnu.org>
 
        PR fortran/78395
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv.c
new file mode 100644 (file)
index 0000000..48e5cda
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+int f(int *p, int *q){
+  __SIZE_TYPE__ n = q - p;
+  return n == 0;
+}
+
+int g(int *p, int *q){
+  __PTRDIFF_TYPE__ n = q - p;
+  return n <= 2;
+}
+
+int h(long *p, long *q){
+  __SIZE_TYPE__ n = q - p;
+  return n == (__SIZE_TYPE__)(-1)/2;
+}
+
+/* { dg-final { scan-tree-dump-not "== 0" "optimized" } } */
+/* { dg-final { scan-tree-dump "<= 8" "optimized" { target { int32 } } } } */
+/* { dg-final { scan-tree-dump "return 0" "optimized" } } */