> -----Original Message-----
> From: Richard Biener <[email protected]>
> Sent: 30 June 2026 10:21
> To: Tamar Christina <[email protected]>
> Cc: [email protected]; nd <[email protected]>
> Subject: Re: [patch]middle-end: Handle variable-length vector types in
> store_constructor
>
> On Fri, 26 Jun 2026, Tamar Christina wrote:
>
> > Currently vec_init does not support VLA vec_init and we instead fall back to
> > storing piecewise through memory.
> >
> > However there's no defined semantics for this. This patch adds the
> semantics
> > that for VLA constructors the vector has to be cleared with zero before
> > piecewise being constructed from scalar elements. This means unspecified
> > elements are initialized to zero.
> >
> > Without this patch
> >
> > #include <arm_sve.h>
> >
> > svint32_t __attribute__ ((noipa))
> > func_init4 (int32_t a, int32_t b, int32_t c)
> > {
> > svint32_t temp = {a, b, c};
> > return temp;
> > }
> >
> > compiles to:
> >
> > func_init4:
> > addvl sp, sp, #-3
> > movi d30, #0
> > str z30, [sp, #2, mul vl]
> > addvl x3, sp, #2
> > str w0, [x3]
> > addvl x0, sp, #1
> > add x0, x0, 4
> > ldr z31, [sp, #2, mul vl]
> > str z31, [sp, #1, mul vl]
> > str w1, [x0]
> > ldr z31, [sp, #1, mul vl]
> > str z31, [sp]
> > str w2, [sp, 8]
> > ldr z0, [sp]
> > addvl sp, sp, #3
> > ret
> >
> > and with the patch
> >
> > func_init4:
> > fmov s0, w2
> > fmov s0, s0
> > insr z0.s, w1
> > insr z0.s, w0
> > ret
> >
> > note that this is still not optimal as the
> >
> > fmov s0, s0
> >
> > that's doing the zero-ing of the vector is not actually needed since the
> > transfer instruction
> >
> > fmov s0, w2
> >
> > already zeros the destination SVE register. But this is an AArch64
> > deficiency
> > that will be dealt with in the backend.
> >
> > the optimal codegen here is:
> >
> > func_init4:
> > orr x1, x1, x2, lsl 32
> > fmov d0, x1
> > insr z0.s, w0
> > ret
> >
> > Bootstrapped Regtested on aarch64-none-linux-gnu,
> > arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> > -m32, -m64 and no issues.
> >
> > Ok for master?
> >
> > Thanks,
> > Tamar
> >
> > Co-Authored-By: Chris Bazley <[email protected]>
> >
> > gcc/ChangeLog:
> >
> > * expr.cc (store_constructor): Handle VLA vec_init support and generic
> > fall through piecewise copy.
> > * doc/md.texi: Document change
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/aarch64/sve/copsi.c: New test.
> >
> > ---
> > diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
> > index
> 1ef748796f5d0de63127b86c9903c9b12420bebf..be40cc695e071babe192
> 8b555a11fd67af0d331b 100644
> > --- a/gcc/doc/md.texi
> > +++ b/gcc/doc/md.texi
> > @@ -7552,7 +7552,9 @@ Initialize the vector to given values. Operand 0 is
> the vector to initialize
> > and operand 1 is parallel containing values for individual fields. The
> > @var{n} mode is the mode of the elements, should be either element mode
> of
> > the vector mode @var{m}, or a vector mode with the same element mode
> and
> > -smaller number of elements.
> > +smaller number of elements. If @var{m} specifies a scalable vector mode,
> > +then operand 1 only specifies the minimum number of elements implied
> > +by @var{m} and elements beyond are zero initialized.
> >
> > @mdindex vec_duplicate@var{m}
> > @item @samp{vec_duplicate@var{m}}
> > diff --git a/gcc/expr.cc b/gcc/expr.cc
> > index
> de73215ccc6623fa90f4a90212fd8dc7c50991a9..373bec1322e7c554cbb31
> 4aed923abd7c3267ad8 100644
> > --- a/gcc/expr.cc
> > +++ b/gcc/expr.cc
> > @@ -7498,11 +7498,14 @@ fields_length (const_tree type)
> > return count;
> > }
> >
> > -
> > /* Store the value of constructor EXP into the rtx TARGET.
> > TARGET is either a REG or a MEM; we know it cannot conflict, since
> > safe_from_p has been called.
> > CLEARED is true if TARGET is known to have been zero'd.
> > + If the constructor EXP has a vector type then elements of TARGET for
> which
> > + there is no corresponding element in EXP are zero'd. For a
> > variable-length
> > + vector type, only elements up to the minimum number of subparts of the
> type
> > + are explicitly zero'd; any elements beyond that are implicitly zero.
> > SIZE is the number of bytes of TARGET we are allowed to modify: this
> > may not be the same as the size of EXP if we are assigning to a field
> > which has been packed to exclude padding bits.
> > @@ -8075,13 +8078,20 @@ store_constructor (tree exp, rtx target, int
> cleared, poly_int64 size,
> > similarly non-const type vectors. */
> > icode = convert_optab_handler (vec_init_optab, mode,
> eltmode);
> > }
> > + else
> > + {
> > + /* Handle variable-length vector types. */
> > + icode = convert_optab_handler (vec_init_optab, mode,
> eltmode);
> > + const_n_elts = constant_lower_bound (n_elts);
> > + cleared = 0;
> > + }
>
> Why set 'cleared' to 0? If the caller cleared TARGET we shouldn't
> need to do this again?
>
> > - if (const_n_elts && icode != CODE_FOR_nothing)
> > - {
> > - vector = rtvec_alloc (const_n_elts);
> > - for (unsigned int k = 0; k < const_n_elts; k++)
> > - RTVEC_ELT (vector, k) = CONST0_RTX (eltmode);
> > - }
> > + if (const_n_elts && icode != CODE_FOR_nothing)
> > + {
> > + vector = rtvec_alloc (const_n_elts);
> > + for (unsigned int k = 0; k < const_n_elts; k++)
> > + RTVEC_ELT (vector, k) = CONST0_RTX (eltmode);
> > + }
> > }
> >
> > /* Compute the size of the elements in the CTOR. It differs
> > @@ -8121,7 +8131,8 @@ store_constructor (tree exp, rtx target, int
> cleared, poly_int64 size,
> > || maybe_gt (4 * zero_count, 3 * count));
>
> and this maybe_lt (count, n_elts) should ensure need_to_clear is set
> for VLA vectors? So I don't understand why you need to change the
> condition below? 'vector' means we go the vec_init expander way,
> so we expect that to perform the clearing (possibly redundant with
> the passed in cleared).
Ah, damn. I misread this but. Yeah the ` maybe_lt (count, n_elts)` already
ensures it's set to need_to_clear.
>
> What's more interesting is if we ever get to store_constructor
> with a variable-length vector mode but !REG_P (target)?
>
Yes, clear_storage requires statically knowing the amount of memory to clear
by pieces. With size a poly I don't think there's a way for this to work?
Though I suppose since poly vector stores would work, a fall back could be
storing a vector of 0.
But then the question is why doesn't store_constructor use emit_move_insn
for all cases where the target supports move of that type? Since surely a clear
of
a MEM_P with a zero store is cheaper than piece wise if supported?
So should the condition there instead of REG_P (target) be optab_handler
(mov_optab, mode)?
Thanks,
Tamar
> > }
> >
> > - if (need_to_clear && maybe_gt (size, 0) && !vector)
> > + if (need_to_clear
> > + && (maybe_gt (size, 0) || REG_P (target)))
> > {
> > if (REG_P (target))
> > emit_move_insn (target, CONST0_RTX (mode));
> > @@ -8138,6 +8149,9 @@ store_constructor (tree exp, rtx target, int
> cleared, poly_int64 size,
> > cleared = 1;
> > }
> >
> > + /* Ensure that something has cleared the register. */
> > + gcc_assert ((need_to_clear && cleared) || !need_to_clear);
> > +
> > if (MEM_P (target))
> > alias = MEM_ALIAS_SET (target);
> > else
> > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> > new file mode 100644
> > index
> 0000000000000000000000000000000000000000..d85403640b9ab894b
> 378e741013eb27b76a7e19a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/aarch64/sve/copsi.c
> > @@ -0,0 +1,33 @@
> > +/* { dg-do compile } */
> > +/* { dg-additional-options "-O2" } */
> > +/* { dg-final { check-function-bodies "**" "" "" } } */
> > +
> > +#include <arm_sve.h>
> > +
> > +/*
> > +** func_init4:
> > +** mov z0\.d, x1
> > +** insr z0\.d, x0
> > +** ret
> > +*/
> > +svint64_t __attribute__ ((noipa))
> > +func_init4 (int64_t a, int64_t b)
> > +{
> > + svint64_t temp = { a, b };
> > + return temp;
> > +}
> > +
> > +/*
> > +** func_init3:
> > +** fmov s0, w2
> > +** fmov s0, s0
> > +** insr z0\.s, w1
> > +** insr z0\.s, w0
> > +** ret
> > +*/
> > +svint32_t __attribute__ ((noipa))
> > +func_init3 (int32_t a, int32_t b, int32_t c)
> > +{
> > + svint32_t temp = { a, b, c };
> > + return temp;
> > +}
> >
> >
> >
>
> --
> 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)