* optabs.c (expand_copysign_absneg): Export.
* optabs.h (expand_copysign_absneg): Declare.
* config/rs6000/rs6000.md (copysigntf3): New.
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94559
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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;
+})
\f
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
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)
{
/* 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. */
+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
# 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) \
# 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) \