diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2023-10-30 16:21:28 +0000 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2023-10-30 16:21:28 +0000 |
commit | a3da9adeb457d4f01c4e695a9621f90c2e2a5e68 (patch) | |
tree | 12eb744747aca917c307b4871a1acc96f589444e | |
parent | 31cc9824d1cd5e0f7fa145d0831a923479333cd6 (diff) | |
download | gcc-a3da9adeb457d4f01c4e695a9621f90c2e2a5e68.zip gcc-a3da9adeb457d4f01c4e695a9621f90c2e2a5e68.tar.gz gcc-a3da9adeb457d4f01c4e695a9621f90c2e2a5e68.tar.bz2 |
ARC: Convert (signed<<31)>>31 to -(signed&1) without barrel shifter.
This patch optimizes PR middle-end/101955 for the ARC backend. On ARC
CPUs with a barrel shifter, using two shifts is optimal as:
asl_s r0,r0,31
asr_s r0,r0,31
but without a barrel shifter, GCC -O2 -mcpu=em currently generates:
and r2,r0,1
ror r2,r2
add.f 0,r2,r2
sbc r0,r0,r0
with this patch, we now generate the smaller, faster and non-flags
clobbering:
bmsk_s r0,r0,0
neg_s r0,r0
2023-10-30 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
PR middle-end/101955
* config/arc/arc.md (*extvsi_1_0): New define_insn_and_split
to convert sign extract of the least significant bit into an
AND $1 then a NEG when !TARGET_BARREL_SHIFTER.
gcc/testsuite/ChangeLog
PR middle-end/101955
* gcc.target/arc/pr101955.c: New test case.
-rw-r--r-- | gcc/config/arc/arc.md | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arc/pr101955.c | 10 |
2 files changed, 24 insertions, 0 deletions
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 11cd22c..96ff62d 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -5905,6 +5905,20 @@ archs4x, archs4xd" (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))]) (match_dup 1)]) +;; Split sign-extension of single least significant bit as and x,$1;neg x +(define_insn_and_split "*extvsi_1_0" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extract:SI (match_operand:SI 1 "register_operand" "0") + (const_int 1) + (const_int 0)))] + "!TARGET_BARREL_SHIFTER" + "#" + "&& 1" + [(set (match_dup 0) (and:SI (match_dup 1) (const_int 1))) + (set (match_dup 0) (neg:SI (match_dup 0)))] + "" + [(set_attr "length" "8")]) + (define_insn_and_split "rotlsi3_cnt1" [(set (match_operand:SI 0 "dest_reg_operand" "=r") (rotate:SI (match_operand:SI 1 "register_operand" "r") diff --git a/gcc/testsuite/gcc.target/arc/pr101955.c b/gcc/testsuite/gcc.target/arc/pr101955.c new file mode 100644 index 0000000..3c66885 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/pr101955.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=em" } */ + +int f(int a) +{ + return (a << 31) >> 31; +} + +/* { dg-final { scan-assembler "bmsk_s\\s+r0,r0,0" } } */ +/* { dg-final { scan-assembler "neg_s\\s+r0,r0" } } */ |