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]

PR/17687 fold sincos at the tree level


This patch was submitted in September and queued in the 4.1 metabug.

Boostrapped/tested C/C++ only on powerpc-darwin and i686-pc-linux-gnu; ok for mainline?

Paolo
gcc:
2005-02-17  Paolo Bonzini  <bonzini@gnu.org>

	PR tree-optimization/17687
	* builtins.c (fold_builtin_sincos): New.
	(fold_builtin): Call it.

gcc/testsuite:
2005-02-17  Paolo Bonzini  <bonzini@gnu.org>

	PR tree-optimization/17687
	* gcc.dg/builtins-53.c: New.
	* gcc.dg/i386-387-9.c: New.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.435
diff -p -u -p -r1.435 builtins.c
--- builtins.c	13 Mar 2005 15:53:13 -0000	1.435
+++ builtins.c	15 Mar 2005 06:56:45 -0000
@@ -155,6 +155,7 @@ static tree fold_builtin_pow (tree, tree
 static tree fold_builtin_powi (tree, tree, tree);
 static tree fold_builtin_sin (tree);
 static tree fold_builtin_cos (tree, tree, tree);
+static tree fold_builtin_sincos (tree, tree);
 static tree fold_builtin_tan (tree);
 static tree fold_builtin_atan (tree, tree);
 static tree fold_builtin_trunc (tree);
@@ -6441,6 +6442,83 @@ fold_builtin_cos (tree arglist, tree typ
   return NULL_TREE;
 }
 
+/* Fold function call to builtin sincos, sincosf, or sincosl.  Return
+   NULL_TREE if no simplification can be made.  */
+static tree
+fold_builtin_sincos (tree arglist, tree fndecl)
+{
+  tree arg, arg1, arg2, sin_fn, cos_fn, sin_modify, cos_modify;
+  tree sin_fndecl, cos_fndecl;
+  enum machine_mode mode;
+  bool negate_sin;
+
+  if (!validate_arglist (arglist,
+			 REAL_TYPE, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
+    return NULL_TREE;
+
+  /* Check if sincos insn is available, otherwise fallback
+     to usual builtin.  */
+  arg = TREE_VALUE (arglist);
+  mode = TYPE_MODE (TREE_TYPE (arg));
+  if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+    return NULL_TREE;
+
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_SINCOS:
+      sin_fndecl = implicit_built_in_decls[BUILT_IN_SIN];
+      cos_fndecl = implicit_built_in_decls[BUILT_IN_COS];
+      break;
+
+    case BUILT_IN_SINCOSF:
+      sin_fndecl = implicit_built_in_decls[BUILT_IN_SINF];
+      cos_fndecl = implicit_built_in_decls[BUILT_IN_COSF];
+      break;
+
+    case BUILT_IN_SINCOSL:
+      sin_fndecl = implicit_built_in_decls[BUILT_IN_SINL];
+      cos_fndecl = implicit_built_in_decls[BUILT_IN_COSL];
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Avoid that cos(-x) is optimized into cos (x), because then sincos_optab
+     could not be used anymore.  */
+  if (TREE_CODE (arg) == NEGATE_EXPR)
+    {
+      arg = TREE_OPERAND (arg, 0);
+      negate_sin = true;
+    }
+  else
+    negate_sin = false;
+
+  arg = save_expr (arg);
+  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  sin_fn = build_function_call_expr (sin_fndecl,
+				     build_tree_list (NULL_TREE, arg));
+  if (negate_sin)
+    sin_fn = build1 (NEGATE_EXPR, TREE_TYPE (sin_fn), sin_fn);
+
+  sin_modify =
+    build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (arg1)),
+	    build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (arg1)), arg1),
+	    fold_convert (TREE_TYPE (TREE_TYPE (arg1)), sin_fn));
+
+  arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+  cos_fn = build_function_call_expr (cos_fndecl,
+				     build_tree_list (NULL_TREE, arg));
+  cos_modify =
+    build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (arg2)),
+	    build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (arg2)), arg2),
+	    fold_convert (TREE_TYPE (TREE_TYPE (arg2)), cos_fn));
+
+  return build1 (NOP_EXPR, void_type_node,
+		 build2 (COMPOUND_EXPR, TREE_TYPE (sin_modify),
+			 cos_modify, sin_modify));
+}
+
 /* Fold function call to builtin tan, tanf, or tanl.  Return
    NULL_TREE if no simplification can be made.  */
 static tree
@@ -8106,6 +8184,11 @@ fold_builtin_1 (tree exp, bool ignore)
     case BUILT_IN_COSL:
       return fold_builtin_cos (arglist, type, fndecl);
 
+    case BUILT_IN_SINCOS:
+    case BUILT_IN_SINCOSF:
+    case BUILT_IN_SINCOSL:
+      return fold_builtin_sincos (arglist, fndecl);
+
     case BUILT_IN_EXP:
     case BUILT_IN_EXPF:
     case BUILT_IN_EXPL:
Index: testsuite/gcc.dg/builtins-53.c
===================================================================
RCS file: testsuite/gcc.dg/builtins-53.c
diff -N testsuite/gcc.dg/builtins-53.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/builtins-53.c	15 Mar 2005 06:56:45 -0000
@@ -0,0 +1,43 @@
+/* Copyright (C) 2005 Free Software Foundation.
+
+   Check that the sincos, sincosf, sincosl
+   built-in functions compile.
+
+   Written by Paolo Bonzini, 17th Mar 2005.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+float sf, cf;
+double sd, cd;
+long double sl, cl;
+
+void f1 (float x)
+{
+  __builtin_sincosf (x, &sf, &cf);
+};
+
+void f2 (double x)
+{
+  __builtin_sincos (x, &sd, &cd);
+};
+
+void f3 (long double x)
+{
+  __builtin_sincosl (x, &sl, &cl);
+};
+
+void g1 (float x)
+{
+  __builtin_sincosf (-x, &sf, &cf);
+};
+
+void g2 (double x)
+{
+  __builtin_sincos (-x, &sd, &cd);
+};
+
+void g3 (long double x)
+{
+  __builtin_sincosl (-x, &sl, &cl);
+};
Index: testsuite/gcc.dg/i386-387-9.c
===================================================================
RCS file: testsuite/gcc.dg/i386-387-9.c
diff -N testsuite/gcc.dg/i386-387-9.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/i386-387-9.c	15 Mar 2005 06:56:45 -0000
@@ -0,0 +1,39 @@
+/* Verify that 387 fsincos instruction is generated from __builtin_sincos.  */
+/* { dg-do compile { target "i?86-*-*" } } */
+/* { dg-options "-O2 -ffast-math -march=i686" } */
+/* { dg-final { scan-assembler "fsincos" } } */
+/* { dg-final { scan-assembler-not "call" } } */
+
+float sf, cf;
+double sd, cd;
+long double sl, cl;
+
+void f1 (float x)
+{
+  __builtin_sincosf (x, &sf, &cf);
+};
+
+void f2 (double x)
+{
+  __builtin_sincos (x, &sd, &cd);
+};
+
+void f3 (long double x)
+{
+  __builtin_sincosl (x, &sl, &cl);
+};
+
+void g1 (float x)
+{
+  __builtin_sincosf (-x, &sf, &cf);
+};
+
+void g2 (double x)
+{
+  __builtin_sincos (-x, &sd, &cd);
+};
+
+void g3 (long double x)
+{
+  __builtin_sincosl (-x, &sl, &cl);
+};

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