This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Expand sincos using optab, if possible


This patch uses the sincos optab to expand calls to sincos, if possible.
This improves fsincos handling on i686 where we only created that, if
sin (), cos () was used, not if sincos () was used.

Bootstrapped and tested on i686-pc-linux-gnu, ok for mainline?

Thanks,
Richard.

:ADDPATCH middle-end:


2006-01-11  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.

Index: builtins.c
===================================================================
*** builtins.c	(revision 109575)
--- builtins.c	(working copy)
*************** static void expand_errno_check (tree, rt
*** 95,100 ****
--- 95,101 ----
  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, rtx, rtx);
  static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
  static rtx expand_builtin_args_info (tree);
  static rtx expand_builtin_next_arg (void);
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2064,2070 ****
    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))
--- 2065,2070 ----
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2084,2092 ****
    /* 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) {
--- 2084,2089 ----
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2147,2155 ****
  
        if (target != 0)
  	{
- 	  if (errno_set)
- 	    expand_errno_check (exp, target);
- 
  	  /* Output the entire sequence.  */
  	  insns = get_insns ();
  	  end_sequence ();
--- 2144,2149 ----
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2168,2173 ****
--- 2162,2225 ----
    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; if convenient, the result should be placed in TARGET.
+    SUBTARGET may be used as the target for computing one of EXP's
+    operands.  */
+ 
+ static rtx
+ expand_builtin_sincos (tree exp, rtx target, rtx subtarget)
+ {
+   rtx op0, op1, op2, target1, target2, insns;
+   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, subtarget, 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);
+ 
+   start_sequence ();
+ 
+   /* 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);
+ 
+   /* Output the entire sequence.  */
+   insns = get_insns ();
+   end_sequence ();
+   emit_insn (insns);
+ 
+   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;
*************** expand_builtin (tree exp, rtx target, rt
*** 5649,5654 ****
--- 5701,5714 ----
  	return target;
        break;
  
+     CASE_FLT_FN (BUILT_IN_SINCOS):
+       if (! flag_unsafe_math_optimizations)
+ 	break;
+       target = expand_builtin_sincos (exp, target, subtarget);
+       if (target)
+ 	return target;
+       break;
+ 
      case BUILT_IN_APPLY_ARGS:
        return expand_builtin_apply_args ();
  
Index: testsuite/gcc.target/i386/387-9.c
===================================================================
*** testsuite/gcc.target/i386/387-9.c	(revision 0)
--- testsuite/gcc.target/i386/387-9.c	(revision 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" } } */



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]