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
This commit is contained in:
Kaveh R. Ghazi 2009-09-20 15:39:22 +00:00 committed by Kaveh Ghazi
parent c4a80a2df3
commit ca75b92633
6 changed files with 73 additions and 24 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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
{

View File

@ -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

View File

@ -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.

View File

@ -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;
}