[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.
	(copysign<GPF:mode>3): New expand pattern.
	(copysign<GPF:mode>3_insn): New insn pattern.

From-SVN: r267019
This commit is contained in:
Richard Earnshaw 2018-12-11 11:26:15 +00:00 committed by Richard Earnshaw
parent c47fb5d9da
commit 315fdae8f9
3 changed files with 44 additions and 35 deletions

View 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.

View file

@ -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.
;; 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 "copysigndf3"
[(match_operand:DF 0 "register_operand")
(match_operand:DF 1 "register_operand")
(match_operand:DF 2 "register_operand")]
(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

View file

@ -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")