Richard Biener <[email protected]> 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.