Commit c128599a by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (do_mpc_arg1, [...]): New.

	* builtins.c (do_mpc_arg1, fold_builtin_ccos): New.
	(fold_builtin_cexp): Ensure we get a complex REAL_TYPE.
	Evaluate constant arguments.
	(fold_builtin_carg): Ensure we get a complex REAL_TYPE.
	(fold_builtin_1): Likewise, also evaluate constant arguments.
	Remove superfluous break.
	(do_mpc_ckconv): New.
	* real.h: Include mpc.h.
	* toplev.c (print_version): Output MPC version info if available.

From-SVN: r147591
parent d33e4b70
2009-05-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (do_mpc_arg1, fold_builtin_ccos): New.
(fold_builtin_cexp): Ensure we get a complex REAL_TYPE.
Evaluate constant arguments.
(fold_builtin_carg): Ensure we get a complex REAL_TYPE.
(fold_builtin_1): Likewise, also evaluate constant arguments.
Remove superfluous break.
(do_mpc_ckconv): New.
* real.h: Include mpc.h.
* toplev.c (print_version): Output MPC version info if available.
2009-05-15 Sandra Loosemore <sandra@codesourcery.com>
* fold-const.c (fold_convert_const_real_from_real): Check for
......
......@@ -58,6 +58,9 @@ along with GCC; see the file COPYING3. If not see
#ifndef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
#endif
#ifdef HAVE_mpc
static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
#endif
/* Define the names of the builtin function types and codes. */
const char *const built_in_class_names[4]
......@@ -7886,6 +7889,33 @@ fold_builtin_cosh (tree arg, tree type, tree fndecl)
return NULL_TREE;
}
/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
argument ARG. TYPE is the type of the return value. Return
NULL_TREE if no simplification can be made. */
static tree
fold_builtin_ccos (tree arg, tree type ATTRIBUTE_UNUSED, tree fndecl,
bool hyper ATTRIBUTE_UNUSED)
{
if (validate_arg (arg, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree tmp;
#ifdef HAVE_mpc
/* Calculate the result when the argument is a constant. */
if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
return tmp;
#endif
/* Optimize fn(-x) into fn(x). */
if ((tmp = fold_strip_sign_ops (arg)))
return build_call_expr (fndecl, 1, tmp);
}
return NULL_TREE;
}
/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
Return NULL_TREE if no simplification can be made. */
......@@ -7960,10 +7990,20 @@ fold_builtin_cexp (tree arg0, tree type)
{
tree rtype;
tree realp, imagp, ifn;
#ifdef HAVE_mpc
tree res;
#endif
if (!validate_arg (arg0, COMPLEX_TYPE))
if (!validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return NULL_TREE;
#ifdef HAVE_mpc
/* Calculate the result when the argument is a constant. */
if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
return res;
#endif
rtype = TREE_TYPE (TREE_TYPE (arg0));
/* In case we can figure out the real part of arg0 and it is constant zero
......@@ -9670,7 +9710,8 @@ fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max)
static tree
fold_builtin_carg (tree arg, tree type)
{
if (validate_arg (arg, COMPLEX_TYPE))
if (validate_arg (arg, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
......@@ -10215,12 +10256,14 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
return fold_builtin_abs (arg0, type);
CASE_FLT_FN (BUILT_IN_CONJ):
if (validate_arg (arg0, COMPLEX_TYPE))
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return fold_build1 (CONJ_EXPR, type, arg0);
break;
CASE_FLT_FN (BUILT_IN_CREAL):
if (validate_arg (arg0, COMPLEX_TYPE))
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));;
break;
......@@ -10230,16 +10273,49 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
break;
CASE_FLT_FN (BUILT_IN_CCOS):
return fold_builtin_ccos(arg0, type, fndecl, /*hyper=*/ false);
CASE_FLT_FN (BUILT_IN_CCOSH):
/* These functions are "even", i.e. f(x) == f(-x). */
if (validate_arg (arg0, COMPLEX_TYPE))
{
tree narg = fold_strip_sign_ops (arg0);
if (narg)
return build_call_expr (fndecl, 1, narg);
}
return fold_builtin_ccos(arg0, type, fndecl, /*hyper=*/ true);
#ifdef HAVE_mpc
CASE_FLT_FN (BUILT_IN_CSIN):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sin);
break;
CASE_FLT_FN (BUILT_IN_CSINH):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sinh);
break;
CASE_FLT_FN (BUILT_IN_CTAN):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_tan);
break;
CASE_FLT_FN (BUILT_IN_CTANH):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_tanh);
break;
CASE_FLT_FN (BUILT_IN_CLOG):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_log);
break;
CASE_FLT_FN (BUILT_IN_CSQRT):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sqrt);
break;
#endif
CASE_FLT_FN (BUILT_IN_CABS):
return fold_builtin_cabs (arg0, type, fndecl);
......@@ -10293,7 +10369,6 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
CASE_FLT_FN (BUILT_IN_COS):
return fold_builtin_cos (arg0, type, fndecl);
break;
CASE_FLT_FN (BUILT_IN_TAN):
return fold_builtin_tan (arg0, type);
......@@ -13127,6 +13202,50 @@ do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
return NULL_TREE;
}
#ifdef HAVE_mpc
/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
number and no overflow/underflow occurred. INEXACT is true if M
was not exactly calculated. TYPE is the tree type for the result.
This function assumes that you cleared the MPFR flags and then
calculated M to see if anything subsequently set a flag prior to
entering this function. Return NULL_TREE if any checks fail. */
static tree
do_mpc_ckconv (mpc_srcptr m, tree type, int inexact)
{
/* Proceed iff we get a normal number, i.e. not NaN or Inf and no
overflow/underflow occurred. If -frounding-math, proceed iff the
result of calling FUNC was exact. */
if (mpfr_number_p (MPC_RE (m)) && mpfr_number_p (MPC_IM (m))
&& !mpfr_overflow_p () && !mpfr_underflow_p ()
&& (!flag_rounding_math || !inexact))
{
REAL_VALUE_TYPE re, im;
real_from_mpfr (&re, MPC_RE (m), type, GMP_RNDN);
real_from_mpfr (&im, MPC_IM (m), type, GMP_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
check for overflow/underflow. If the REAL_VALUE_TYPE is zero
but the mpft_t is not, then we underflowed in the
conversion. */
if (real_isfinite (&re) && real_isfinite (&im)
&& (re.cl == rvc_zero) == (mpfr_zero_p (MPC_RE (m)) != 0)
&& (im.cl == rvc_zero) == (mpfr_zero_p (MPC_IM (m)) != 0))
{
REAL_VALUE_TYPE re_mode, im_mode;
real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
/* Proceed iff the specified mode can hold the value. */
if (real_identical (&re_mode, &re) && real_identical (&im_mode, &im))
return build_complex (type, build_real (TREE_TYPE (type), re_mode),
build_real (TREE_TYPE (type), im_mode));
}
}
return NULL_TREE;
}
#endif /* HAVE_mpc */
/* If argument ARG is a REAL_CST, call the one-argument mpfr function
FUNC on it and return the resulting value as a tree with type TYPE.
If MIN and/or MAX are not NULL, then the supplied ARG must be
......@@ -13523,6 +13642,52 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
return result;
}
#ifdef HAVE_mpc
/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
function FUNC on it and return the resulting value as a tree with
type TYPE. The mpfr precision is set to the precision of TYPE. We
assume that function FUNC returns zero if the result could be
calculated exactly within the requested precision. */
static tree
do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
{
tree result = NULL_TREE;
STRIP_NOPS (arg);
/* To proceed, MPFR must exactly represent the target floating point
format, which only happens when the target base equals two. */
if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE
&& REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2)
{
const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg));
const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
if (real_isfinite (re) && real_isfinite (im))
{
const struct real_format *const fmt =
REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
const int prec = fmt->p;
const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
int inexact;
mpc_t m;
mpc_init2 (m, prec);
mpfr_from_real (MPC_RE(m), re, rnd);
mpfr_from_real (MPC_IM(m), im, rnd);
mpfr_clear_flags ();
inexact = func (m, m, rnd);
result = do_mpc_ckconv (m, type, inexact);
mpc_clear (m);
}
}
return result;
}
#endif /* HAVE_mpc */
/* FIXME tuples.
The functions below provide an alternate interface for folding
builtin function calls presented as GIMPLE_CALL statements rather
......
......@@ -24,6 +24,9 @@
#ifndef GENERATOR_FILE
#include <gmp.h>
#include <mpfr.h>
#ifdef HAVE_mpc
#include <mpc.h>
#endif
#endif
#include "machmode.h"
......
......@@ -1170,8 +1170,13 @@ print_version (FILE *file, const char *indent)
N_("%s%s%s %sversion %s (%s) compiled by CC, ")
#endif
;
#ifdef HAVE_mpc
static const char fmt2[] =
N_("GMP version %s, MPFR version %s.\n");
N_("GMP version %s, MPFR version %s, MPC version %s\n");
#else
static const char fmt2[] =
N_("GMP version %s, MPFR version %s\n");
#endif
static const char fmt3[] =
N_("%s%swarning: %s header version %s differs from library version %s.\n");
static const char fmt4[] =
......@@ -1203,7 +1208,11 @@ print_version (FILE *file, const char *indent)
#endif
fprintf (file,
file == stderr ? _(fmt2) : fmt2,
GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING);
GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING
#ifdef HAVE_mpc
, MPC_VERSION_STRING
#endif
);
if (strcmp (GCC_GMP_STRINGIFY_VERSION, gmp_version))
fprintf (file,
file == stderr ? _(fmt3) : fmt3,
......@@ -1214,6 +1223,13 @@ print_version (FILE *file, const char *indent)
file == stderr ? _(fmt3) : fmt3,
indent, *indent != 0 ? " " : "",
"MPFR", MPFR_VERSION_STRING, mpfr_get_version ());
#ifdef HAVE_mpc
if (strcmp (MPC_VERSION_STRING, mpc_get_version ()))
fprintf (file,
file == stderr ? _(fmt3) : fmt3,
indent, *indent != 0 ? " " : "",
"MPC", MPC_VERSION_STRING, mpc_get_version ());
#endif
fprintf (file,
file == stderr ? _(fmt4) : fmt4,
indent, *indent != 0 ? " " : "",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment