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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/builtins.c | 40 | ||||
-rw-r--r-- | gcc/fold-const.c | 8 | ||||
-rw-r--r-- | gcc/real.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/builtin-math-7.c | 33 |
6 files changed, 73 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb7dc70..af2d02c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-09-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + 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. + 2009-09-20 Jan Hubicka <jh@suse.cz> * dwarf2out.c (add_const_value_attribute): Return true if successful. 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); } diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1ce0013..34e47c1 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1974,7 +1974,9 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) case MULT_EXPR: #ifdef HAVE_mpc if (COMPLEX_FLOAT_TYPE_P (type)) - return do_mpc_arg2 (arg1, arg2, type, mpc_mul); + return do_mpc_arg2 (arg1, arg2, type, + /* do_nonfinite= */ folding_initializer, + mpc_mul); #endif real = const_binop (MINUS_EXPR, @@ -1990,7 +1992,9 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) case RDIV_EXPR: #ifdef HAVE_mpc if (COMPLEX_FLOAT_TYPE_P (type)) - return do_mpc_arg2 (arg1, arg2, type, mpc_div); + return do_mpc_arg2 (arg1, arg2, type, + /* do_nonfinite= */ folding_initializer, + mpc_div); #endif { @@ -27,7 +27,7 @@ #ifdef HAVE_mpc #include <mpc.h> # ifdef HAVE_mpc -extern tree do_mpc_arg2 (tree, tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t)); +extern tree do_mpc_arg2 (tree, tree, tree, int, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t)); # endif # if MPC_VERSION >= MPC_VERSION_NUM(0,6,1) # define HAVE_mpc_pow diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6481b99..127d213 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-09-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * gcc.dg/torture/builtin-math-7.c: Update for testing Annex G + cases in static initializers. + 2009-09-20 Kai Tietz <kai.tietz@onevision.com> * gcc.c-tortue/compile/pr39886.c: New. diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-7.c b/gcc/testsuite/gcc.dg/torture/builtin-math-7.c index edd82e0..0d6307d 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-7.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-7.c @@ -5,7 +5,7 @@ Origin: Kaveh R. Ghazi, August 13, 2009. */ /* { dg-do run } */ -/* { dg-require-effective-target mpc } */ +/* { dg-require-effective-target mpc_pow } */ /* { dg-add-options ieee } */ extern void link_error(int); @@ -16,23 +16,43 @@ extern void link_error(int); link_error(__LINE__); \ } while (0) +/* Use this error function for cases which only evaluate at + compile-time when optimizing. */ +#ifdef __OPTIMIZE__ +# define ERROR_FUNC(X) link_error(X) +#else +# define ERROR_FUNC(X) __builtin_abort() +#endif + +/* Evaluate this expression at compile-time using static initializers. */ +#define STATICINIT_TESTIT(TYPE,X,OP,Y,RES) do { \ + static const _Complex TYPE foo = (_Complex TYPE)(X) OP (_Complex TYPE)(Y); \ + if (foo != (_Complex TYPE)(RES)) \ + ERROR_FUNC (__LINE__); \ +} while (0) + /* Evaluate this expression at runtime. */ #define RUNTIME_TESTIT(TYPE,X,OP,Y,RES) do { \ - volatile _Complex TYPE foo = (_Complex TYPE)(X); \ + volatile _Complex TYPE foo; \ + foo = (_Complex TYPE)(X); \ foo OP##= (_Complex TYPE)(Y); \ - if (foo != (_Complex TYPE)(RES)) __builtin_abort(); \ + if (foo != (_Complex TYPE)(RES)) \ + __builtin_abort(); \ } while (0) /* Evaluate this expression at compile-time and runtime. */ #define TESTIT(TYPE,X,OP,Y,RES) do { \ + STATICINIT_TESTIT(TYPE,X,OP,Y,RES); \ COMPILETIME_TESTIT(TYPE,X,OP,Y,RES); \ RUNTIME_TESTIT(TYPE,X,OP,Y,RES); \ } while (0) /* Either the real or imaginary parts should be infinity. */ #define TEST_ONE_PART_INF(VAL) do { \ - if (! __builtin_isinf(__real (VAL)) \ - && ! __builtin_isinf(__imag (VAL))) \ + static const _Complex double foo = (VAL); \ + if (! __builtin_isinf(__real foo) && ! __builtin_isinf(__imag foo)) \ + ERROR_FUNC (__LINE__); \ + if (! __builtin_isinf(__real (VAL)) && ! __builtin_isinf(__imag (VAL))) \ __builtin_abort(); \ } while (0) @@ -71,5 +91,8 @@ int main() TEST_ONE_PART_INF ((_Complex double)1 / (_Complex double)0); TEST_ONE_PART_INF ((VAL1) / (_Complex double)1); + RUNTIME_TESTIT (double, 1, /, VAL1, 0); + STATICINIT_TESTIT (double, 1, /, VAL1, 0); + return 0; } |