From f51286f21f3b69878d9b5d55041089aba79c82a6 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 12 Jan 2015 21:44:32 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++++++ gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/gcc.dg/pr64454.c | 43 ++++++++++++++++++++++++++++++++++ gcc/tree-vrp.c | 40 +++++++++++++++++++++++++++---- 4 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr64454.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 775efde21b4..b9d47cf84dc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2015-01-12 Jakub Jelinek + 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 95a1a23e1be..9a07ada5235 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2015-01-12 Jakub Jelinek + 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 00000000000..33018d3bb18 --- /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 ae1da4674cc..ecf86c35666 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; -- 2.30.2