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]

Re: [PATCH take 2]: Integrate GCC with the complex math library MPC (middle-end)


On Fri, May 15, 2009 at 6:01 PM, Kaveh R. GHAZI <ghazi@caip.rutgers.edu> wrote:
> This patch is "take 2" of the middle-end bits for the MPC integration
> originally posted and explained here:
> http://gcc.gnu.org/ml/gcc-patches/2009-03/msg00672.html
>
> The only change from the last patch iteration is a one-line bugfix for the
> enumeration type of the "rnd" variable:
>
> < + ? ? ? const mpc_rnd_t rnd = fmt->round_towards_zero ? (MPC_RNDZZ) : (MPC_RNDNN);
> ---
>> + ? ? ? const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
>
> I accidentally used an MPC enum where an MPFR one was actually needed.
> Chalk one up for the new -Wc++-compat warnings!
>
> Tested in conjunction with the MPC configury patch, no regressions.
>
> Note: it's safe to install this patch separately from the other MPC bits.
>
> Okay for mainline?

What about testcases?  (It will be of course interesting with
"optional" stuff ...)

Richard.

> ? ? ? ? ? ? ? ?Thanks,
> ? ? ? ? ? ? ? ?--Kaveh
>
>
> 2009-03-12 ?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.
>
> diff -rup orig/egcc-SVN20090514/gcc/builtins.c egcc-SVN20090514/gcc/builtins.c
> --- orig/egcc-SVN20090514/gcc/builtins.c ? ? ? ?2009-05-06 02:01:25.000000000 +0200
> +++ egcc-SVN20090514/gcc/builtins.c ? ? 2009-05-15 08:01:43.000000000 +0200
> @@ -58,6 +58,9 @@ along with GCC; see the file COPYING3.
> ?#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,
> ? 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
> ?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,
> ? ? ? 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,
> ? ? 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,
>
> ? ? 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
> ? 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,
> ? 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
> diff -rup orig/egcc-SVN20090514/gcc/real.h egcc-SVN20090514/gcc/real.h
> --- orig/egcc-SVN20090514/gcc/real.h ? ?2009-04-23 02:00:52.000000000 +0200
> +++ egcc-SVN20090514/gcc/real.h 2009-05-15 07:47:52.000000000 +0200
> @@ -24,6 +24,9 @@
> ?#ifndef GENERATOR_FILE
> ?#include <gmp.h>
> ?#include <mpfr.h>
> +#ifdef HAVE_mpc
> +#include <mpc.h>
> +#endif
> ?#endif
> ?#include "machmode.h"
>
> diff -rup orig/egcc-SVN20090514/gcc/toplev.c egcc-SVN20090514/gcc/toplev.c
> --- orig/egcc-SVN20090514/gcc/toplev.c ?2009-05-09 06:30:24.000000000 +0200
> +++ egcc-SVN20090514/gcc/toplev.c ? ? ? 2009-05-15 07:47:52.000000000 +0200
> @@ -1170,8 +1170,13 @@ print_version (FILE *file, const char *i
> ? ? 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 *i
> ?#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 *i
> ? ? ? ? ? ? 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 ? " " : "",
>


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