return true;
}
+static machine_mode
+loongarch_mode_for_move_size (HOST_WIDE_INT size)
+{
+ switch (size)
+ {
+ case 32:
+ return V32QImode;
+ case 16:
+ return V16QImode;
+ }
+
+ return int_mode_for_size (size * BITS_PER_UNIT, 0).require ();
+}
+
/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
Assume that the areas do not overlap. */
for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2)
{
- mode = int_mode_for_size (delta_cur * BITS_PER_UNIT, 0).require ();
+ mode = loongarch_mode_for_move_size (delta_cur);
for (; offs + delta_cur <= length; offs += delta_cur, i++)
{
for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2)
{
- mode = int_mode_for_size (delta_cur * BITS_PER_UNIT, 0).require ();
+ mode = loongarch_mode_for_move_size (delta_cur);
for (; offs + delta_cur <= length; offs += delta_cur, i++)
loongarch_emit_move (adjust_address (dest, mode, offs), regs[i]);
HOST_WIDE_INT align = INTVAL (r_align);
- if (!TARGET_STRICT_ALIGN || align > UNITS_PER_WORD)
- align = UNITS_PER_WORD;
+ if (!TARGET_STRICT_ALIGN || align > LARCH_MAX_MOVE_PER_INSN)
+ align = LARCH_MAX_MOVE_PER_INSN;
if (length <= align * LARCH_MAX_MOVE_OPS_STRAIGHT)
{
least twice. */
#define LARCH_MAX_MOVE_OPS_STRAIGHT (LARCH_MAX_MOVE_OPS_PER_LOOP_ITER * 2)
+#define LARCH_MAX_MOVE_PER_INSN \
+ (ISA_HAS_LASX ? 32 : (ISA_HAS_LSX ? 16 : UNITS_PER_WORD))
+
/* The base cost of a memcpy call, for MOVE_RATIO and friends. These
values were determined experimentally by benchmarking with CSiBE.
*/
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -march=la464 -mno-strict-align" } */
+/* { dg-final { scan-assembler-times "xvst" 2 } } */
+/* { dg-final { scan-assembler-times "\tvst" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 95); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -march=la464 -mno-strict-align" } */
+/* { dg-final { scan-assembler-times "xvst" 2 } } */
+/* { dg-final { scan-assembler-times "\tvst" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+typedef char __attribute__ ((vector_size (32), aligned (32))) vec;
+extern vec a[], b[];
+void test() { __builtin_memcpy(a, b, 95); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=la464 -mabi=lp64d -mstrict-align" } */
+/* { dg-final { scan-assembler-not "vst" } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 16); }