https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119103
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- So first of all the range info on the shift is lost, so vect_recog_over_widening_pattern cannot do its work. The info is lost when PRE moves the invariant (int) amount cast out of the loop - we've dropped the unreachable() at that point, so we can't recover the lost info then. With --param lim-expensive=1 and the following patch it works (not sure if we can really just take the max-shift, but I think so - we should possibly check the min to be ges_p zero). diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 4f0a7ea162b..38256039c04 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -6544,10 +6544,17 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt) case RSHIFT_EXPR: { tree shift = gimple_assign_rhs2 (stmt); - if (TREE_CODE (shift) != INTEGER_CST - || !wi::ltu_p (wi::to_widest (shift), precision)) + unsigned int const_shift; + wide_int min_shift, max_shift; + if (TREE_CODE (shift) == SSA_NAME + && vect_get_range_info (shift, &min_shift, &max_shift) + && wi::ltu_p (max_shift, TYPE_PRECISION (type))) + const_shift = max_shift.to_uhwi (); + else if (TREE_CODE (shift) == INTEGER_CST + && wi::ltu_p (wi::to_widest (shift), precision)) + const_shift = TREE_INT_CST_LOW (shift); + else return; - unsigned int const_shift = TREE_INT_CST_LOW (shift); if (code == LSHIFT_EXPR) { /* Avoid creating an undefined shift.