]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ARC: Split asl dst,1,src into bset dst,0,src to implement 1<<x.
authorRoger Sayle <roger@nextmovesoftware.com>
Mon, 16 Oct 2023 12:03:09 +0000 (13:03 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Mon, 16 Oct 2023 12:03:09 +0000 (13:03 +0100)
This patch adds a pre-reload splitter to arc.md, to use the bset (set
specific bit instruction) to implement 1<<x (i.e. left shifts of one)
on ARC processors that don't have a barrel shifter.

Currently,

int foo(int x) {
  return 1 << x;
}

when compiled with -O2 -mcpu=em is compiled as a loop:

foo: mov_s   r2,1    ;3
        and.f lp_count,r0, 0x1f
        lpnz    2f
        add r2,r2,r2
        nop
2:      # end single insn loop
        j_s.d   [blink]
        mov_s   r0,r2   ;4

with this patch we instead generate a single instruction:

foo: bset    r0,0,r0
        j_s     [blink]

2023-10-16  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
* config/arc/arc.md (*ashlsi3_1): New pre-reload splitter to
use bset dst,0,src to implement 1<<x on !TARGET_BARREL_SHIFTER.

gcc/config/arc/arc.md

index a936a8be53d92dac4217d42a04018215a2bf0c45..22af0bf47ddb6e151d19fd18d74dfe5c8faa7247 100644 (file)
@@ -3421,6 +3421,22 @@ archs4x, archs4xd"
    (set_attr "predicable" "no,no,yes,no,no")
    (set_attr "cond" "nocond,canuse,canuse,nocond,nocond")])
 
+;; Split asl dst,1,src into bset dst,0,src.
+(define_insn_and_split "*ashlsi3_1"
+  [(set (match_operand:SI 0 "dest_reg_operand")
+       (ashift:SI (const_int 1)
+                  (match_operand:SI 1 "nonmemory_operand")))]
+  "!TARGET_BARREL_SHIFTER
+   && arc_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+       (ior:SI (ashift:SI (const_int 1) (match_dup 1))
+               (const_int 0)))]
+  ""
+  [(set_attr "type" "shift")
+   (set_attr "length" "8")])
+
 (define_insn_and_split "*ashlsi3_nobs"
   [(set (match_operand:SI 0 "dest_reg_operand")
        (ashift:SI (match_operand:SI 1 "register_operand")