[aarch64] PR target/87369 Prefer bsl/bit/bif for copysign
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 11 Dec 2018 11:26:15 +0000 (11:26 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Tue, 11 Dec 2018 11:26:15 +0000 (11:26 +0000)
The copysign operations will almost always be performed on values in
floating-point registers.  As such, we do not want the compiler to
simplify the operations into code sequences that can only be done
using the general-purpose register set.  Unfortunately, this is what
is currently happening.

Fortunately, it seems quite unlikely that copysign() will be
subsequently followed by other logical operations on the values
involved, so I think it is acceptable to use an unspec here.  This
allows us to preserve the operation in a form that allows the register
allocator to make the right choice later on, without limitation on the
final form of the operation (well, if we do end up using the gp
register bank, we get a dead constant load that we cannot easily
eliminate at a late stage).

PR target/37369
* config/aarch64/iterators.md (sizem1): Add sizes for SFmode and DFmode.
(Vbtype): Add SFmode mapping.
* config/aarch64/aarch64.md (copysigndf3, copysignsf3): Delete.
(copysign<GPF:mode>3): New expand pattern.
(copysign<GPF:mode>3_insn): New insn pattern.

From-SVN: r267019

gcc/ChangeLog
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md

index 5c95b16f364a1c72a84e3779cbc837809cab8084..9981ddd835943ef2919fe4ffadd9c17b44644548 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-11  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/37369
+       * config/aarch64/iterators.md (sizem1): Add sizes for SFmode and DFmode.
+       (Vbtype): Add SFmode mapping.
+       * config/aarch64/aarch64.md (copysigndf3, copysignsf3): Delete.
+       (copysign<GPF:mode>3): New expand pattern.
+       (copysign<GPF:mode>3_insn): New insn pattern.
+
 2018-12-11  Richard Biener  <rguenther@suse.de>
 
        * ccmp.c (ccmp_candidate_p): Use GIMPLE API properly.
index 82af4d47f78c65880f5eec78add5a69110db7711..6657316c5dd9881bc4bafac418372a68b59043db 100644 (file)
     UNSPEC_FADDA
     UNSPEC_REV_SUBREG
     UNSPEC_SPECULATION_TRACKER
+    UNSPEC_COPYSIGN
 ])
 
 (define_c_enum "unspecv" [
 ;;   LDR d2, #(1 << 63)
 ;;   BSL v2.8b, [y], [x]
 ;;
-;; or another, equivalent, sequence using one of BSL/BIT/BIF.
-;; aarch64_simd_bsldf will select the best suited of these instructions
-;; to generate based on register allocation, and knows how to partially
-;; constant fold based on the values of X and Y, so expand through that.
-
-(define_expand "copysigndf3"
-  [(match_operand:DF 0 "register_operand")
-   (match_operand:DF 1 "register_operand")
-   (match_operand:DF 2 "register_operand")]
+;; or another, equivalent, sequence using one of BSL/BIT/BIF.  Because
+;; we expect these operations to nearly always operate on
+;; floating-point values, we do not want the operation to be
+;; simplified into a bit-field insert operation that operates on the
+;; integer side, since typically that would involve three inter-bank
+;; register copies.  As we do not expect copysign to be followed by
+;; other logical operations on the result, it seems preferable to keep
+;; this as an unspec operation, rather than exposing the underlying
+;; logic to the compiler.
+
+(define_expand "copysign<GPF:mode>3"
+  [(match_operand:GPF 0 "register_operand")
+   (match_operand:GPF 1 "register_operand")
+   (match_operand:GPF 2 "register_operand")]
   "TARGET_FLOAT && TARGET_SIMD"
 {
-  rtx mask = gen_reg_rtx (DImode);
-  emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
-  emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
-                                    operands[2], operands[1]));
+  rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
+  emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
+                                   << (GET_MODE_BITSIZE (<MODE>mode) - 1)));
+  emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2],
+                                      bitmask));
   DONE;
 }
 )
 
-;; As above, but we must first get to a 64-bit value if we wish to use
-;; aarch64_simd_bslv2sf.
-
-(define_expand "copysignsf3"
-  [(match_operand:SF 0 "register_operand")
-   (match_operand:SF 1 "register_operand")
-   (match_operand:SF 2 "register_operand")]
+(define_insn "copysign<GPF:mode>3_insn"
+  [(set (match_operand:GPF 0 "register_operand" "=w,w,w,r")
+       (unspec:GPF [(match_operand:GPF 1 "register_operand" "w,0,w,r")
+                    (match_operand:GPF 2 "register_operand" "w,w,0,0")
+                    (match_operand:<V_INT_EQUIV> 3 "register_operand" "0,w,w,X")]
+        UNSPEC_COPYSIGN))]
   "TARGET_FLOAT && TARGET_SIMD"
-{
-  rtx v_bitmask = gen_reg_rtx (V2SImode);
-
-  /* Juggle modes to get us in to a vector mode for BSL.  */
-  rtx op1 = lowpart_subreg (DImode, operands[1], SFmode);
-  rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
-  rtx tmp = gen_reg_rtx (V2SFmode);
-  emit_move_insn (v_bitmask,
-                 aarch64_simd_gen_const_vector_dup (V2SImode,
-                                                    HOST_WIDE_INT_M1U << 31));
-  emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
-  emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
-  DONE;
-}
+  "@
+   bsl\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
+   bit\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
+   bif\\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype>
+   bfxil\\t%<w1>0, %<w1>1, #0, <sizem1>"
+  [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
 )
 
+
 ;; For xorsign (x, y), we want to generate:
 ;;
 ;; LDR   d2, #1<<63
index a80755734d67e90d25b4570d36de2f82d38addc6..ae75666167dd3c7787a2e2abb4136e85bef89420 100644 (file)
 (define_mode_attr sizen [(QI "8") (HI "16") (SI "32") (DI "64")])
 
 ;; Give the ordinal of the MSB in the mode
-(define_mode_attr sizem1 [(QI "#7") (HI "#15") (SI "#31") (DI "#63")])
+(define_mode_attr sizem1 [(QI "#7") (HI "#15") (SI "#31") (DI "#63")
+                         (HF "#15") (SF "#31") (DF "#63")])
 
 ;; Attribute to describe constants acceptable in logical operations
 (define_mode_attr lconst [(SI "K") (DI "L")])
                          (V8HF "16b") (V2SF  "8b")
                          (V4SF "16b") (V2DF  "16b")
                          (DI   "8b")  (DF    "8b")
-                         (SI   "8b")])
+                         (SI   "8b")  (SF    "8b")])
 
 ;; Define element mode for each vector mode.
 (define_mode_attr VEL [(V8QI  "QI") (V16QI "QI") (VNx16QI "QI")