expand_constructor passed int_expr_size to store_constructor, which is
-1 for a type whose size is a POLY_INT_CST.  The RECORD_TYPE case then
skipped clear_storage, so an empty CONSTRUCTOR of an SVE or RVV tuple
type stored nothing: a register target got only a clobber and a memory
target was left unchanged.  Pass the poly size instead; only types with
a POLY_INT_CST size are affected.

Bootstrapped and regression tested on x86_64-pc-linux-gnu.  On
aarch64-linux-gnu (qemu), regression tested dg.exp, aarch64.exp and
the SVE tests at SVE VL128, and the SVE tests at VL2048.  On
riscv64, compiling gcc.target/riscv/rvv/base changes the asm of the new
test only.  Tested together with the previous patch and the PR123370
patch.

Assisted-by: Claude Opus 5 (Anthropic)

        PR middle-end/121105

gcc/ChangeLog:

        * expr.cc (expand_constructor): Pass a poly_int64 size to
        store_constructor.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/sve/pr121105_1.c: New test.
        * gcc.target/aarch64/sve/pr121105_2.c: New test.
        * g++.target/aarch64/sve/pr121105.C: New test.
        * gcc.target/riscv/rvv/base/pr121105.c: New test.

Signed-off-by: Dominic P <[email protected]>
---
 gcc/expr.cc                                   |   5 +-
 .../g++.target/aarch64/sve/pr121105.C         |  13 ++
 .../gcc.target/aarch64/sve/pr121105_1.c       | 121 ++++++++++++++++++
 .../gcc.target/aarch64/sve/pr121105_2.c       |  33 +++++
 .../gcc.target/riscv/rvv/base/pr121105.c      |  21 +++
 5 files changed, 192 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.target/aarch64/sve/pr121105.C
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr121105_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr121105_2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr121105.c

diff --git a/gcc/expr.cc b/gcc/expr.cc
index a9157dc5d41..6f8255f2d9f 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -9573,7 +9573,10 @@ expand_constructor (tree exp, rtx target, enum 
expand_modifier modifier,
       target = assign_temp (type, TREE_ADDRESSABLE (exp), 1);
     }
 
-  store_constructor (exp, target, 0, int_expr_size (exp), false);
+  poly_int64 size;
+  if (!poly_int_tree_p (size_in_bytes (type), &size))
+    size = -1;
+  store_constructor (exp, target, 0, size, false);
   return target;
 }
 
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr121105.C 
b/gcc/testsuite/g++.target/aarch64/sve/pr121105.C
new file mode 100644
index 00000000000..06aacb6c10a
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr121105.C
@@ -0,0 +1,13 @@
+// PR middle-end/121105
+// { dg-do compile }
+// { dg-options "-O2" }
+
+#include <arm_sve.h>
+
+svfloat32x4_t
+e ()
+{
+  return svfloat32x4_t{};
+}
+
+// { dg-final { scan-assembler-times {\tmovi\td[0-3], #0\n} 4 } }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr121105_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve/pr121105_1.c
new file mode 100644
index 00000000000..f508a35f526
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr121105_1.c
@@ -0,0 +1,121 @@
+/* PR middle-end/121105 */
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+static int
+nonzero (svuint8_t v)
+{
+  return svptest_any (svptrue_b8 (), svcmpne (svptrue_b8 (), v, 0));
+}
+
+__attribute__((noipa)) svfloat32x4_t
+dirty4 (void)
+{
+  svfloat32_t v = svdup_f32 (-1.0f);
+  return svcreate4 (v, v, v, v);
+}
+
+__attribute__((noipa)) svfloat32x4_t
+ret4 (void)
+{
+  svfloat32x4_t x = {};
+  return x;
+}
+
+__attribute__((noipa)) svint8x2_t
+ret2 (void)
+{
+  return (svint8x2_t) {};
+}
+
+__attribute__((noipa)) void
+mem3 (svuint64x3_t *p)
+{
+  *p = (svuint64x3_t) {};
+}
+
+__attribute__((noipa)) void
+dirty_stack (void)
+{
+  volatile unsigned char buf[4096];
+  for (int i = 0; i < 4096; i++)
+    buf[i] = 0xff;
+}
+
+__attribute__((noipa)) int
+check2 (svint16x2_t *p)
+{
+  return (nonzero (svreinterpret_u8 (svget2 (*p, 0)))
+         || nonzero (svreinterpret_u8 (svget2 (*p, 1))));
+}
+
+__attribute__((noipa)) int
+addr2 (void)
+{
+  svint16x2_t x = {};
+  return check2 (&x);
+}
+
+__attribute__((noipa)) svboolx4_t
+dirtyb (void)
+{
+  svbool_t t = svptrue_b8 ();
+  return svcreate4 (t, t, t, t);
+}
+
+__attribute__((noipa)) svboolx4_t
+retb4 (void)
+{
+  return (svboolx4_t) {};
+}
+
+__attribute__((noipa)) void
+memb2 (svboolx2_t *p)
+{
+  *p = (svboolx2_t) {};
+}
+
+int
+main (void)
+{
+  dirty4 ();
+  svfloat32x4_t a = ret4 ();
+  if (nonzero (svreinterpret_u8 (svget4 (a, 0)))
+      || nonzero (svreinterpret_u8 (svget4 (a, 1)))
+      || nonzero (svreinterpret_u8 (svget4 (a, 2)))
+      || nonzero (svreinterpret_u8 (svget4 (a, 3))))
+    __builtin_abort ();
+
+  dirty4 ();
+  svint8x2_t b = ret2 ();
+  if (nonzero (svreinterpret_u8 (svget2 (b, 0)))
+      || nonzero (svreinterpret_u8 (svget2 (b, 1))))
+    __builtin_abort ();
+
+  svuint64_t m1 = svdup_u64 (-1);
+  svuint64x3_t c = svcreate3 (m1, m1, m1);
+  mem3 (&c);
+  if (nonzero (svreinterpret_u8 (svget3 (c, 0)))
+      || nonzero (svreinterpret_u8 (svget3 (c, 1)))
+      || nonzero (svreinterpret_u8 (svget3 (c, 2))))
+    __builtin_abort ();
+
+  dirty_stack ();
+  if (addr2 ())
+    __builtin_abort ();
+
+  svbool_t all = svptrue_b8 ();
+  dirtyb ();
+  svboolx4_t d = retb4 ();
+  if (svptest_any (all, svget4 (d, 0)) || svptest_any (all, svget4 (d, 1))
+      || svptest_any (all, svget4 (d, 2)) || svptest_any (all, svget4 (d, 3)))
+    __builtin_abort ();
+
+  svboolx2_t e = svcreate2 (all, all);
+  memb2 (&e);
+  if (svptest_any (all, svget2 (e, 0)) || svptest_any (all, svget2 (e, 1)))
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr121105_2.c 
b/gcc/testsuite/gcc.target/aarch64/sve/pr121105_2.c
new file mode 100644
index 00000000000..1c50e31422f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr121105_2.c
@@ -0,0 +1,33 @@
+/* PR middle-end/121105 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svboolx2_t
+ret2 (void)
+{
+  svboolx2_t x = {};
+  return x;
+}
+
+svboolx4_t
+ret4 (void)
+{
+  return (svboolx4_t) {};
+}
+
+void
+mem2 (svboolx2_t *p)
+{
+  *p = (svboolx2_t) {};
+}
+
+void
+mem4 (svboolx4_t *p)
+{
+  *p = (svboolx4_t) {};
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-9]+\.b\n} 12 } } */
+/* { dg-final { scan-assembler-times {\tstr\tp[0-9]+, \[x0(?:, #[1-3], mul 
vl)?\]\n} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr121105.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/pr121105.c
new file mode 100644
index 00000000000..118d4f04ed3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr121105.c
@@ -0,0 +1,21 @@
+/* PR middle-end/121105 */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O2" } */
+
+#include "riscv_vector.h"
+
+vint32m1x4_t
+ret4 (void)
+{
+  vint32m1x4_t x = {};
+  return x;
+}
+
+void
+mem2 (vint8m1x2_t *p)
+{
+  *p = (vint8m1x2_t) {};
+}
+
+/* { dg-final { scan-assembler-times 
{(?:vmv\.v\.i|vmv1r\.v)\s+v(?:8|9|10|11),} 4 } } */
+/* { dg-final { scan-assembler-times {vs1r\.v|vse8\.v} 2 } } */
-- 
2.56.0

Reply via email to