aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2006-01-13 11:31:49 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2006-01-13 11:31:49 +0000
commit403e54f013d0186db61adbc5cfee6ed08f35bfe6 (patch)
treeb8b96c69d5797b33eed925faa0af9382e3fc6fb3
parent90922b2d107a5f1c32b5c34f3b36aefe02c33a01 (diff)
downloadgcc-403e54f013d0186db61adbc5cfee6ed08f35bfe6.zip
gcc-403e54f013d0186db61adbc5cfee6ed08f35bfe6.tar.gz
gcc-403e54f013d0186db61adbc5cfee6ed08f35bfe6.tar.bz2
builtins.c (expand_builtin_sincos): New function.
2006-01-13 Richard Guenther <rguenther@suse.de> * builtins.c (expand_builtin_sincos): New function. (expand_builtin_mathfn_3): Remove dead code, sin and cos do not set errno. (expand_builtin): Expand sincos using expand_builtin_sincos. * gcc.target/i386/387-9.c: New testcase. From-SVN: r109664
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/builtins.c65
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/387-9.c36
4 files changed, 105 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4da37fd..2951055 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2006-01-13 Richard Guenther <rguenther@suse.de>
+
+ * builtins.c (expand_builtin_sincos): New function.
+ (expand_builtin_mathfn_3): Remove dead code, sin and cos
+ do not set errno.
+ (expand_builtin): Expand sincos using expand_builtin_sincos.
+
2006-01-12 DJ Delorie <dj@redhat.com>
* config/m32c/shift.md: Rewrite: Allow arbitrary operands for
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 01d16dd..657f38b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -95,6 +95,7 @@ static void expand_errno_check (tree, rtx);
static rtx expand_builtin_mathfn (tree, rtx, rtx);
static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
+static rtx expand_builtin_sincos (tree);
static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
static rtx expand_builtin_args_info (tree);
static rtx expand_builtin_next_arg (void);
@@ -2064,7 +2065,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode mode;
- bool errno_set = false;
tree arg, narg;
if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -2084,9 +2084,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
/* Make a suitable register to place result in. */
mode = TYPE_MODE (TREE_TYPE (exp));
- if (! flag_errno_math || ! HONOR_NANS (mode))
- errno_set = false;
-
/* Check if sincos insn is available, otherwise fallback
to sin or cos insn. */
if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
@@ -2147,9 +2144,6 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
if (target != 0)
{
- if (errno_set)
- expand_errno_check (exp, target);
-
/* Output the entire sequence. */
insns = get_insns ();
end_sequence ();
@@ -2168,6 +2162,55 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
return target;
}
+/* Expand a call to the builtin sincos math function.
+ Return 0 if a normal call should be emitted rather than expanding the
+ function in-line. EXP is the expression that is a call to the builtin
+ function. */
+
+static rtx
+expand_builtin_sincos (tree exp)
+{
+ rtx op0, op1, op2, target1, target2;
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum machine_mode mode;
+ tree arg, sinp, cosp;
+ int result;
+
+ if (!validate_arglist (arglist, REAL_TYPE,
+ POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+ return 0;
+
+ arg = TREE_VALUE (arglist);
+ sinp = TREE_VALUE (TREE_CHAIN (arglist));
+ cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+ /* Make a suitable register to place result in. */
+ mode = TYPE_MODE (TREE_TYPE (arg));
+
+ /* Check if sincos insn is available, otherwise emit the call. */
+ if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+ return NULL_RTX;
+
+ target1 = gen_reg_rtx (mode);
+ target2 = gen_reg_rtx (mode);
+
+ op0 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+ op1 = expand_expr (build_fold_indirect_ref (sinp), NULL_RTX, VOIDmode, 0);
+ op2 = expand_expr (build_fold_indirect_ref (cosp), NULL_RTX, VOIDmode, 0);
+
+ /* Compute into target1 and target2.
+ Set TARGET to wherever the result comes back. */
+ result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
+ gcc_assert (result);
+
+ /* Move target1 and target2 to the memory locations indicated
+ by op1 and op2. */
+ emit_move_insn (op1, target1);
+ emit_move_insn (op2, target2);
+
+ return const0_rtx;
+}
+
/* Expand a call to one of the builtin rounding functions (lfloor).
If expanding via optab fails, lower expression to (int)(floor(x)).
EXP is the expression that is a call to the builtin function;
@@ -5649,6 +5692,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target;
break;
+ CASE_FLT_FN (BUILT_IN_SINCOS):
+ if (! flag_unsafe_math_optimizations)
+ break;
+ target = expand_builtin_sincos (exp);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_APPLY_ARGS:
return expand_builtin_apply_args ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1df5757..e1cbca6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2006-01-13 Richard Guenther <rguenther@suse.de>
+
+ * gcc.target/i386/387-9.c: New testcase.
+
2006-01-12 Nathan Sidwell <nathan@codesourcery.com>
PR c++/24824
diff --git a/gcc/testsuite/gcc.target/i386/387-9.c b/gcc/testsuite/gcc.target/i386/387-9.c
new file mode 100644
index 0000000..f04faa5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/387-9.c
@@ -0,0 +1,36 @@
+/* Verify that 387 fsincos instruction is generated. */
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O -funsafe-math-optimizations -march=i686" } */
+
+extern double sin (double);
+extern double cos (double);
+extern void sincos (double, double *, double *);
+
+double f1(double x)
+{
+ double s, c;
+ sincos (x, &s, &c);
+ return s + c;
+}
+
+double f2(double x)
+{
+ double s, c, tmp;
+ sincos (x, &s, &tmp);
+ c = cos (x);
+ return s + c;
+}
+
+double f3(double x)
+{
+ double s, c, tmp;
+ sincos (x, &tmp, &c);
+ s = sin (x);
+ return s + c;
+}
+
+/* { dg-final { scan-assembler "fsincos" } } */
+/* { dg-final { scan-assembler-not "fsin " } } */
+/* { dg-final { scan-assembler-not "fcos" } } */
+/* { dg-final { scan-assembler-not "call" } } */