Commit 74a15d14 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 01726bc9
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> 2016-02-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/riscv/riscv.c (riscv_build_integer_1): Avoid use of INT16_MAX. * config/riscv/riscv.c (riscv_build_integer_1): Avoid use of INT16_MAX.
......
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> 2017-02-08 Richard Biener <rguenther@suse.de>
PR tree-optimization/71824 PR tree-optimization/71824
......
/* 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"} } */
...@@ -9226,12 +9226,12 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9226,12 +9226,12 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
return true; return true;
} }
/* Simplify a division or modulo operator to a right shift or /* Simplify a division or modulo operator to a right shift or bitwise and
bitwise and if the first operand is unsigned or is greater if the first operand is unsigned or is greater than zero and the second
than zero and the second operand is an exact power of two. operand is an exact power of two. For TRUNC_MOD_EXPR op0 % op1 with
For TRUNC_MOD_EXPR op0 % op1 with constant op1, optimize it constant op1 (op1min = op1) or with op1 in [op1min, op1max] range,
into just op0 if op0's range is known to be a subset of 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 [-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned
modulo. */ modulo. */
static bool static bool
...@@ -9241,17 +9241,25 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9241,17 +9241,25 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
tree val = NULL; tree val = NULL;
tree op0 = gimple_assign_rhs1 (stmt); tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt); tree op1 = gimple_assign_rhs2 (stmt);
tree op1min = op1;
value_range *vr = get_value_range (op0); value_range *vr = get_value_range (op0);
if (rhs_code == TRUNC_MOD_EXPR if (rhs_code == TRUNC_MOD_EXPR
&& TREE_CODE (op1) == INTEGER_CST && TREE_CODE (op1) == SSA_NAME)
&& tree_int_cst_sgn (op1) == 1 {
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) && 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)) if (TYPE_UNSIGNED (TREE_TYPE (op0))
|| tree_int_cst_sgn (vr->min) >= 0 || 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)) vr->min))
{ {
/* If op0 already has the range op0 % op1 has, /* If op0 already has the range op0 % op1 has,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment