Hi! The following testcase shows another case that can be handled easily. If rhs2 is defined in a bb dominated by first_bb, we need to be careful because we can't rely on value range information of it after we optimize the guarding >= 0 check into 1. On the testcase, we have there rhs2 = (int) something_N; cast where both types are integral with the same precision, so we can in this case just check if something_N is defined in some bb not dominated by first_bb, or if it is result of & constant, or zero extension etc.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-06-05 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69615 * tree-ssa-reassoc.c (optimize_range_tests_var_bound): If rhs2 is lhs of a cast from a same precision integral SSA_NAME in a bb dominated by first_bb, retry with rhs2 set to the rhs1 of the cast. Don't emit cast to utype if rhs2 has already a compatible type. * gcc.dg/tree-ssa/pr69615.c: New test. --- gcc/tree-ssa-reassoc.c.jj 2018-04-27 09:08:57.667850280 +0200 +++ gcc/tree-ssa-reassoc.c 2018-06-05 17:01:39.028144763 +0200 @@ -3172,7 +3172,7 @@ optimize_range_tests_var_bound (enum tre to (unsigned) k_32 < (unsigned) iftmp.0_44, then we would execute those stmts even for negative k_32 and the value ranges would be no longer guaranteed and so the optimization would be invalid. */ - if (opcode == ERROR_MARK) + while (opcode == ERROR_MARK) { gimple *g = SSA_NAME_DEF_STMT (rhs2); basic_block bb2 = gimple_bb (g); @@ -3182,21 +3182,37 @@ optimize_range_tests_var_bound (enum tre { /* As an exception, handle a few common cases. */ if (gimple_assign_cast_p (g) - && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g))) - && TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g))) - && (TYPE_PRECISION (TREE_TYPE (rhs2)) - > TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (g))))) - /* Zero-extension is always ok. */ ; + && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g)))) + { + tree op0 = gimple_assign_rhs1 (g); + if (TYPE_UNSIGNED (TREE_TYPE (op0)) + && (TYPE_PRECISION (TREE_TYPE (rhs2)) + > TYPE_PRECISION (TREE_TYPE (op0)))) + /* Zero-extension is always ok. */ + break; + else if (TYPE_PRECISION (TREE_TYPE (rhs2)) + == TYPE_PRECISION (TREE_TYPE (op0)) + && TREE_CODE (op0) == SSA_NAME) + { + /* Cast from signed to unsigned or vice versa. Retry + with the op0 as new rhs2. */ + rhs2 = op0; + continue; + } + } else if (is_gimple_assign (g) && gimple_assign_rhs_code (g) == BIT_AND_EXPR && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST && !wi::neg_p (wi::to_wide (gimple_assign_rhs2 (g)))) /* Masking with INTEGER_CST with MSB clear is always ok - too. */ ; - else - continue; + too. */ + break; + rhs2 = NULL_TREE; } + break; } + if (rhs2 == NULL_TREE) + continue; wide_int nz = get_nonzero_bits (rhs2); if (wi::neg_p (nz)) @@ -3253,10 +3269,13 @@ optimize_range_tests_var_bound (enum tre gimple_set_uid (g, uid); rhs1 = gimple_assign_lhs (g); gsi_insert_before (&gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, rhs2); - gimple_set_uid (g, uid); - rhs2 = gimple_assign_lhs (g); - gsi_insert_before (&gsi, g, GSI_SAME_STMT); + if (!useless_type_conversion_p (utype, TREE_TYPE (rhs2))) + { + g = gimple_build_assign (make_ssa_name (utype), NOP_EXPR, rhs2); + gimple_set_uid (g, uid); + rhs2 = gimple_assign_lhs (g); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + } if (tree_swap_operands_p (rhs1, rhs2)) { std::swap (rhs1, rhs2); --- gcc/testsuite/gcc.dg/tree-ssa/pr69615.c.jj 2018-06-06 12:55:16.535159073 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/pr69615.c 2018-06-06 12:54:53.993133421 +0200 @@ -0,0 +1,16 @@ +/* PR tree-optimization/69615 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not " >= 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < 0" "optimized" } } */ + +extern void foo (void); + +void +bar (int z, unsigned int y) +{ + long long x = z; + y &= 0xf; + if (x >= 0 && x < (int) y) + foo (); +} Jakub