Commit fb0f04fe by James Greenhalgh Committed by James Greenhalgh

[AArch64] Implement copysign[ds]f3

gcc/

	* config/aarch64/aarch64.md (copysigndf3): New.
	(copysignsf3): Likewise.

gcc/testsuite/

	* gcc.target/aarch64/copysign_1.c: New.
	* gcc.target/aarch64/copysign_2.c: New.

From-SVN: r227849
parent bb6b3973
2015-09-17 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64.md (copysigndf3): New.
(copysignsf3): Likewise.
2015-09-17 David S. Miller <davem@davemloft.net>
* config/sparc/sparc-protos.h (sparc_secondary_memory_needed):
......@@ -4412,6 +4412,52 @@
[(set_attr "type" "f_minmax<s>")]
)
;; For copysign (x, y), we want to generate:
;;
;; 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")]
"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]));
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")]
"TARGET_FLOAT && TARGET_SIMD"
{
rtx mask = gen_reg_rtx (DImode);
/* Juggle modes to get us in to a vector mode for BSL. */
rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
rtx tmp = gen_reg_rtx (V2SFmode);
emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
DONE;
}
)
;; -------------------------------------------------------------------
;; Reload support
;; -------------------------------------------------------------------
......
2015-09-17 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.target/aarch64/copysign_1.c: New.
* gcc.target/aarch64/copysign_2.c: New.
2015-09-17 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/tree-ssa/loop-bound-2.c: New test.
......
/* { dg-do run } */
/* { dg-options "-O2 --save-temps" } */
double fabs (double);
double
check (double x, double y)
{
return __builtin_copysign (x, y);
}
double
check1 (double x)
{
return __builtin_copysign (x, 1.0);
}
double
check2 (double x)
{
return __builtin_copysign (1.0, x);
}
double
check3 (double x)
{
return -__builtin_copysign (x, 1.0);
}
double
check4 (double x, double y)
{
return x * __builtin_copysign (x, y);
}
double
check5 (double x, double y)
{
return __builtin_copysign (-x, -y);
}
int
main (int argc, char** argv)
{
double x = 2.0;
double y = -5.0;
double epsilon = 0.00001;
double expected = -2.0;
if (fabs (check (x, y) - expected) >= epsilon)
__builtin_abort ();
expected = 2.0;
if (fabs (check1 (x) - expected) >= epsilon)
__builtin_abort ();
expected = 1.0;
if (fabs (check2 (x) - expected) >= epsilon)
__builtin_abort ();
expected = -2.0;
if (fabs (check3 (x) - expected) >= epsilon)
__builtin_abort ();
expected = -4.0;
if (fabs (check4 (x, y) - expected) >= epsilon)
__builtin_abort ();
expected = 2.0;
if (fabs (check5 (x, y) - expected) >= epsilon)
__builtin_abort ();
}
/* { dg-final { scan-assembler-not "copysign\tw" } } */
/* { dg-do run } */
/* { dg-options "-O2 --save-temps" } */
float fabsf (float);
float
check (float x, float y)
{
return __builtin_copysignf (x, y);
}
float
check1 (float x)
{
return __builtin_copysignf (x, 1.0);
}
float
check2 (float x)
{
return __builtin_copysignf (1.0, x);
}
float
check3 (float x)
{
return -__builtin_copysignf (x, 1.0);
}
float
check4 (float x, float y)
{
return x * __builtin_copysignf (x, y);
}
float
check5 (float x, float y)
{
return __builtin_copysignf (-x, -y);
}
int
main (int argc, char** argv)
{
float x = 2.0f;
float y = -5.0f;
float epsilon = 0.00001f;
float expected = -2.0f;
if (fabsf (check (x, y) - expected) >= epsilon)
__builtin_abort ();
expected = 2.0f;
if (fabsf (check1 (x) - expected) >= epsilon)
__builtin_abort ();
expected = 1.0f;
if (fabsf (check2 (x) - expected) >= epsilon)
__builtin_abort ();
expected = -2.0f;
if (fabsf (check3 (x) - expected) >= epsilon)
__builtin_abort ();
expected = -4.0f;
if (fabsf (check4 (x, y) - expected) >= epsilon)
__builtin_abort ();
expected = 2.0f;
if (fabsf (check5 (x, y) - expected) >= epsilon)
__builtin_abort ();
}
/* { dg-final { scan-assembler-not "copysign\tw" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment