Hi! While looking at the RTL problem when combiner optimizes away (x & 0xfffe) % 0xffff into just (x & 0xfffe), I've looked at VRP which optimizes that case well (-O2 only, the PR is -O1), but discovered that it isn't generic enough, we actually don't need op1 to be constant in this case, a range whose (positive) minimum satisfies it can be handled the same.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (or shall I defer it for GCC8)? 2017-02-07 Jakub Jelinek <ja...@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. * gcc.dg/tree-ssa/pr79408.c: New test. --- gcc/tree-vrp.c.jj 2017-01-30 19:10:50.000000000 +0100 +++ gcc/tree-vrp.c 2017-02-07 12:33:32.721482609 +0100 @@ -9241,17 +9241,25 @@ simplify_div_or_mod_using_ranges (gimple 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), - vr->min)) + || tree_int_cst_lt (fold_unary (NEGATE_EXPR, TREE_TYPE (op1min), + op1min), vr->min)) { /* If op0 already has the range op0 % op1 has, --- gcc/testsuite/gcc.dg/tree-ssa/pr79408.c.jj 2017-02-07 16:30:42.439774777 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/pr79408.c 2017-02-07 16:32:37.653282317 +0100 @@ -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"} } */ Jakub