From 74a15d1424da560bb599fe781ccbef070372a477 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 8 Feb 2017 10:21:57 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 8 +++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/tree-ssa/pr79408.c | 40 +++++++++++++++++++++++++++++++++ gcc/tree-vrp.c | 28 ++++++++++++++--------- 4 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr79408.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb1e7e9..67dc9b1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-02-08 Jakub Jelinek + + 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 * config/riscv/riscv.c (riscv_build_integer_1): Avoid use of INT16_MAX. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 260a3a5..0f0517d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-02-08 Jakub Jelinek + + PR tree-optimization/79408 + * gcc.dg/tree-ssa/pr79408.c: New test. + 2017-02-08 Richard Biener PR tree-optimization/71824 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr79408.c b/gcc/testsuite/gcc.dg/tree-ssa/pr79408.c new file mode 100644 index 0000000..2ea24f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr79408.c @@ -0,0 +1,40 @@ +/* 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"} } */ 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, -- 2.7.4