mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-11 13:33:52 +08:00
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:
parent
c4a80a2df3
commit
ca75b92633
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user