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  <jiong.w...@arm.com>
2014-07-29  Renlin Li  <renlin...@arm.com>

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 <jiong.w...@arm.com>
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" } } */

Reply via email to