diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2009-09-20 15:39:22 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2009-09-20 15:39:22 +0000 |
commit | ca75b926331a12b6323284f80617a6fe3afa1e38 (patch) | |
tree | 659746d75cac0bc57cdf3050c02e53c1fd81275e /gcc/builtins.c | |
parent | c4a80a2df36df59ceedcd1236dea299cba12349f (diff) | |
download | gcc-ca75b926331a12b6323284f80617a6fe3afa1e38.zip gcc-ca75b926331a12b6323284f80617a6fe3afa1e38.tar.gz gcc-ca75b926331a12b6323284f80617a6fe3afa1e38.tar.bz2 |
re PR middle-end/30789 (complex folding inexact)
PR middle-end/30789
* builtins.c (do_mpc_arg2): Accept DO_NONFINITE parameter.
(do_mpc_ckconv): Accept FORCE_CONVERT parameter.
(fold_builtin_2, do_mpc_arg1): Update accordingly.
* fold-const.c (const_binop): Likewise.
* real.h (do_mpc_arg2): Update prototype.
testsuite:
* gcc.dg/torture/builtin-math-7.c: Update for testing Annex G
cases in static initializers.
From-SVN: r151904
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 8ef9607..fddb36c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -10741,7 +10741,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE && validate_arg (arg1, COMPLEX_TYPE) && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE) - return do_mpc_arg2 (arg0, arg1, type, mpc_pow); + return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow); break; #endif @@ -13347,17 +13347,19 @@ do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact) 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. */ + entering this function. Return NULL_TREE if any checks fail, if + FORCE_CONVERT is true, then bypass the checks. */ static tree -do_mpc_ckconv (mpc_srcptr m, tree type, int inexact) +do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert) { /* 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_realref (m)) && mpfr_number_p (mpc_imagref (m)) - && !mpfr_overflow_p () && !mpfr_underflow_p () - && (!flag_rounding_math || !inexact)) + if (force_convert + || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m)) + && !mpfr_overflow_p () && !mpfr_underflow_p () + && (!flag_rounding_math || !inexact))) { REAL_VALUE_TYPE re, im; @@ -13367,16 +13369,19 @@ do_mpc_ckconv (mpc_srcptr m, tree type, int inexact) 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_realref (m)) != 0) - && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)) + if (force_convert + || (real_isfinite (&re) && real_isfinite (&im) + && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0) + && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (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)) + if (force_convert + || (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)); } @@ -13819,7 +13824,7 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t)) mpfr_from_real (mpc_imagref(m), im, rnd); mpfr_clear_flags (); inexact = func (m, m, crnd); - result = do_mpc_ckconv (m, type, inexact); + result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0); mpc_clear (m); } } @@ -13831,11 +13836,13 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t)) 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. */ + could be calculated exactly within the requested precision. If + DO_NONFINITE is true, then fold expressions containing Inf or NaN + in the arguments and/or results. */ #ifdef HAVE_mpc tree -do_mpc_arg2 (tree arg0, tree arg1, tree type, +do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite, int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t)) { tree result = NULL_TREE; @@ -13856,8 +13863,9 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1)); const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1)); - if (real_isfinite (re0) && real_isfinite (im0) - && real_isfinite (re1) && real_isfinite (im1)) + if (do_nonfinite + || (real_isfinite (re0) && real_isfinite (im0) + && real_isfinite (re1) && real_isfinite (im1))) { const struct real_format *const fmt = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type))); @@ -13875,7 +13883,7 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, mpfr_from_real (mpc_imagref(m1), im1, rnd); mpfr_clear_flags (); inexact = func (m0, m0, m1, crnd); - result = do_mpc_ckconv (m0, type, inexact); + result = do_mpc_ckconv (m0, type, inexact, do_nonfinite); mpc_clear (m0); mpc_clear (m1); } |