summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/rs6000/rs6000.md27
-rw-r--r--gcc/optabs.c2
-rw-r--r--gcc/optabs.h1
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/copysign1.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/copysign2.c12
7 files changed, 67 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3ec28c7a24f..054b745832a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-02-01 Richard Henderson <rth@redhat.com>
+
+ PR 19696
+ * optabs.c (expand_copysign_absneg): Export.
+ * optabs.h (expand_copysign_absneg): Declare.
+ * config/rs6000/rs6000.md (copysigntf3): New.
+
2005-02-01 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/19633
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 7ccdab8b5a8..c2dd678d767 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -8466,6 +8466,33 @@
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
}")
+
+(define_expand "copysigntf3"
+ [(match_operand:TF 0 "general_operand" "")
+ (match_operand:TF 1 "general_operand" "")
+ (match_operand:TF 2 "general_operand" "")]
+ "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+{
+ rtx target, op0, op1, temp;
+ bool op0_is_abs = false;
+
+ target = operands[0];
+ op0 = operands[1];
+ op1 = operands[2];
+
+ if (GET_CODE (op0) == CONST_DOUBLE)
+ {
+ if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
+ op0 = simplify_unary_operation (ABS, TFmode, op0, TFmode);
+ op0_is_abs = true;
+ }
+
+ temp = expand_copysign_absneg (TFmode, op0, op1, target, 127, op0_is_abs);
+ if (temp != target)
+ emit_move_insn (target, temp);
+ DONE;
+})
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
diff --git a/gcc/optabs.c b/gcc/optabs.c
index dd3232b499c..889f9156dd1 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2662,7 +2662,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
is that we have a split register file, and leaving op0 in fp registers,
and not playing with subregs so much, will help the register allocator. */
-static rtx
+rtx
expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
int bitpos, bool op0_is_abs)
{
diff --git a/gcc/optabs.h b/gcc/optabs.h
index a378a963c72..613831a8249 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -455,6 +455,7 @@ extern rtx expand_abs (enum machine_mode, rtx, rtx, int, int);
/* Expand the copysign operation. */
extern rtx expand_copysign (rtx, rtx, rtx);
+extern rtx expand_copysign_absneg (enum machine_mode, rtx, rtx, rtx, int, bool);
/* Generate an instruction with a given INSN_CODE with an output and
an input. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a6ff8329a1f..ace5f5f5ce1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-02-01 Richard Henderson <rth@redhat.com>
+
+ * gcc.c-torture/execute/ieee/copysign1.c: Special case sizeof
+ long double for ibm double-double format.
+ * gcc.c-torture/execute/ieee/copysign2.c: Likewise.
+
2005-02-01 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/19633
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/copysign1.c b/gcc/testsuite/gcc.c-torture/execute/ieee/copysign1.c
index 6f6a215ad48..fa4097a748d 100644
--- a/gcc/testsuite/gcc.c-torture/execute/ieee/copysign1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/copysign1.c
@@ -17,6 +17,19 @@
# endif
#endif
+/* Work around the fact that the sign of the second double in the IBM
+ double-double format is not strictly specified when it contains a zero.
+ For instance, -0.0L can be represented with either (-0.0, +0.0) or
+ (-0.0, -0.0). The former is what we'll get from the compiler when it
+ builds constants; the later is what we'll get from the negation operator
+ at runtime. */
+/* ??? This hack only works for big-endian, which is fortunately true for
+ all of AIX, Darwin, and Irix. */
+#if LDBL_MANT_DIG == 106
+# undef fpsizeofl
+# define fpsizeofl sizeof(double)
+#endif
+
#define TEST(TYPE, EXT) \
TYPE c##EXT (TYPE x, TYPE y) \
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/copysign2.c b/gcc/testsuite/gcc.c-torture/execute/ieee/copysign2.c
index a39d11574f2..fac7ab3a530 100644
--- a/gcc/testsuite/gcc.c-torture/execute/ieee/copysign2.c
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/copysign2.c
@@ -17,6 +17,18 @@
# endif
#endif
+/* Work around the fact that the sign of the second double in the IBM
+ double-double format is not strictly specified when it contains a zero.
+ For instance, -0.0L can be represented with either (-0.0, +0.0) or
+ (-0.0, -0.0). The former is what we'll get from the compiler when it
+ builds constants; the later is what we'll get from the negation operator
+ at runtime. */
+/* ??? This hack only works for big-endian, which is fortunately true for
+ all of AIX, Darwin, and Irix. */
+#if LDBL_MANT_DIG == 106
+# undef fpsizeofl
+# define fpsizeofl sizeof(double)
+#endif
#define TEST(TYPE, EXT) \