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.