https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88301
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Keywords| |missed-optimization Last reconfirmed| |2018-12-03 Component|middle-end |tree-optimization CC| |rguenth at gcc dot gnu.org Ever confirmed|0 |1 Summary|Optimization regression |[8/9 Regression] |with undefined unsigned |Optimization regression |overflow |with undefined unsigned | |overflow Target Milestone|--- |8.3 --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- This would be void evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb) { ... if (is_fallthru && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)) { set_ssa_range_info (vrs[i].first, vrs[i].second); maybe_set_nonzero_bits (pred_e, vrs[i].first); } looks like we do not manage to find a new range for the assert for _2. Hmm, for _2 we get _2 <= 4294967294 that's of course not too useful. Looks like we are not factoring in SSA range info when we register asserts for _3 != 0. It's of course somewhat of a special case... The code we currently add the assert from is /* Add asserts for NAME cmp CST and NAME being defined as NAME = NAME2 & CST2. Extract CST2 from the and. Also handle NAME = (unsigned) NAME2; casts where NAME's type is unsigned and has smaller precision than NAME2's type as if it was NAME = NAME2 & MASK. */ names[0] = NULL_TREE; names[1] = NULL_TREE; cst2 = NULL_TREE; if (rhs_code == BIT_AND_EXPR what we'd like to add is a case where we can look through a non-value-changing conversion identifying that using SSA range-info. Like Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 266733) +++ gcc/tree-vrp.c (working copy) @@ -2966,6 +2966,20 @@ register_edge_assert_for_2 (tree name, e add_assert_info (asserts, name2, tmp, new_comp_code, new_val); } + wide_int rmin, rmax; + tree rhs1 = gimple_assign_rhs1 (def_stmt); + if (CONVERT_EXPR_CODE_P (rhs_code) + && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) + && int_fits_type_p (val, TREE_TYPE (rhs1)) + && (TYPE_PRECISION (TREE_TYPE (name)) > TYPE_PRECISION (TREE_TYPE (rhs1)) + || (get_range_info (rhs1, &rmin, &rmax) == VR_RANGE + && (wi::min_precision (rmin, TYPE_SIGN (TREE_TYPE (rhs1))) + <= TYPE_PRECISION (TREE_TYPE (name))) + && (wi::min_precision (rmax, TYPE_SIGN (TREE_TYPE (rhs1))) + <= TYPE_PRECISION (TREE_TYPE (name)))))) + add_assert_info (asserts, rhs1, rhs1, + comp_code, fold_convert (TREE_TYPE (rhs1), val)); + /* Add asserts for NAME cmp CST and NAME being defined as NAME = NAME2 & CST2. but struggling with the range-fits-type idiom (we must have several copies of that now...). Maybe it should be instead && wi::le_p (wi::to_widest (wi::min_value (TYPE_PRECISION (TREE_TYPE (name)), TYPE_SIGN (name))), wi::to_widest (rmin), SIGNED) && wi::ge_p (wi::to_widest (wi::max_value (TYPE_PRECISION (TREE_TYPE (name)), TYPE_SIGN (name))), wi::to_widest (rmax), SIGNED)