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.

Reply via email to