ARC: Split asl dst,1,src into bset dst,0,src to implement 1<<x.

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.
This commit is contained in:
Roger Sayle 2023-10-16 13:03:09 +01:00
parent d6ebe61889
commit 817a701681

View 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")