diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb7dc70f2831..af2d02cb580e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-09-20 Kaveh R. Ghazi + + 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 * dwarf2out.c (add_const_value_attribute): Return true if successful. diff --git a/gcc/builtins.c b/gcc/builtins.c index 8ef96070c3ad..fddb36c7a4d0 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 1ce0013ef354..34e47c19e79c 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 { diff --git a/gcc/real.h b/gcc/real.h index c93435b2524c..e72723e01ea3 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -27,7 +27,7 @@ #ifdef HAVE_mpc #include # 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 6481b993bea4..127d213d7997 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-09-20 Kaveh R. Ghazi + + * gcc.dg/torture/builtin-math-7.c: Update for testing Annex G + cases in static initializers. + 2009-09-20 Kai Tietz * 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 edd82e032fa6..0d6307d653b5 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; }