On Thu, Jun 18, 2026 at 9:19 AM Robin Dapp <[email protected]> wrote:
>
> Hi,
>
> This is another small improvement for PR125390.  Originally a riscv-specific
> issue and ICE, I noticed poor codegen when we extract values from a tuple
> type.  In the optimized dump we have:
>
>   vect_array.9 = .MASK_LEN_LOAD_LANES (&c, 32B, { -1, -1, -1, -1 }, _44(D), 
> 4, 0);
>   _48 = BIT_FIELD_REF <vect_array.9[0], 32, 96>;
>   _50 = BIT_FIELD_REF <vect_array.9[1], 32, 96>;
>   f_13 = _48 ^ _50;
>   a = f_13;
>
> and _48 as well as _50 spill to memory instead of extracting directly.
>
> We end up with
>
>   (subreg:RVVMF2SI (reg:RVVMF2x2SI 138 [ vect_array.9 ]) 0)
>
> which, as we pun the with a large integer mode, involves OImode
> that we cannot "move".  We might be able to work around that in the
> target in unintuitive ways :)  and we could also offer vec_extract for
> all tuple modes but I figured it could be much easier if expand already
> handled the tuple -> vector part for us so just a vector extract is left
> for the target to do.

But the above looks exactly "right"?

>
> This patch does that.  Is the approach reasonable?

What does it generate?  I'd exect that same subreg for the tuple -> vector
part?

> Bootstrapped and regtested on x86, power10, and aarch64.
> Regtested on riscv64.
>
> Regards
>  Robin
>
>         PR middle-end/125390
>
> gcc/ChangeLog:
>
>         * expr.cc (expand_expr_real_1): Prepare tuple extraction.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/rvv/autovec/pr125390.c: New test.
> ---
>  gcc/expr.cc                                   | 32 +++++++++++++++++++
>  .../gcc.target/riscv/rvv/autovec/pr125390.c   | 16 ++++++++++
>  2 files changed, 48 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c
>
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index de73215ccc6..e4f0eeb2b5b 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -12329,6 +12329,38 @@ expand_expr_real_1 (tree exp, rtx target, 
> machine_mode tmode,
>               must_force_mem = true;
>           }
>
> +       /* Check if we're dealing with a vector-tuple type extraction.
> +          If so, and the bitfield size does not overlap multiple
> +          vectors, force the respective single vector into a register
> +          and use that for actual extraction further down.  */
> +       tree from = TREE_OPERAND (exp, 0);
> +       if (!must_force_mem
> +           && REG_P (op0)
> +           && VECTOR_MODE_P (GET_MODE (op0))
> +           && TREE_CODE (from) == ARRAY_REF
> +           && VECTOR_TYPE_P (TREE_TYPE (from)))
> +         {
> +           machine_mode vmode = TYPE_MODE (TREE_TYPE (from));
> +           poly_uint16 vmodesz = GET_MODE_BITSIZE (vmode);
> +
> +           HOST_WIDE_INT vec_idx;
> +           poly_uint64 off;
> +
> +           if (can_div_trunc_p (bitpos, vmodesz, &vec_idx, &off)
> +               && known_le (off + bitsize, vmodesz))
> +             {
> +               rtx sub = simplify_gen_subreg (vmode, op0, GET_MODE (op0),
> +                                              vec_idx * GET_MODE_SIZE 
> (vmode));
> +               if (sub)
> +                 {
> +                   op0 = force_reg (vmode, sub);
> +                   orig_op0 = op0;
> +                   mode2 = vmode;
> +                   bitpos = off;
> +                 }
> +             }
> +         }
> +
>         /* If this is a constant, put it in a register if it is a legitimate
>            constant and we don't need a memory reference.  */
>         if (CONSTANT_P (op0)
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c 
> b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c
> new file mode 100644
> index 00000000000..363fc0c8d40
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr125390.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=zvl 
> -O2 -fdump-rtl-expand" } */
> +
> +int a, b[64], c[64];
> +
> +void
> +foo (void)
> +{
> +  for (unsigned e = 0; e < 8; e += 2)
> +    {
> +      a = c[e] ^ c[e + 1];
> +      b[e] = 0;
> +    }
> +}
> +
> +/* { dg-final { scan-rtl-dump-not "virtual-stack-vars" "expand" } } */
> --
> 2.54.0

Reply via email to