aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-02-08 10:21:57 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-02-08 10:21:57 +0100
commit74a15d1424da560bb599fe781ccbef070372a477 (patch)
treeab1c196bea449e8d75b31dfc1fabc401ae65b2d2 /gcc/tree-vrp.c
parent01726bc97785f6e66d6d882bf2b81077391603c5 (diff)
downloadgcc-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.c28
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,