aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-01-12 21:44:32 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2015-01-12 21:44:32 +0100
commitf51286f21f3b69878d9b5d55041089aba79c82a6 (patch)
tree0217d8864283be08a04517b8666b0763b5234f11
parent01991953449246570f85f30b7b37e29a7e5b2cc1 (diff)
downloadgcc-f51286f21f3b69878d9b5d55041089aba79c82a6.zip
gcc-f51286f21f3b69878d9b5d55041089aba79c82a6.tar.gz
gcc-f51286f21f3b69878d9b5d55041089aba79c82a6.tar.bz2
re PR tree-optimization/64454 (optimize (x%5)%5)
PR tree-optimization/64454 * tree-vrp.c (simplify_div_or_mod_using_ranges): Optimize op0 % op1 into op0 if op0 is in range [-op1 + 1, op1 - 1] for signed or [0, op1 - 1] for unsigned modulo. (simplify_stmt_using_ranges): Call simplify_div_or_mod_using_ranges even if op1 does not satisfy integer_pow2p. * gcc.dg/pr64454.c: New test. From-SVN: r219491
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/pr64454.c43
-rw-r--r--gcc/tree-vrp.c40
4 files changed, 88 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 775efde..b9d47cf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2015-01-12 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/64454
+ * tree-vrp.c (simplify_div_or_mod_using_ranges): Optimize
+ op0 % op1 into op0 if op0 is in range [-op1 + 1, op1 - 1]
+ for signed or [0, op1 - 1] for unsigned modulo.
+ (simplify_stmt_using_ranges): Call simplify_div_or_mod_using_ranges
+ even if op1 does not satisfy integer_pow2p.
+
PR other/64370
* sreal.c (sreal::to_double): Use ldexp instead of scalbnl.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 95a1a23..9a07ada 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2015-01-12 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/64454
+ * gcc.dg/pr64454.c: New test.
+
PR testsuite/64028
* gcc.dg/vect/no-section-anchors-vect-31.c: Add dg-add-options
bind_pic_locally.
diff --git a/gcc/testsuite/gcc.dg/pr64454.c b/gcc/testsuite/gcc.dg/pr64454.c
new file mode 100644
index 0000000..33018d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64454.c
@@ -0,0 +1,43 @@
+/* PR tree-optimization/64454 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+unsigned
+f1 (unsigned x)
+{
+ return (x % 5) % 5;
+}
+
+int
+f2 (int x)
+{
+ return (x % 5) % 5;
+}
+
+int
+f3 (int x)
+{
+ return (x % -5) % -5;
+}
+
+unsigned
+f4 (unsigned x)
+{
+ return (x % 5) % 6;
+}
+
+int
+f5 (int x)
+{
+ return (x % 5) % 6;
+}
+
+int
+f6 (int x)
+{
+ return (x % -5) % -6;
+}
+
+/* { dg-final { scan-tree-dump-times "% 5" 6 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "% 6" 0 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ae1da46..ecf86c3 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -8998,7 +8998,11 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
/* 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. */
+ 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
+ modulo. */
static bool
simplify_div_or_mod_using_ranges (gimple stmt)
@@ -9007,7 +9011,30 @@ simplify_div_or_mod_using_ranges (gimple stmt)
tree val = NULL;
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
- value_range_t *vr = get_value_range (gimple_assign_rhs1 (stmt));
+ value_range_t *vr = get_value_range (op0);
+
+ if (rhs_code == TRUNC_MOD_EXPR
+ && TREE_CODE (op1) == INTEGER_CST
+ && tree_int_cst_sgn (op1) == 1
+ && range_int_cst_p (vr)
+ && tree_int_cst_lt (vr->max, op1))
+ {
+ 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),
+ vr->min))
+ {
+ /* If op0 already has the range op0 % op1 has,
+ then TRUNC_MOD_EXPR won't change anything. */
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, op0);
+ update_stmt (stmt);
+ return true;
+ }
+ }
+
+ if (!integer_pow2p (op1))
+ return false;
if (TYPE_UNSIGNED (TREE_TYPE (op0)))
{
@@ -9880,11 +9907,14 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
/* Transform TRUNC_DIV_EXPR and TRUNC_MOD_EXPR into RSHIFT_EXPR
and BIT_AND_EXPR respectively if the first operand is greater
- than zero and the second operand is an exact power of two. */
+ than zero and the second operand is an exact power of two.
+ Also optimize TRUNC_MOD_EXPR away if the second operand is
+ constant and the first operand already has the right value
+ range. */
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
- if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
- && integer_pow2p (gimple_assign_rhs2 (stmt)))
+ if (TREE_CODE (rhs1) == SSA_NAME
+ && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
return simplify_div_or_mod_using_ranges (stmt);
break;