]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2006-12-13 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Dec 2006 10:17:36 +0000 (10:17 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Dec 2006 10:17:36 +0000 (10:17 +0000)
PR tree-optimization/17687
* builtins.def (BUILT_IN_CEXPI, BUILT_IN_CEXPIF, BUILT_IN_CEXPIL):
New builtins for imaginary argument cexp.
* builtin-types.def (BT_FN_COMPLEX_FLOAT_FLOAT,
BT_FN_COMPLEX_DOUBLE_DOUBLE, BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE):
New required builtin types.
* builtins.c (expand_builtin_cexpi): Declare.
(mathfn_built_in): Handle BUILT_IN_CEXPI.
(expand_builtin_cexpi): New static helper.
(expand_builtin): Call it.
(do_mpfr_sincos): Adjust for CEXPI evaluation.
(fold_builtin_sincos): New function to fold sincos to cepxi.

* gcc.dg/builtins-59.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119824 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtin-types.def
gcc/builtins.c
gcc/builtins.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-59.c [new file with mode: 0644]

index 6dc18a3bcb5115db1d3292837ff80e6654a48de8..1f4301dfd394861c014508516d82a6acb8368e30 100644 (file)
@@ -1,3 +1,18 @@
+2006-12-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/17687
+       * builtins.def (BUILT_IN_CEXPI, BUILT_IN_CEXPIF, BUILT_IN_CEXPIL):
+       New builtins for imaginary argument cexp.
+       * builtin-types.def (BT_FN_COMPLEX_FLOAT_FLOAT,
+       BT_FN_COMPLEX_DOUBLE_DOUBLE, BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE):
+       New required builtin types.
+       * builtins.c (expand_builtin_cexpi): Declare.
+       (mathfn_built_in): Handle BUILT_IN_CEXPI.
+       (expand_builtin_cexpi): New static helper.
+       (expand_builtin): Call it.
+       (do_mpfr_sincos): Adjust for CEXPI evaluation.
+       (fold_builtin_sincos): New function to fold sincos to cepxi.
+
 2006-12-13  Richard Guenther  <rguenther@suse.de>
 
        * ipa-reference.c (scan_for_static_refs): Also scan
index 5d42b2ef9aa866df1836c6eb9ae5f66364c48d3e..bac7480438c93020f0a499e40a8565c5c8011058 100644 (file)
@@ -159,6 +159,12 @@ DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_COMPLEX_DOUBLE,
                     BT_DOUBLE, BT_COMPLEX_DOUBLE)
 DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE,
                     BT_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_FLOAT,
+                    BT_COMPLEX_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_DOUBLE,
+                    BT_COMPLEX_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE,
+                    BT_COMPLEX_LONGDOUBLE, BT_LONGDOUBLE)
 DEF_FUNCTION_TYPE_1 (BT_FN_PTR_UINT, BT_PTR, BT_UINT)
 DEF_FUNCTION_TYPE_1 (BT_FN_PTR_SIZE, BT_PTR, BT_SIZE)
 DEF_FUNCTION_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT)
index a6f1402c456b3022a6437601a97c39f71902d796..78b34338eb68d9249a99a61bdf6d06ce36f52615 100644 (file)
@@ -94,6 +94,7 @@ 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_cexpi (tree, rtx, rtx);
 static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
 static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_args_info (tree);
@@ -1648,6 +1649,7 @@ mathfn_built_in (tree type, enum built_in_function fn)
       CASE_MATHFN (BUILT_IN_ATANH)
       CASE_MATHFN (BUILT_IN_CBRT)
       CASE_MATHFN (BUILT_IN_CEIL)
+      CASE_MATHFN (BUILT_IN_CEXPI)
       CASE_MATHFN (BUILT_IN_COPYSIGN)
       CASE_MATHFN (BUILT_IN_COS)
       CASE_MATHFN (BUILT_IN_COSH)
@@ -2215,6 +2217,78 @@ expand_builtin_sincos (tree exp)
   return const0_rtx;
 }
 
+/* Expand a call to the internal cexpi builtin to the sincos math function.
+   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_cexpi (tree exp, rtx target, rtx subtarget)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  enum machine_mode mode;
+  tree arg, type;
+  rtx op0, op1, op2;
+
+  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    return 0;
+
+  arg = TREE_VALUE (arglist);
+  type = TREE_TYPE (arg);
+  mode = TYPE_MODE (TREE_TYPE (arg));
+
+  /* Try expanding via a sincos optab, fall back to emitting a libcall
+     to sincos.  We are sure we have sincos either way because cexpi
+     is only generated from sincos.  */
+  if (sincos_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+    {
+      op1 = gen_reg_rtx (mode);
+      op2 = gen_reg_rtx (mode);
+
+      op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+
+      /* Compute into op1 and op2.  */
+      expand_twoval_unop (sincos_optab, op0, op2, op1, 0);
+    }
+  else
+    {
+      tree call, narglist, fn = NULL_TREE;
+      tree top1, top2;
+      rtx op1a, op2a;
+
+      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
+       fn = built_in_decls[BUILT_IN_SINCOSF];
+      else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
+       fn = built_in_decls[BUILT_IN_SINCOS];
+      else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
+       fn = built_in_decls[BUILT_IN_SINCOSL];
+      gcc_assert (fn);
+      op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
+      op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
+      op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
+      op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0));
+      top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a);
+      top2 = make_tree (build_pointer_type (TREE_TYPE (arg)), op2a);
+
+      narglist = build_tree_list (NULL_TREE, top2);
+      narglist = tree_cons (NULL_TREE, top1, narglist);
+      narglist = tree_cons (NULL_TREE, arg, narglist);
+
+      /* Make sure not to fold the sincos call again.  */
+      call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+      expand_normal (build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+                            call, arglist, NULL_TREE));
+    }
+
+  /* Now build the proper return type.  */
+  return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type),
+                             make_tree (TREE_TYPE (arg), op2),
+                             make_tree (TREE_TYPE (arg), op1)),
+                     target, VOIDmode, 0);
+}
+
 /* Expand a call to one of the builtin rounding functions gcc defines
    as an extension (lfloor and lceil).  As these are gcc extensions we
    do not need to worry about setting errno to EDOM.
@@ -5772,6 +5846,11 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
+    CASE_FLT_FN (BUILT_IN_CEXPI):
+      target = expand_builtin_cexpi (exp, target, subtarget);
+      gcc_assert (target);
+      return target;
+
     CASE_FLT_FN (BUILT_IN_SIN):
     CASE_FLT_FN (BUILT_IN_COS):
       if (! flag_unsafe_math_optimizations)
@@ -7249,6 +7328,45 @@ fold_builtin_tan (tree arglist, tree type)
   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 type, arg0, arg1, arg2;
+  tree res, fn, call;
+
+  if (!validate_arglist (arglist, REAL_TYPE, POINTER_TYPE,
+                        POINTER_TYPE, VOID_TYPE))
+    return NULL_TREE;
+
+  arg0 = TREE_VALUE (arglist);
+  type = TREE_TYPE (arg0);
+  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+  /* Calculate the result when the argument is a constant.  */
+  if ((res = do_mpfr_sincos (arg0, arg1, arg2)))
+    return res;
+
+  /* Canonicalize sincos to cexpi.  */
+  fn = mathfn_built_in (type, BUILT_IN_CEXPI);
+  if (!fn)
+    return NULL_TREE;
+
+  call = build_function_call_expr (fn, build_tree_list (NULL_TREE, arg0));
+  call = builtin_save_expr (call);
+
+  return build2 (COMPOUND_EXPR, type,
+                build2 (MODIFY_EXPR, void_type_node,
+                        build_fold_indirect_ref (arg1),
+                        build1 (IMAGPART_EXPR, type, call)),
+                build2 (MODIFY_EXPR, void_type_node,
+                        build_fold_indirect_ref (arg2),
+                        build1 (REALPART_EXPR, type, call)));
+}
+
 /* Fold function call to builtin trunc, truncf or truncl.  Return
    NULL_TREE if no simplification can be made.  */
 
@@ -9192,10 +9310,11 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
       return fold_builtin_tan (arglist, type);
 
     CASE_FLT_FN (BUILT_IN_SINCOS):
-      if (validate_arglist (arglist, REAL_TYPE, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
-       return do_mpfr_sincos (TREE_VALUE (arglist), TREE_VALUE (TREE_CHAIN (arglist)),
-                              TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
-    break;
+      return fold_builtin_sincos (arglist);
+
+    CASE_FLT_FN (BUILT_IN_CEXPI):
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+       return do_mpfr_sincos (TREE_VALUE (arglist), NULL_TREE, NULL_TREE);
 
     CASE_FLT_FN (BUILT_IN_SINH):
       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
@@ -11667,6 +11786,8 @@ do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type,
 
 /* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set
    the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values.
+   If ARG_SINP and ARG_COSP are NULL then the result is returned
+   as a complex value.
    The type is taken from the type of ARG and is used for setting the
    precision of the calculation and results.  */
 
@@ -11698,6 +11819,11 @@ do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp)
          mpfr_clears (m, ms, mc, NULL);
          if (result_s && result_c)
            {
+             /* If we are to return in a complex value do so.  */
+             if (!arg_sinp && !arg_cosp)
+               return build_complex (build_complex_type (type),
+                                     result_c, result_s);
+
              /* Dereference the sin/cos pointer arguments.  */
              arg_sinp = build_fold_indirect_ref (arg_sinp);
              arg_cosp = build_fold_indirect_ref (arg_cosp);
index 802e20c9f10bb46e2349de4c7dea4f6e94f81363..ca402a35ec7cd01863ebaae5a33466e778381e60 100644 (file)
@@ -452,6 +452,9 @@ DEF_C99_BUILTIN        (BUILT_IN_CCOSL, "ccosl", BT_FN_COMPLEX_LONGDOUBLE_COMPLE
 DEF_C99_BUILTIN        (BUILT_IN_CEXP, "cexp", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_CEXPF, "cexpf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_CEXPL, "cexpl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_CEXPI, "cexpi", BT_FN_COMPLEX_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_CEXPIF, "cexpif", BT_FN_COMPLEX_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN        (BUILT_IN_CEXPIL, "cexpil", BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_CIMAG, "cimag", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_CIMAGF, "cimagf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_CIMAGL, "cimagl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
index 6f8978106decc168ff3eef17e7cadefc439b8b45..08dc8ef891b459604fd3145dce7c42c003230f91 100644 (file)
@@ -1,3 +1,8 @@
+2006-12-13  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/17687
+       * gcc.dg/builtins-59.c: New testcase.
+
 2006-12-13  Ben Elliston  <bje@au.ibm.com>
 
        * gcc.target/spu/Wmain.c: New test.
diff --git a/gcc/testsuite/gcc.dg/builtins-59.c b/gcc/testsuite/gcc.dg/builtins-59.c
new file mode 100644 (file)
index 0000000..a7da712
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+double test (double x)
+{
+  double s, c;
+  __builtin_sincos (x, &s, &c);
+  return s + c;
+}
+
+/* { dg-final { scan-tree-dump "__builtin_cexpi" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "sincos" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */