diff options
author | Richard Guenther <rguenther@suse.de> | 2006-01-13 11:31:49 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2006-01-13 11:31:49 +0000 |
commit | 403e54f013d0186db61adbc5cfee6ed08f35bfe6 (patch) | |
tree | b8b96c69d5797b33eed925faa0af9382e3fc6fb3 | |
parent | 90922b2d107a5f1c32b5c34f3b36aefe02c33a01 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/builtins.c | 65 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/387-9.c | 36 |
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" } } */ |