On Thu, 26 Feb 2026, Xi Ruoyao wrote:

> The comment above expand_vector_broadcast() states a precondition that
> the mode of op must be the element mode of vmode.  But when
> expand_binop() called expand_vector_broadcast() to broadcast the shift
> amount, it only truncated the shift amount if it's too wide, but no
> action is performed if the shift amount is too narrow.

OK.

Thanks,
Richard.

>       PR middle-end/124250
>       PR target/123807
> 
> gcc/
>       * optabs.cc (expand_vector_broadcast): Add a checking assert to
>       verify the precondition about the input modes.
>       (expand_binop): Extend the shift amount if it's narrower than
>       the element of the shifted vector.
> 
> gcc/testsuite/
> 
>       * gcc.c-torture/compile/pr124250.c: New test.
> ---
> 
> Bootstrapped and regtested on x86_64-linux-gnu and
> loongarch64-linux-gnu.  Ok for trunk?
> 
>  gcc/optabs.cc                                 | 34 +++++++++++++------
>  .../gcc.c-torture/compile/pr124250.c          |  8 +++++
>  2 files changed, 31 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr124250.c
> 
> diff --git a/gcc/optabs.cc b/gcc/optabs.cc
> index e813cf9b215..249413c7576 100644
> --- a/gcc/optabs.cc
> +++ b/gcc/optabs.cc
> @@ -428,9 +428,9 @@ force_expand_binop (machine_mode mode, optab binoptab,
>    return true;
>  }
>  
> -/* Create a new vector value in VMODE with all elements set to OP.  The
> -   mode of OP must be the element mode of VMODE.  If OP is a constant,
> -   then the return value will be a constant.  */
> +/* Create a new vector value in VMODE with all elements set to OP.  If OP
> +   is not a constant, the mode of it must be the element mode of VMODE.
> +   If OP is a constant, then the return value will be a constant.  */
>  
>  rtx
>  expand_vector_broadcast (machine_mode vmode, rtx op)
> @@ -439,6 +439,8 @@ expand_vector_broadcast (machine_mode vmode, rtx op)
>    rtvec vec;
>  
>    gcc_checking_assert (VECTOR_MODE_P (vmode));
> +  gcc_checking_assert (CONST_INT_P (op)
> +                    || GET_MODE_INNER (vmode) == GET_MODE (op));
>  
>    if (valid_for_const_vector_p (vmode, op))
>      return gen_const_vec_duplicate (vmode, op);
> @@ -1629,15 +1631,25 @@ expand_binop (machine_mode mode, optab binoptab, rtx 
> op0, rtx op1,
>        if (otheroptab
>         && (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing)
>       {
> -       /* The scalar may have been extended to be too wide.  Truncate
> -          it back to the proper size to fit in the broadcast vector.  */
> +       /* The scalar may be wider or narrower than the vector element.
> +          Truncate or extend it to the proper size to fit in the
> +          broadcast vector.  */
>         scalar_mode inner_mode = GET_MODE_INNER (mode);
> -       if (!CONST_INT_P (op1)
> -           && (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
> -               > GET_MODE_BITSIZE (inner_mode)))
> -         op1 = force_reg (inner_mode,
> -                          simplify_gen_unary (TRUNCATE, inner_mode, op1,
> -                                              GET_MODE (op1)));
> +       if (!CONST_INT_P (op1))
> +         {
> +           auto mode1 = as_a <scalar_int_mode> (GET_MODE (op1));
> +           int size1 = GET_MODE_BITSIZE (mode1);
> +           int inner_size = GET_MODE_BITSIZE (inner_mode);
> +
> +           if (size1 != inner_size)
> +             {
> +               auto unary = size1 > inner_size ? TRUNCATE : ZERO_EXTEND;
> +               op1 = force_reg (inner_mode,
> +                                simplify_gen_unary (unary, inner_mode,
> +                                                    op1, mode1));
> +             }
> +         }
> +
>         rtx vop1 = expand_vector_broadcast (mode, op1);
>         if (vop1)
>           {
> diff --git a/gcc/testsuite/gcc.c-torture/compile/pr124250.c 
> b/gcc/testsuite/gcc.c-torture/compile/pr124250.c
> new file mode 100644
> index 00000000000..1435091dc0b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.c-torture/compile/pr124250.c
> @@ -0,0 +1,8 @@
> +typedef long long v2i64 __attribute__ ((vector_size (16), aligned (16)));
> +v2i64 a, b;
> +
> +void
> +test (int l)
> +{
> +  a = b >> (-l);
> +}
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to