diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index fec25bdf8ea..f9861020902 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -8286,8 +8286,9 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) For ISA_HAS_LWL_LWR we rely on the lwl/lwr & swl/swr load. Otherwise picking the minimum of alignment or BITS_PER_WORD gets us the desired size for bits. */ - - if (!ISA_HAS_LWL_LWR) + if (ISA_HAS_UNALIGNED_ACCESS) + bits = BITS_PER_WORD; + else if (!ISA_HAS_LWL_LWR) bits = MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest))); else { @@ -8309,7 +8310,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) { regs[i] = gen_reg_rtx (mode); - if (MEM_ALIGN (src) >= bits) + if (ISA_HAS_UNALIGNED_ACCESS || MEM_ALIGN (src) >= bits) mips_emit_move (regs[i], adjust_address (src, mode, offset)); else { @@ -8322,7 +8323,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) /* Copy the chunks to the destination. */ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) - if (MEM_ALIGN (dest) >= bits) + if (ISA_HAS_UNALIGNED_ACCESS || MEM_ALIGN (dest) >= bits) mips_emit_move (adjust_address (dest, mode, offset), regs[i]); else { @@ -8418,25 +8419,26 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, bool mips_expand_block_move (rtx dest, rtx src, rtx length) { - if (!ISA_HAS_LWL_LWR + if (!CONST_INT_P (length)) + return false; + + if (mips_isa_rev >= 6 && !ISA_HAS_UNALIGNED_ACCESS && (MEM_ALIGN (src) < MIPS_MIN_MOVE_MEM_ALIGN || MEM_ALIGN (dest) < MIPS_MIN_MOVE_MEM_ALIGN)) return false; - if (CONST_INT_P (length)) + if (INTVAL (length) <= MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER) { - if (INTVAL (length) <= MIPS_MAX_MOVE_BYTES_STRAIGHT) - { - mips_block_move_straight (dest, src, INTVAL (length)); - return true; - } - else if (optimize) - { - mips_block_move_loop (dest, src, INTVAL (length), - MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER); - return true; - } + mips_block_move_straight (dest, src, INTVAL (length)); + return true; } + else if (optimize) + { + mips_block_move_loop (dest, src, INTVAL (length), + MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER); + return true; + } + return false; } diff --git a/gcc/testsuite/gcc.target/mips/expand-block-move-r6-no-unaligned.c b/gcc/testsuite/gcc.target/mips/expand-block-move-r6-no-unaligned.c new file mode 100644 index 00000000000..0fdcac2d30b --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/expand-block-move-r6-no-unaligned.c @@ -0,0 +1,15 @@ +/* { dg-options "isa_rev>=6 -mno-unaligned-access" } */ +/* { dg-final { scan-assembler "memcpy" } } */ + +char a[4097], b[4097]; +#ifdef __mips64 +#define MAX_SIZE 128 +#else +#define MAX_SIZE 64 +#endif + +NOCOMPRESSION void +foo () +{ + __builtin_memcpy(&a[1], &b[1], MAX_SIZE-16); +} diff --git a/gcc/testsuite/gcc.target/mips/expand-block-move-r6.c b/gcc/testsuite/gcc.target/mips/expand-block-move-r6.c new file mode 100644 index 00000000000..9e247b15d06 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/expand-block-move-r6.c @@ -0,0 +1,20 @@ +/* { dg-options "isa_rev>=6" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" } { "" } } */ +/* { dg-final { scan-assembler-not "memcpy" } } */ +/* { dg-final { scan-assembler-not "lb\t" } } */ +/* { dg-final { scan-assembler-not "sb\t" } } */ +/* { dg-final { scan-assembler-not "lh\t" } } */ +/* { dg-final { scan-assembler-not "sh\t" } } */ + +char a[4097], b[4097]; +#ifdef __mips64 +#define MAX_SIZE 128 +#else +#define MAX_SIZE 64 +#endif + +NOCOMPRESSION void +foo () +{ + __builtin_memcpy(&a[1], &b[1], MAX_SIZE-16); +}