public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] MIPS: Use unaligned access to expand block_move on r6
@ 2023-05-31  9:55 YunQiang Su
  2023-05-31  9:55 ` [PATCH v2 2/2] MIPS: Don't expand large unaligned block move YunQiang Su
  0 siblings, 1 reply; 2+ messages in thread
From: YunQiang Su @ 2023-05-31  9:55 UTC (permalink / raw)
  To: gcc-patches
  Cc: macro, jiaxun.yang, syq, richard.sandiford, jeffreyalaw, YunQiang Su

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

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;
 }
 \f
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);
+}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH v2 2/2] MIPS: Don't expand large unaligned block move
  2023-05-31  9:55 [PATCH v2 1/2] MIPS: Use unaligned access to expand block_move on r6 YunQiang Su
@ 2023-05-31  9:55 ` YunQiang Su
  0 siblings, 0 replies; 2+ messages in thread
From: YunQiang Su @ 2023-05-31  9:55 UTC (permalink / raw)
  To: gcc-patches
  Cc: macro, jiaxun.yang, syq, richard.sandiford, jeffreyalaw, YunQiang Su

For large unaligned block move, lib call may have better performance
than expanding.

Let's just return, if length is
	larger than 64 on O32
	larger than 128 on N32/N64.

Here are some test results:

CPU		Aligned	O32	N32	N64
Cavium 7130	1	72	192	192
Cavium 7130	2	96	192	192
Cavium 7130	4	+inf	192	192
Cavium 7130	8	+inf	+inf	+inf
LS3A 2000	1	32	32	64
LS3A 2000	2	32	64	64
LS3A 2000	4	+inf	32	48
LS3A 2000	8	+inf	+inf	+inf
LS3A 4000	1	32	64	128
LS3A 4000	2	64	64	128
LS3A 4000	4	192	128	192
LS3A 4000	8	192	+inf	+inf
Ingenic X2000	1	96	-	-
Ingenic X2000	2	96	-	-
Ingenic X2000	4	+inf	-	-
interAptiv	1	64	-	-
interAptiv	2	64	-	-
interAptiv	4	+inf	-	-
P6600		1	64	128	128
P6600		2	64	128	128
P6600		4	256	192	128
P6600		8	+inf	+inf	+inf
P6600		1U	48	48	48	-mno-unaligned-access
P6600		2U	128	96	96	-mno-unaligned-access
P6600		4U	384	768	768	-mno-unaligned-access
P6600		8U	1024	+inf	+inf	-mno-unaligned-access
I6500		1	384	896	640
I6500		2	256	768	512
I6500		4	384	704	512
I6500		8	512	1024	1024
I6500		1U	32	32	32	-mno-unaligned-access
I6500		2U	96	64	64	-mno-unaligned-access
I6500		4U	384	640	768	-mno-unaligned-access
I6500		8U	256	+inf	+inf	-mno-unaligned-access

When the length of block move is larger than this value,
(g)libc call has better performance.

gcc/
	* config/mips/mips.cc (mips_expand_block_move): don't expand
	large unaligned block move.

gcc/testsuite/
	* gcc.target/mips/expand-block-move-large.c: new test.
---
 gcc/config/mips/mips.cc                       |  6 +++++
 .../gcc.target/mips/expand-block-move-large.c | 22 +++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/mips/expand-block-move-large.c

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index ca297e3c1e5..7a7f4be627f 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -8308,6 +8308,12 @@ mips_expand_block_move (rtx dest, rtx src, rtx length)
 	  || MEM_ALIGN (dest) < MIPS_MIN_MOVE_MEM_ALIGN))
     return false;
 
+  if ((ISA_HAS_LWL_LWR || ISA_HAS_UNALIGNED_ACCESS)
+      && INTVAL (length) > MIPS_MAX_MOVE_BYTES_STRAIGHT * 2
+      && MEM_ALIGN (src) < BITS_PER_WORD
+      && MEM_ALIGN (dest) < BITS_PER_WORD)
+    return false;
+
   if (INTVAL (length) <= MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER)
     {
       mips_block_move_straight (dest, src, INTVAL (length));
diff --git a/gcc/testsuite/gcc.target/mips/expand-block-move-large.c b/gcc/testsuite/gcc.target/mips/expand-block-move-large.c
new file mode 100644
index 00000000000..98705f6c560
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/expand-block-move-large.c
@@ -0,0 +1,22 @@
+/* { dg-final { scan-assembler "memcpy" } } */
+/* { dg-final { scan-assembler-not "lwl" } } */
+/* { dg-final { scan-assembler-not "swl" } } */
+/* { dg-final { scan-assembler-not "lwr" } } */
+/* { dg-final { scan-assembler-not "swr" } } */
+/* { dg-final { scan-assembler-not "ldl" } } */
+/* { dg-final { scan-assembler-not "sdl" } } */
+/* { dg-final { scan-assembler-not "ldr" } } */
+/* { dg-final { scan-assembler-not "sdr" } } */
+
+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);
+}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-05-31  9:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-31  9:55 [PATCH v2 1/2] MIPS: Use unaligned access to expand block_move on r6 YunQiang Su
2023-05-31  9:55 ` [PATCH v2 2/2] MIPS: Don't expand large unaligned block move YunQiang Su

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).