aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2023-10-30 16:21:28 +0000
committerRoger Sayle <roger@nextmovesoftware.com>2023-10-30 16:21:28 +0000
commita3da9adeb457d4f01c4e695a9621f90c2e2a5e68 (patch)
tree12eb744747aca917c307b4871a1acc96f589444e
parent31cc9824d1cd5e0f7fa145d0831a923479333cd6 (diff)
downloadgcc-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.md14
-rw-r--r--gcc/testsuite/gcc.target/arc/pr101955.c10
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" } } */