[v2,1/2] MIPS: Use unaligned access to expand block_move on r6

Message ID 20230531095551.1299186-1-yunqiang.su@cipunited.com
State Accepted
Headers
Series [v2,1/2] MIPS: Use unaligned access to expand block_move on r6 |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

YunQiang Su May 31, 2023, 9:55 a.m. UTC
  MIPSr6 support unaligned memory access with normal lh/sh/lw/sw/ld/sd
instructions, and thus lwl/lwr/ldl/ldr and swl/swr/sdl/sdr is removed.

For microarchitecture, these memory access instructions issue 2
operation if the address is not aligned, which is like what lwl family
do.

For some situation (such as accessing boundary of pages) on some
microarchitectures, the unaligned access may not be good enough,
then the kernel should trap&emu it: the kernel may need
-mno-unalgined-access option.

gcc/
	* config/mips/mips.cc (mips_expand_block_move): don't expand for
	r6 with -mno-unaligned-access option if one or both of src and
	dest are unaligned. restruct: return directly if length is not const.
	(mips_block_move_straight): emit_move if ISA_HAS_UNALIGNED_ACCESS.

gcc/testsuite/
	* gcc.target/mips/expand-block-move-r6-no-unaligned.c: new test.
	* gcc.target/mips/expand-block-move-r6.c: new test.
---
 gcc/config/mips/mips.cc                       | 36 ++++++++++---------
 .../mips/expand-block-move-r6-no-unaligned.c  | 15 ++++++++
 .../gcc.target/mips/expand-block-move-r6.c    | 20 +++++++++++
 3 files changed, 54 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/expand-block-move-r6-no-unaligned.c
 create mode 100644 gcc/testsuite/gcc.target/mips/expand-block-move-r6.c
  

Patch

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index ca491b981a3..ca297e3c1e5 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -8167,8 +8167,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
     {
@@ -8190,7 +8191,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
 	{
@@ -8203,7 +8204,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
       {
@@ -8299,25 +8300,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);
+}