re PR tree-optimization/79408 (Missed VRP optimization of integer modulo)
authorJakub Jelinek <jakub@redhat.com>
Wed, 8 Feb 2017 09:21:57 +0000 (10:21 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 8 Feb 2017 09:21:57 +0000 (10:21 +0100)
PR tree-optimization/79408
* tree-vrp.c (simplify_div_or_mod_using_ranges): If op1 is not
constant, but SSA_NAME with a known integer range, use the minimum
of that range instead of op1 to determine if modulo can be replaced
with its first operand.

* gcc.dg/tree-ssa/pr79408.c: New test.

From-SVN: r245273

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr79408.c [new file with mode: 0644]
gcc/tree-vrp.c

index bb1e7e9..67dc9b1 100644 (file)
@@ -1,3 +1,11 @@
+2017-02-08  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/79408
+       * tree-vrp.c (simplify_div_or_mod_using_ranges): If op1 is not
+       constant, but SSA_NAME with a known integer range, use the minimum
+       of that range instead of op1 to determine if modulo can be replaced
+       with its first operand.
+
 2016-02-08  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/riscv/riscv.c (riscv_build_integer_1): Avoid use of INT16_MAX.
index 260a3a5..0f0517d 100644 (file)
@@ -1,3 +1,8 @@
+2017-02-08  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/79408
+       * gcc.dg/tree-ssa/pr79408.c: New test.
+
 2017-02-08  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/71824
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr79408.c b/gcc/testsuite/gcc.dg/tree-ssa/pr79408.c
new file mode 100644 (file)
index 0000000..2ea24f4
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR tree-optimization/79408 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void link_error (void);
+
+void
+foo (unsigned int x, unsigned int y)
+{
+  if (x > 7312)
+    return;
+  if (y <= 7312)
+    return;
+  if (x % y != x)
+    link_error ();
+}
+
+void
+bar (int x, int y)
+{
+  if (x > 7312 || x < 0)
+    return;
+  if (y <= 7312)
+    return;
+  if (x % y != x)
+    link_error ();
+}
+
+void
+baz (int x, int y)
+{
+  if (x > 7312 || x < -7312)
+    return;
+  if (y <= 7312)
+    return;
+  if (x % y != x)
+    link_error ();
+}
+
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
index b429217..e058d8d 100644 (file)
@@ -9226,12 +9226,12 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
   return true;
 }
 
-/* Simplify a division or modulo operator to a right shift or
-   bitwise and if the first operand is unsigned or is greater
-   than zero and the second operand is an exact power of two.
-   For TRUNC_MOD_EXPR op0 % op1 with constant op1, optimize it
-   into just op0 if op0's range is known to be a subset of
-   [-op1 + 1, op1 - 1] for signed and [0, op1 - 1] for unsigned
+/* Simplify a division or modulo operator to a right shift or bitwise and
+   if the first operand is unsigned or is greater than zero and the second
+   operand is an exact power of two.  For TRUNC_MOD_EXPR op0 % op1 with
+   constant op1 (op1min = op1) or with op1 in [op1min, op1max] range,
+   optimize it into just op0 if op0's range is known to be a subset of
+   [-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned
    modulo.  */
 
 static bool
@@ -9241,17 +9241,25 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
   tree val = NULL;
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
+  tree op1min = op1;
   value_range *vr = get_value_range (op0);
 
   if (rhs_code == TRUNC_MOD_EXPR
-      && TREE_CODE (op1) == INTEGER_CST
-      && tree_int_cst_sgn (op1) == 1
+      && TREE_CODE (op1) == SSA_NAME)
+    {
+      value_range *vr1 = get_value_range (op1);
+      if (range_int_cst_p (vr1))
+       op1min = vr1->min;
+    }
+  if (rhs_code == TRUNC_MOD_EXPR
+      && TREE_CODE (op1min) == INTEGER_CST
+      && tree_int_cst_sgn (op1min) == 1
       && range_int_cst_p (vr)
-      && tree_int_cst_lt (vr->max, op1))
+      && tree_int_cst_lt (vr->max, op1min))
     {
       if (TYPE_UNSIGNED (TREE_TYPE (op0))
          || tree_int_cst_sgn (vr->min) >= 0
-         || tree_int_cst_lt (fold_unary (NEGATE_EXPR, TREE_TYPE (op1), op1),
+         || tree_int_cst_lt (fold_unary (NEGATE_EXPR, TREE_TYPE (op1min), op1min),
                              vr->min))
        {
          /* If op0 already has the range op0 % op1 has,