Richard Biener <rguent...@suse.de> writes:
> When vectorizing a shift of u16 data by an amount that's known to
> be less than 16 we currently fail to emit a vector u16 shift.  The
> first reason is that the promotion of the shift amount is hoisted
> only by PRE and that cannot preserve range info, the second reason
> is that pattern detection doesn't use range info when computing
> the precision required for an operation.
>
> The following addresses the first issue by making LIM hoist all
> expressions for the pass that runs right before PRE and the
> second issue by querying ranges for the shift amount.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
>
>       PR tree-optimization/119103
>       * tree-ssa-loop-im.cc (in_loop_pipeline): Globalize.
>       (compute_invariantness): Override costing when we run
>       right before PRE and PRE is enabled.
>       (pass_lim::execute): Adjust.
>       * tree-vect-patterns.cc (vect_determine_precisions_from_users):
>       For variable shift amounts use range information.
>
>       * gcc.target/i386/pr119103.c: New testcase.

Nice!

> [...]
> diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
> index 4f0a7ea162b..09408359cf2 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -6544,10 +6544,19 @@ 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::ge_p (min_shift, 0, TYPE_SIGN (TREE_TYPE (shift)))
> +         && wi::lt_p (max_shift, TYPE_PRECISION (type),
> +                      TYPE_SIGN (TREE_TYPE (shift))))
> +       const_shift = max_shift.to_uhwi ();

Don't we need to use min_shift rather than max_shift for LSHIFT_EXPR's:

            /* We need CONST_SHIFT fewer bits of the input.  */
            min_input_precision = (MAX (operation_precision, const_shift)
                                   - const_shift);

?  If so, I guess that means replacing const_shift with a minimum and
a maximum.

Thanks,
Richard

> +     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