Initializing a vector with one non-zero element and zeros must
start from a zero vector and insert the element, instead of
broadcasting the element and inserting every zero.
before:
or $r12,$r0,$r0
vreplgr2vr.w $vr0,$r4
vinsgr2vr.w $vr0,$r12,1
vinsgr2vr.w $vr0,$r12,2
vinsgr2vr.w $vr0,$r12,3
movfr2gr.d $r4,$f0
vpickve2gr.d $r5,$vr0,1
after:
vrepli.b $vr0,0
vinsgr2vr.w $vr0,$r4,0
movfr2gr.d $r4,$f0
vpickve2gr.d $r5,$vr0,1
gcc/ChangeLog:
* config/loongarch/loongarch.cc (loongarch_expand_vector_init):
Optimization.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/vector/lasx/vec-init-zero.c: New test.
* gcc.target/loongarch/vector/lsx/vec-init-zero.c: New test.
---
gcc/config/loongarch/loongarch.cc | 31 +++++++++++++++++++
.../loongarch/vector/lasx/vec-init-zero.c | 11 +++++++
.../loongarch/vector/lsx/vec-init-zero.c | 11 +++++++
3 files changed, 53 insertions(+)
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/vec-init-zero.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/vec-init-zero.c
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index bf401602394..7f65787fd40 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -10592,6 +10592,37 @@ loongarch_expand_vector_init (rtx target, rtx vals)
gcc_unreachable ();
}
+ /* Fast path for a mostly-zero initializer such as { x, 0, 0, 0 }:
+ start from a zero vector and insert the single non-zero element.
+ Otherwise we would broadcast a non-zero element and then insert each
+ zero separately, which is both longer and needs a zero in a GPR. */
+ if ((ISA_HAS_LASX && GET_MODE_SIZE (vmode) == 32)
+ || (ISA_HAS_LSX && GET_MODE_SIZE (vmode) == 16))
+ {
+ unsigned int nz = 0, nz_index = 0;
+ rtx zero = CONST0_RTX (imode);
+
+ for (i = 0; i < nelt; i++)
+ if (!rtx_equal_p (val[i], zero))
+ {
+ nz++;
+ nz_index = i;
+ }
+
+ if (nz == 1)
+ {
+ emit_move_insn (target, CONST0_RTX (vmode));
+ op0 = force_reg (imode, val[nz_index]);
+ if (GET_MODE_SIZE (vmode) == 32)
+ emit_insn (loongarch_vec_set256 (target, op0,
+ GEN_INT (nz_index)));
+ else
+ emit_insn (loongarch_vec_set128 (target, op0,
+ GEN_INT (nz_index)));
+ return;
+ }
+ }
+
if (ISA_HAS_LASX && GET_MODE_SIZE (vmode) == 32)
{
/* If all elements are the same, just do a broadcost. */
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vec-init-zero.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vec-init-zero.c
new file mode 100644
index 00000000000..24d6fdadfa7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vec-init-zero.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+/* { dg-final { scan-assembler-times "xvinsgr2vr\.w" 1 } } */
+
+typedef int v8si __attribute__ ((vector_size (32)));
+
+v8si
+init_zero_lasx (int x)
+{
+ return (v8si) {0, 0, 0, 0, x, 0, 0, 0};
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/vec-init-zero.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vec-init-zero.c
new file mode 100644
index 00000000000..ad0e567e7f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vec-init-zero.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-final { scan-assembler-times "vinsgr2vr\.w" 1 } } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+init_zero_lsx (int x)
+{
+ return (v4si) {x, 0, 0, 0};
+}
--
2.55.0