Skip to content

Commit 987caaa

Browse files
committed
[xstormy16] Improved SImode shifts by two bits.
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,gcc-mirror#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 2023-04-23 Roger Sayle <[email protected]> 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.
1 parent 5830953 commit 987caaa

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

gcc/config/stormy16/stormy16.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,29 @@ xstormy16_output_shift (machine_mode mode, enum rtx_code code,
21052105
return r;
21062106
}
21072107

2108+
/* For shifts of size 2, we can use two shifts of size 1. */
2109+
if (size == 2)
2110+
{
2111+
switch (code)
2112+
{
2113+
case ASHIFT:
2114+
sprintf (r, "shl %s,#1 | rlc %s,#1 | shl %s,#1 | rlc %s,#1",
2115+
r0, r1, r0, r1);
2116+
break;
2117+
case ASHIFTRT:
2118+
sprintf (r, "asr %s,#1 | rrc %s,#1 | asr %s,#1 | rrc %s,#1",
2119+
r1, r0, r1, r0);
2120+
break;
2121+
case LSHIFTRT:
2122+
sprintf (r, "shr %s,#1 | rrc %s,#1 | shr %s,#1 | rrc %s,#1",
2123+
r1, r0, r1, r0);
2124+
break;
2125+
default:
2126+
gcc_unreachable ();
2127+
}
2128+
return r;
2129+
}
2130+
21082131
/* For large shifts, there are easy special cases. */
21092132
if (size == 16)
21102133
{
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-O2" } */
3+
4+
unsigned long ashift_1(unsigned long x) { return x << 1; }
5+
unsigned long ashift_2(unsigned long x) { return x << 2; }
6+
unsigned long lshiftrt_1(unsigned long x) { return x >> 1; }
7+
unsigned long lshiftrt_2(unsigned long x) { return x >> 2; }
8+
long ashiftrt_1(long x) { return x >> 1; }
9+
long ashiftrt_2(long x) { return x >> 2; }
10+
11+
/* { dg-final { scan-assembler-not "mov " } } */
12+
/* { dg-final { scan-assembler-not "or " } } */

0 commit comments

Comments
 (0)