aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arc/arc.md
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2023-10-30 16:12:30 +0000
committerRoger Sayle <roger@nextmovesoftware.com>2023-10-30 16:12:30 +0000
commitd24c3c533454449f4bfe3db5a4c7d0eaff08e3c7 (patch)
tree5a8e904ec77b7022753b4aab7b6bc93a3f183e49 /gcc/config/arc/arc.md
parentfb1941d08fc3711b058c1e148e9ce7ed9b7dfbba (diff)
downloadgcc-d24c3c533454449f4bfe3db5a4c7d0eaff08e3c7.zip
gcc-d24c3c533454449f4bfe3db5a4c7d0eaff08e3c7.tar.gz
gcc-d24c3c533454449f4bfe3db5a4c7d0eaff08e3c7.tar.bz2
ARC: Improved SImode shifts and rotates with -mswap.
This patch improves the code generated by the ARC back-end for CPUs without a barrel shifter but with -mswap. The -mswap option provides a SWAP instruction that implements SImode rotations by 16, but also logical shift instructions (left and right) by 16 bits. Clearly these are also useful building blocks for implementing shifts by 17, 18, etc. which would otherwise require a loop. As a representative example: int shl20 (int x) { return x << 20; } GCC with -O2 -mcpu=em -mswap would previously generate: shl20: mov lp_count,10 lp 2f add r0,r0,r0 add r0,r0,r0 2: # end single insn loop j_s [blink] with this patch we now generate: shl20: mov_s r2,0 ;3 lsl16 r0,r0 add3 r0,r2,r0 j_s.d [blink] asl_s r0,r0 Although both are four instructions (excluding the j_s), the original takes ~22 cycles, and replacement ~4 cycles. 2023-10-30 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * config/arc/arc.cc (arc_split_ashl): Use lsl16 on TARGET_SWAP. (arc_split_ashr): Use swap and sign-extend on TARGET_SWAP. (arc_split_lshr): Use lsr16 on TARGET_SWAP. (arc_split_rotl): Use swap on TARGET_SWAP. (arc_split_rotr): Likewise. * config/arc/arc.md (ANY_ROTATE): New code iterator. (<ANY_ROTATE>si2_cnt16): New define_insn for alternate form of swap instruction on TARGET_SWAP. (ashlsi2_cnt16): Rename from *ashlsi16_cnt16 and move earlier. (lshrsi2_cnt16): New define_insn for LSR16 instruction. (*ashlsi2_cnt16): See above. gcc/testsuite/ChangeLog * gcc.target/arc/lsl16-1.c: New test case. * gcc.target/arc/lsr16-1.c: Likewise. * gcc.target/arc/swap-1.c: Likewise. * gcc.target/arc/swap-2.c: Likewise.
Diffstat (limited to 'gcc/config/arc/arc.md')
-rw-r--r--gcc/config/arc/arc.md43
1 files changed, 32 insertions, 11 deletions
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index ee43887..11cd22c 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -3353,6 +3353,7 @@ archs4x, archs4xd"
;; Shift instructions.
+(define_code_iterator ANY_ROTATE [rotate rotatert])
(define_code_iterator ANY_SHIFT_ROTATE [ashift ashiftrt lshiftrt
rotate rotatert])
@@ -3415,6 +3416,37 @@ archs4x, archs4xd"
(set_attr "predicable" "no,no,yes,no,no")
(set_attr "cond" "nocond,canuse,canuse,nocond,nocond")])
+(define_insn "<insn>si2_cnt16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ANY_ROTATE:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16)))]
+ "TARGET_SWAP"
+ "swap\\t%0,%1"
+ [(set_attr "length" "4")
+ (set_attr "type" "two_cycle_core")])
+
+(define_insn "ashlsi2_cnt16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL")
+ (const_int 16)))]
+ "TARGET_SWAP && TARGET_V2"
+ "lsl16\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "false")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
+(define_insn "lshrsi2_cnt16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "rL")
+ (const_int 16)))]
+ "TARGET_SWAP && TARGET_V2"
+ "lsr16\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "false")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
;; Split asl dst,1,src into bset dst,0,src.
(define_insn_and_split "*ashlsi3_1"
[(set (match_operand:SI 0 "dest_reg_operand")
@@ -5929,17 +5961,6 @@ archs4x, archs4xd"
(set_attr "length" "4")
(set_attr "predicable" "no")])
-(define_insn "*ashlsi2_cnt16"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL")
- (const_int 16)))]
- "TARGET_SWAP && TARGET_V2"
- "lsl16\\t%0,%1"
- [(set_attr "type" "shift")
- (set_attr "iscompact" "false")
- (set_attr "length" "4")
- (set_attr "predicable" "no")])
-
(define_insn "lshrsi3_cnt1"
[(set (match_operand:SI 0 "dest_reg_operand" "=q,w")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "q,c")