]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
x86: Handle small OP size in setmem_epilogue_gen_val
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 3 Oct 2025 23:02:20 +0000 (07:02 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Sun, 5 Oct 2025 21:19:41 +0000 (05:19 +0800)
Since OP size passed to setmem_epilogue_gen_val may be smaller than the
required vector size, duplicate it first before setting vector.

gcc/

PR target/122150
* config/i386/i386-expand.cc (setmem_epilogue_gen_val): Duplicate
OP if its size is smaller than MODE size.

gcc/testsuite/

PR target/122150
* gcc.target/i386/pr122150.c: New test.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
gcc/config/i386/i386-expand.cc
gcc/testsuite/gcc.target/i386/pr122150.c [new file with mode: 0644]

index c6f42275a3e50aba85b18e3d3c72d1d529881ae9..0115af4d359e6da8ee536ae86b2d955406e2975b 100644 (file)
@@ -8443,9 +8443,28 @@ setmem_epilogue_gen_val (void *op_p, void *prev_p, HOST_WIDE_INT,
 
       unsigned int op_size = GET_MODE_SIZE (op_mode);
       unsigned int size = GET_MODE_SIZE (mode);
-      unsigned int nunits = op_size / GET_MODE_SIZE (QImode);
-      machine_mode vec_mode
-       = mode_for_vector (QImode, nunits).require ();
+      unsigned int nunits;
+      machine_mode vec_mode;
+      if (op_size < size)
+       {
+         /* If OP size is smaller than MODE size, duplicate it.  */
+         nunits = size / GET_MODE_SIZE (QImode);
+         vec_mode = mode_for_vector (QImode, nunits).require ();
+         nunits = size / op_size;
+         gcc_assert (SCALAR_INT_MODE_P (op_mode));
+         machine_mode dup_mode
+           = mode_for_vector (as_a <scalar_mode> (op_mode),
+                              nunits).require ();
+         target = gen_reg_rtx (vec_mode);
+         op = gen_vec_duplicate (dup_mode, op);
+         rtx dup_op = gen_reg_rtx (dup_mode);
+         emit_move_insn (dup_op, op);
+         op = gen_rtx_SUBREG (vec_mode, dup_op, 0);
+         emit_move_insn (target, op);
+         return target;
+       }
+      nunits = op_size / GET_MODE_SIZE (QImode);
+      vec_mode = mode_for_vector (QImode, nunits).require ();
       target = gen_reg_rtx (vec_mode);
       op = gen_rtx_SUBREG (vec_mode, op, 0);
       emit_move_insn (target, op);
diff --git a/gcc/testsuite/gcc.target/i386/pr122150.c b/gcc/testsuite/gcc.target/i386/pr122150.c
new file mode 100644 (file)
index 0000000..973c34d
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-mstringop-strategy=unrolled_loop" } */
+
+char c[2841];
+
+__attribute__((noipa))
+void
+foo (void)
+{
+  __builtin_memset (&c, 1, 2841);
+}
+
+int
+main (void)
+{
+  foo ();
+  for (unsigned i = 0; i < sizeof (c); i++)
+    if (c[i] != 1)
+      __builtin_abort();
+  return 0;
+}