diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2023-11-13 09:16:59 +0000 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2023-11-13 09:16:59 +0000 |
commit | b51bfee1beed03872ea0289cb47dd2336d9f528c (patch) | |
tree | b244944edde12e78e4dc3a8782036a2279a11ec4 /gcc/rust/resolve | |
parent | e9d59a2a5a8e8ce667847372cc480215fa862aa4 (diff) | |
download | gcc-b51bfee1beed03872ea0289cb47dd2336d9f528c.zip gcc-b51bfee1beed03872ea0289cb47dd2336d9f528c.tar.gz gcc-b51bfee1beed03872ea0289cb47dd2336d9f528c.tar.bz2 |
ARC: Improved DImode rotates and right shifts by one bit.
This patch improves the code generated for DImode right shifts (both
arithmetic and logical) by a single bit, and also for DImode rotates
(both left and right) by a single bit. In approach, this is similar
to the recently added DImode left shift by a single bit patch, but
also builds upon the x86's UNSPEC carry flag representation:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632169.html
The benefits can be seen from the four new test cases:
long long ashr(long long x) { return x >> 1; }
Before:
ashr: asl r2,r1,31
lsr_s r0,r0
or_s r0,r0,r2
j_s.d [blink]
asr_s r1,r1,1
After:
ashr: asr.f r1,r1
j_s.d [blink]
rrc r0,r0
unsigned long long lshr(unsigned long long x) { return x >> 1; }
Before:
lshr: asl r2,r1,31
lsr_s r0,r0
or_s r0,r0,r2
j_s.d [blink]
lsr_s r1,r1
After:
lshr: lsr.f r1,r1
j_s.d [blink]
rrc r0,r0
unsigned long long rotl(unsigned long long x) { return (x<<1) | (x>>63); }
Before:
rotl: lsr r12,r1,31
lsr r2,r0,31
asl_s r3,r0,1
asl_s r1,r1,1
or r0,r12,r3
j_s.d [blink]
or_s r1,r1,r2
After:
rotl: add.f r0,r0,r0
adc.f r1,r1,r1
j_s.d [blink]
add.cs r0,r0,1
unsigned long long rotr(unsigned long long x) { return (x>>1) | (x<<63); }
Before:
rotr: asl r12,r1,31
asl r2,r0,31
lsr_s r3,r0
lsr_s r1,r1
or r0,r12,r3
j_s.d [blink]
or_s r1,r1,r2
After:
rotr: asr.f 0,r0
rrc.f r1,r1
j_s.d [blink]
rrc r0,r0
On CPUs without a barrel shifter the improvements are even better.
2023-11-13 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* config/arc/arc.md (UNSPEC_ARC_CC_NEZ): New UNSPEC that
represents the carry flag being set if the operand is non-zero.
(adc_f): New define_insn representing adc with updated flags.
(ashrdi3): New define_expand that only handles shifts by 1.
(ashrdi3_cnt1): New pre-reload define_insn_and_split.
(lshrdi3): New define_expand that only handles shifts by 1.
(lshrdi3_cnt1): New pre-reload define_insn_and_split.
(rrcsi2): New define_insn for rrc (SImode rotate right through carry).
(rrcsi2_carry): Likewise for rrc.f, as above but updating flags.
(rotldi3): New define_expand that only handles rotates by 1.
(rotldi3_cnt1): New pre-reload define_insn_and_split.
(rotrdi3): New define_expand that only handles rotates by 1.
(rotrdi3_cnt1): New pre-reload define_insn_and_split.
(lshrsi3_cnt1_carry): New define_insn for lsr.f.
(ashrsi3_cnt1_carry): New define_insn for asr.f.
(btst_0_carry): New define_insn for asr.f without result.
gcc/testsuite/ChangeLog
* gcc.target/arc/ashrdi3-1.c: New test case.
* gcc.target/arc/lshrdi3-1.c: Likewise.
* gcc.target/arc/rotldi3-1.c: Likewise.
* gcc.target/arc/rotrdi3-1.c: Likewise.
Diffstat (limited to 'gcc/rust/resolve')
0 files changed, 0 insertions, 0 deletions