From: Christopher Bazley <[email protected]>
When given a constructor of variable-length vector type, the
store_constructor function now builds a vector with the lower bound
of the number of subparts in the vector type and uses it to emit the
body of the kind of insn chosen by the convert_optab_handler function.
Previously, this function used a fallback path of calling
store_constructor_field upon discovering that the number of subparts
in the vector type was not a constant multiple of the number of
subparts in the element type.
For example, this allows GCC to generate the following AArch64 assembly
language output for the tail of a reduction in the slp_6 test:
uaddv d31, p6, z31.b
uaddv d27, p6, z27.b
uaddv d26, p6, z26.b
movi d30, #0
insr z30.b, b26
insr z30.b, b27
insr z30.b, b31
add z25.b, z25.b, z30.b
instead of the following output (with predicated tails for basic block
SLP vectorization but without this change):
addvl x0, sp, #2
movi d0, #0
st1b z0.b, p6, [sp, #2, mul vl]
uaddv d27, p6, z27.b
uaddv d26, p6, z26.b
uaddv d25, p6, z25.b
str b27, [x0]
addvl x0, sp, #1
add x0, x0, 1
ptrue p7.b, vl3
ld1b z0.b, p6/z, [sp, #2, mul vl]
st1b z0.b, p6, [sp, #1, mul vl]
str b26, [x0]
ld1b z0.b, p6/z, [sp, #1, mul vl]
st1b z0.b, p6, [sp]
str b25, [sp, 2]
ld1b z0.b, p6/z, [sp]
add z28.b, z28.b, z0.b
st1b z28.b, p7, [x1]
addvl sp, sp, #3
or the original assembly language output (with neither predicated tails
for basic block SLP vectorization nor this change):
uaddv d31, p6, z31.b
fmov x0, d31
uaddv d31, p6, z26.b
add w6, w6, w0
fmov x0, d31
uaddv d31, p6, z27.b
add w5, w5, w0
fmov x0, d31
add w4, w4, w0
The behavior of vec_init for scalable vector modes was not
previously documented, so rectify that. Any elements beyond the
minimum number of elements implied by the vector mode are
implicitly zero.
gcc/ChangeLog:
* expr.cc (store_constructor): Add an else block to handle
cases of TREE_CODE (TREE_TYPE (exp)) == VECTOR_TYPE in which
exact_div (n_elts, GET_MODE_NUNITS (eltmode)).is_constant
(&const_n_elts) is false similar to the existing "element type
is not a vector type" case except that const_n_elts is taken
from the lower bound of the subparts of the vector type.
* doc/md.texi: Update description of vec_init.
---
gcc/doc/md.texi | 4 +++-
gcc/expr.cc | 22 ++++++++++++++++------
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 90755bdf389a..e28abff06e7b 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -7509,7 +7509,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 de73215ccc66..76bb519e687b 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7503,6 +7503,10 @@ fields_length (const_tree type)
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 +8079,19 @@ 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);
+ }
- 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
--
2.54.0