From: Richard Earnshaw Date: Tue, 11 Dec 2018 11:26:15 +0000 (+0000) Subject: [aarch64] PR target/87369 Prefer bsl/bit/bif for copysign X-Git-Tag: upstream/12.2.0~27411 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=315fdae8f965045f86e966953f3c010a61072729;p=platform%2Fupstream%2Fgcc.git [aarch64] PR target/87369 Prefer bsl/bit/bif for copysign 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. (copysign3): New expand pattern. (copysign3_insn): New insn pattern. From-SVN: r267019 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5c95b16..9981ddd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-12-11 Richard Earnshaw + + 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. + (copysign3): New expand pattern. + (copysign3_insn): New insn pattern. + 2018-12-11 Richard Biener * ccmp.c (ccmp_candidate_p): Use GIMPLE API properly. diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 82af4d4..6657316 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -222,6 +222,7 @@ UNSPEC_FADDA UNSPEC_REV_SUBREG UNSPEC_SPECULATION_TRACKER + UNSPEC_COPYSIGN ]) (define_c_enum "unspecv" [ @@ -5987,49 +5988,47 @@ ;; 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 "copysign3" + [(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 (mode); + emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U + << (GET_MODE_BITSIZE (mode) - 1))); + emit_insn (gen_copysign3_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 "copysign3_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: 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., %2., %1. + bit\\t%0., %2., %3. + bif\\t%0., %1., %3. + bfxil\\t%0, %1, #0, " + [(set_attr "type" "neon_bsl,neon_bsl,neon_bsl,bfm")] ) + ;; For xorsign (x, y), we want to generate: ;; ;; LDR d2, #1<<63 diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index a807557..ae75666 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -601,7 +601,8 @@ (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")]) @@ -687,7 +688,7 @@ (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")