This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR/17687 fold sincos at the tree level
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 16 Mar 2005 18:00:07 +0100
- Subject: 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);
+};