[xstormy16] Improved SImode shifts by two bits.

Message ID 008401d97539$87cdd6e0$976984a0$@nextmovesoftware.com
State Accepted
Headers
Series [xstormy16] Improved SImode shifts by two bits. |

Checks

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

Commit Message

Roger Sayle April 22, 2023, 4:43 p.m. UTC
  Currently on xstormy16 SImode shifts by a single bit require two
instructions, and shifts by other non-zero integer immediate constants
require five instructions.  This patch implements the obvious optimization
that shifts by two bits can be done in four instructions, by using two
single-bit sequences.

Hence, ashift_2 was previously generated as:
        mov r7,r2 | shl r2,#2 | shl r3,#2 | shr r7,#14 | or r3,r7
        ret
and with this patch we now generate:
        shl r2,#1 | rlc r3,#1 | shl r2,#1 | rlc r3,#1
        ret

This patch has been tested by building a cross-compiler to xstormy16-elf
on x86_64-pc-linux-gnu, and confirming that the new test case passes with
"make -k check-gcc".  Ok for mainline?


2023-04-22  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
        * config/stormy16/stormy16.cc (xstormy16_output_shift): Implement
        SImode shifts by two by performing a single bit SImode shift twice.

gcc/testsuite/ChangeLog
        * gcc.target/xstormy16/shiftsi.c: New test case.


Thanks in advance,
Roger
--
  

Comments

Jeff Law April 22, 2023, 10:01 p.m. UTC | #1
On 4/22/23 10:43, Roger Sayle wrote:
> 
> Currently on xstormy16 SImode shifts by a single bit require two
> instructions, and shifts by other non-zero integer immediate constants
> require five instructions.  This patch implements the obvious optimization
> that shifts by two bits can be done in four instructions, by using two
> single-bit sequences.
> 
> Hence, ashift_2 was previously generated as:
>          mov r7,r2 | shl r2,#2 | shl r3,#2 | shr r7,#14 | or r3,r7
>          ret
> and with this patch we now generate:
>          shl r2,#1 | rlc r3,#1 | shl r2,#1 | rlc r3,#1
>          ret
> 
> This patch has been tested by building a cross-compiler to xstormy16-elf
> on x86_64-pc-linux-gnu, and confirming that the new test case passes with
> "make -k check-gcc".  Ok for mainline?
> 
> 
> 2023-04-22  Roger Sayle  <roger@nextmovesoftware.com>
> 
> gcc/ChangeLog
>          * config/stormy16/stormy16.cc (xstormy16_output_shift): Implement
>          SImode shifts by two by performing a single bit SImode shift twice.
> 
> gcc/testsuite/ChangeLog
>          * gcc.target/xstormy16/shiftsi.c: New test case.
OK.
jeff
  

Patch

diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
index 1ed619a..cf2f807 100644
--- a/gcc/config/stormy16/stormy16.cc
+++ b/gcc/config/stormy16/stormy16.cc
@@ -2105,6 +2105,29 @@  xstormy16_output_shift (machine_mode mode, enum rtx_code code,
       return r;
     }
 
+  /* For shifts of size 2, we can use two shifts of size 1.  */
+  if (size == 2)
+    {
+      switch (code)
+	{
+	case ASHIFT:
+	  sprintf (r, "shl %s,#1 | rlc %s,#1 | shl %s,#1 | rlc %s,#1",
+		   r0, r1, r0, r1);
+	  break;
+	case ASHIFTRT:
+	  sprintf (r, "asr %s,#1 | rrc %s,#1 | asr %s,#1 | rrc %s,#1",
+		   r1, r0, r1, r0);
+	  break;
+	case LSHIFTRT:
+	  sprintf (r, "shr %s,#1 | rrc %s,#1 | shr %s,#1 | rrc %s,#1",
+		   r1, r0, r1, r0);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+      return r;
+    }
+
   /* For large shifts, there are easy special cases.  */
   if (size == 16)
     {
diff --git a/gcc/testsuite/gcc.target/xstormy16/shiftsi.c b/gcc/testsuite/gcc.target/xstormy16/shiftsi.c
new file mode 100644
index 0000000..42bbca7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/xstormy16/shiftsi.c
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long ashift_1(unsigned long x) { return x << 1; }
+unsigned long ashift_2(unsigned long x) { return x << 2; }
+unsigned long lshiftrt_1(unsigned long x) { return x >> 1; }
+unsigned long lshiftrt_2(unsigned long x) { return x >> 2; }
+long ashiftrt_1(long x) { return x >> 1; }
+long ashiftrt_2(long x) { return x >> 2; }
+
+/* { dg-final { scan-assembler-not "mov " } } */
+/* { dg-final { scan-assembler-not "or " } } */