aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2009-09-20 15:39:22 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2009-09-20 15:39:22 +0000
commitca75b926331a12b6323284f80617a6fe3afa1e38 (patch)
tree659746d75cac0bc57cdf3050c02e53c1fd81275e /gcc/builtins.c
parentc4a80a2df36df59ceedcd1236dea299cba12349f (diff)
downloadgcc-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.c40
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);
}