Message ID | 008401d97539$87cdd6e0$976984a0$@nextmovesoftware.com |
---|---|
State | New |
Headers | show |
Series | [xstormy16] Improved SImode shifts by two bits. | expand |
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
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 " } } */