this patch optimize copysign/copysignf for -mfloat-abi=soft on arm when BFI
instruction is available.
before this patch, we do copysign (a, b) by three steps:
* fetch the sign bit of b to A
* fetch all non-sign bits of a to B
* or A and B
while these three steps could be finished by one single BFI instruction.
for example, for the following simple testcase:
1.c:
float
fcopysign (float a, float b)
{
return __builtin_copysignf (a, b);
}
before this patch
=================
fcopysign:
and r1, r1, #-2147483648
bic r0, r0, #-2147483648
orr r0, r0, r1
bx lr
after this patch
===============
fcopysign:
bfi r1, r0, #0, #31
mov r0, r1
bx lr
at least one instruction could be saved.
test done
===
no regression on the full toolchain test on arm-none-eabi.
ok to install?
thanks.
2014-07-29 Jiong Wang <[email protected]>
2014-07-29 Renlin Li <[email protected]>
gcc/
* config/arm/iterators.md (SFDF): New mode iterator.
(fp_high): New mode attribute.
* config/arm/unspecs.md (UNSPEC_BFM): New UNSPEC.
* config/arm/arm.md (copysign<mode>3): New define_insn for copysign.
gcc/testsuite/
* gcc.target/arm/copysign.c: New case for copysign/copysignf soft-float opt.
commit 3b29b02cb4b525302179dde9e32528354040a2cb
Author: Jiong Wang <[email protected]>
Date: Tue Jul 15 17:09:21 2014 +0100
[ARM] Optimize copysign/copysignf.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6ae240e..4244043 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11106,6 +11106,19 @@
[(set_attr "predicable" "yes")]
)
+(define_insn "copysign<mode>3"
+ [(set (match_operand:SFDF 0 "register_operand" "=r")
+ (unspec:SFDF [(match_operand:SFDF 1 "register_operand" "r")
+ (match_operand:SFDF 2 "register_operand" "0")]
+ UNSPEC_BFM))]
+ "TARGET_SOFT_FLOAT && arm_arch_thumb2"
+ "bfi\t%<fp_high>0, %<fp_high>1, #0, #31"
+ [(set_attr "length" "4")
+ (set_attr "predicable" "yes")
+ (set_attr "predicable_short_it" "no")
+ (set_attr "type" "bfm")]
+)
+
;; Vector bits common to IWMMXT and Neon
(include "vec-common.md")
;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 6fe6eef..d9de55a 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -42,6 +42,9 @@
;; A list of the 32bit and 64bit integer modes
(define_mode_iterator SIDI [SI DI])
+;; A list of the 32bit and 64bit float modes
+(define_mode_iterator SFDF [SF DF])
+
;; A list of modes which the VFP unit can handle
(define_mode_iterator SDF [(SF "TARGET_VFP") (DF "TARGET_VFP_DOUBLE")])
@@ -497,6 +500,8 @@
(DI "") (V2DI "_q")
(DF "") (V2DF "_q")])
+(define_mode_attr fp_high [(SF "") (DF "R")])
+
;;----------------------------------------------------------------------------
;; Code attributes
;;----------------------------------------------------------------------------
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 147cb80..94dc578 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -62,6 +62,7 @@
; a given symbolic address.
UNSPEC_THUMB1_CASESI ; A Thumb1 compressed dispatch-table call.
UNSPEC_RBIT ; rbit operation.
+ UNSPEC_BFM ; bfm operation.
UNSPEC_SYMBOL_OFFSET ; The offset of the start of the symbol from
; another symbolic address.
UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
diff --git a/gcc/testsuite/gcc.target/arm/copysign.c b/gcc/testsuite/gcc.target/arm/copysign.c
new file mode 100644
index 0000000..7ec2068
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/copysign.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-skip-if "skip override" { *-*-* } { "-mfloat-abi=softfp" "-mfloat-abi=hard" } { "" } } */
+/* { dg-options "-O2 -march=armv7-a -mfloat-abi=soft" } */
+
+float
+fcopysign (float a, float b)
+{
+ return __builtin_copysignf (a, b);
+}
+
+double
+dcopysign (double a, double b)
+{
+ return __builtin_copysign (a, b);
+}
+
+/* { dg-final { scan-assembler-times "bfi" 2 } } */
+/* { dg-final { scan-assembler-not "orr" } } */