aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJames Greenhalgh <james.greenhalgh@arm.com>2015-09-17 08:23:05 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2015-09-17 08:23:05 +0000
commitfb0f04feaa6710087d04a5214394bd468d983a6b (patch)
treeb83481dc814025c58c58a64ff47444650c086743 /gcc
parentbb6b3973cc5738eab821d4fd8a61d14266d8a503 (diff)
downloadgcc-fb0f04feaa6710087d04a5214394bd468d983a6b.zip
gcc-fb0f04feaa6710087d04a5214394bd468d983a6b.tar.gz
gcc-fb0f04feaa6710087d04a5214394bd468d983a6b.tar.bz2
[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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/aarch64/aarch64.md46
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/aarch64/copysign_1.c81
-rw-r--r--gcc/testsuite/gcc.target/aarch64/copysign_2.c81
5 files changed, 218 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 42faf2e..dcc6f2f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+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):
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 88ba72e..925c6b1 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -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
;; -------------------------------------------------------------------
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bea9258..ab7f1cc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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.
diff --git a/gcc/testsuite/gcc.target/aarch64/copysign_1.c b/gcc/testsuite/gcc.target/aarch64/copysign_1.c
new file mode 100644
index 0000000..27fb9ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/copysign_1.c
@@ -0,0 +1,81 @@
+/* { 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" } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/copysign_2.c b/gcc/testsuite/gcc.target/aarch64/copysign_2.c
new file mode 100644
index 0000000..6eaa704
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/copysign_2.c
@@ -0,0 +1,81 @@
+/* { 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" } } */
+