On Mon, Nov 3, 2025 at 6:02 PM Robin Dapp <[email protected]> wrote:
>
> I didn't commit yet but instead set up an arm qemu environment.
>
> There is indeed a problem after the patch:  The widen lshift standard name
> requires an immediate shift-count operand and that's what the arm pattern
> implements.
>
> However, we don't lower an IFN_VEC_WIDEN_LSHIFT similar to regular shifts in
> veclower.  The tree code before only ever used an immediate so we never had
> that situation.
>
> The attached patch (applied on top) adds initial veclower handling for IFNs,
> checking if the target supports a VOIDmode shift-count and replacing/lowering
> it if so.
>
> Is that a reasonable thing to do?  For riscv I'd relax this restriction again
> as our insn can handle vector, register, and immediate.

We shouldn't have created the IFN in the first palace if it isn't supported.  So
I think whatever did that misses the internal-fn-supported check instead.

Richard.

>
> Bootstrapped on x86 and power10.  Regtested on arm, rv64gcv, aarch64.
>
> Regards
>  Robin
>
> [PATCH] vect: Lower widen lshift vector shift count to scalar.
>
> The introduction of IFN_VEC_WIDEN_LSHIFT caused test failures on arm
> because the arm backend, correctly, does not accept vectors as shift
> count for vec_widen_[us]_shiftl.  The difference with an IFN vs
> a widen-lshift tree is that we implicitly vectorize the shift count,
> similar to a regular shift.
>
> A regular vec-vec shift will be lowered to vec-imm if possible.
> This patch does the same thing for IFN_VEC_WIDEN_LSHIFT
>
> gcc/ChangeLog:
>
>         * optabs-query.cc (can_shift_by_imm_p): New function.
>         * optabs-query.h (can_shift_by_imm_p): Declare.
>         * tree-vect-generic.cc (expand_vector_widen_lshift):
>         New function.
>         (expand_vector_ifn): New function that calls
>         expand_vector_widen_lshift.
>         (expand_vector_operations_1): Call expand_vector_ifn.
> ---
>  gcc/optabs-query.cc      | 18 +++++++++++
>  gcc/optabs-query.h       |  1 +
>  gcc/tree-vect-generic.cc | 68 ++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 85 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/optabs-query.cc b/gcc/optabs-query.cc
> index 5335d0d8401..00d095d5d9c 100644
> --- a/gcc/optabs-query.cc
> +++ b/gcc/optabs-query.cc
> @@ -849,3 +849,21 @@ can_implement_p (optab op, machine_mode mode)
>  {
>    return can_open_code_p (op, mode) || optab_libfunc (op, mode);
>  }
> +
> +/* Whether OP (a shift optab) can shift by an immediate.  */
> +
> +bool
> +can_shift_by_imm_p (optab op, machine_mode mode)
> +{
> +  if (!VECTOR_MODE_P (mode))
> +    return false;
> +
> +  enum insn_code icode = optab_handler (op, mode);
> +  if (icode == CODE_FOR_nothing)
> +    return false;
> +
> +  const struct insn_data_d *data = &insn_data[icode];
> +  machine_mode shift_mode = data->operand[2].mode;
> +
> +  return shift_mode == VOIDmode;
> +}
> diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
> index da98af337fa..1916486025f 100644
> --- a/gcc/optabs-query.h
> +++ b/gcc/optabs-query.h
> @@ -176,6 +176,7 @@ opt_machine_mode get_absneg_bit_mode (optab, machine_mode,
>  bool can_vec_extract (machine_mode, machine_mode);
>  bool can_open_code_p (optab, machine_mode);
>  bool can_implement_p (optab, machine_mode);
> +bool can_shift_by_imm_p (optab, machine_mode);
>
>  /* Version of find_widening_optab_handler_and_mode that operates on
>     specific mode types.  */
> diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
> index 0e867293bd0..edba99a0203 100644
> --- a/gcc/tree-vect-generic.cc
> +++ b/gcc/tree-vect-generic.cc
> @@ -2022,6 +2022,69 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
>    gsi_replace (gsi, g, false);
>  }
>
> +/* Expand an internal function IFN_VEC_WIDEN_LSHIFT.
> +   During vectorization we vectorized both arguments so the shift count is a
> +   vector now.  Check if the target supports an immediate as well and convert
> +   the second argument if so.  */
> +
> +static void
> +expand_vector_widen_lshift (gcall *call)
> +{
> +  gcc_assert (gimple_call_num_args (call) == 2);
> +
> +  /* Check whether we have IFN_VEC_WIDEN_LSHIFT (arg1, {x,x,x,x})
> +     where x could be a scalar variable or a constant.
> +     Transform to IFN_VEC_WIDEN_LSHIFT (arg1, x).  */
> +  tree arg1 = gimple_call_arg (call, 0);
> +  tree arg2 = gimple_call_arg (call, 1);
> +
> +  internal_fn ifn = gimple_call_internal_fn (call);
> +
> +  tree type = TREE_TYPE (arg1);
> +  optab op = direct_internal_fn_optab (ifn, {type, type});
> +
> +  if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg2))
> +      && can_shift_by_imm_p (op, TYPE_MODE (type)))
> +    {
> +      tree shift_count;
> +      if ((shift_count = ssa_uniform_vector_p (arg2)) != NULL_TREE)
> +       {
> +         gimple_call_set_arg (call, 1, shift_count);
> +         update_stmt (call);
> +         return;
> +       }
> +    }
> +
> +  /* The standard name expects an immediate.  If we couldn't convert the
> +     argument something is wrong.  */
> +  gcc_unreachable ();
> +}
> +
> +static void
> +expand_vector_ifn (gimple_stmt_iterator *gsi)
> +{
> +  gimple *g = gsi_stmt (*gsi);
> +  gcc_assert (is_gimple_call (g) && gimple_call_internal_p (g));
> +
> +  internal_fn ifn = gimple_call_internal_fn (g);
> +
> +  switch (ifn)
> +    {
> +    case IFN_VEC_CONVERT:
> +      expand_vector_conversion (gsi);
> +      break;
> +    case IFN_VEC_WIDEN_LSHIFT:
> +    case IFN_VEC_WIDEN_LSHIFT_HI:
> +    case IFN_VEC_WIDEN_LSHIFT_LO:
> +    case IFN_VEC_WIDEN_LSHIFT_EVEN:
> +    case IFN_VEC_WIDEN_LSHIFT_ODD:
> +      expand_vector_widen_lshift (as_a <gcall *> (g));
> +      break;
> +    default:
> +      break;
> +    }
> +}
> +
>  /* Process one statement.  If we identify a vector operation, expand it.  */
>
>  static void
> @@ -2037,8 +2100,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
>    gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
>    if (!stmt)
>      {
> -      if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
> -       expand_vector_conversion (gsi);
> +      gimple *g = gsi_stmt (*gsi);
> +      if (is_gimple_call (g) && gimple_call_internal_p (g))
> +         expand_vector_ifn (gsi);
>        return;
>      }
>
> --
> 2.51.0
>

Reply via email to