diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-02-08 10:21:57 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-02-08 10:21:57 +0100 |
commit | 74a15d1424da560bb599fe781ccbef070372a477 (patch) | |
tree | ab1c196bea449e8d75b31dfc1fabc401ae65b2d2 /gcc/tree-vrp.c | |
parent | 01726bc97785f6e66d6d882bf2b81077391603c5 (diff) | |
download | gcc-74a15d1424da560bb599fe781ccbef070372a477.zip gcc-74a15d1424da560bb599fe781ccbef070372a477.tar.gz gcc-74a15d1424da560bb599fe781ccbef070372a477.tar.bz2 |
re PR tree-optimization/79408 (Missed VRP optimization of integer modulo)
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
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index b429217..e058d8d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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, |